runFill([ 'xhGhsOrder' => GhsOrder::tableName(), 'xhCg' => Purchase::tableName(), ]); } /** * 仅补充 xhGhsOrder */ public function actionFillGhsOrder() { return $this->runFill([ 'xhGhsOrder' => GhsOrder::tableName(), ]); } /** * 仅补充 xhCg */ public function actionFillCg() { return $this->runFill([ 'xhCg' => Purchase::tableName(), ]); } private function runFill(array $tables) { ini_set('memory_limit', '512M'); set_time_limit(0); if ($this->batchSize < 1) { $this->stderr("batchSize 必须大于 0\n"); return ExitCode::UNSPECIFIED_ERROR; } $exitCode = ExitCode::OK; foreach ($tables as $label => $tableName) { $code = $this->fillTable($label, $tableName); if ($code !== ExitCode::OK) { $exitCode = $code; } } return $exitCode; } private function fillTable($label, $tableName) { $db = Yii::$app->db; $remaining = (int)$db->createCommand( "SELECT COUNT(*) FROM {$tableName} WHERE salt = ''" )->queryScalar(); $this->stdout("{$label}({$tableName}) 待补充: {$remaining}\n"); if ($remaining === 0) { return ExitCode::OK; } $processed = 0; $maxProcess = $this->limit > 0 ? min($this->limit, $remaining) : $remaining; $lastId = 0; while ($processed < $maxProcess) { $batchLimit = min($this->batchSize, $maxProcess - $processed); $rows = $db->createCommand( "SELECT id FROM {$tableName} WHERE salt = '' AND id > :lastId ORDER BY id ASC LIMIT {$batchLimit}" )->bindValue(':lastId', $lastId)->queryColumn(); if (empty($rows)) { break; } foreach ($rows as $id) { $id = (int)$id; $lastId = $id; if ($this->dryRun) { $this->stdout("[dry-run] {$label} id={$id}\n"); $processed++; continue; } $salt = stringUtil::charsShuffleLowerCase(10); $affected = $db->createCommand( "UPDATE {$tableName} SET salt = :salt WHERE id = :id AND salt = ''" )->bindValues([ ':salt' => $salt, ':id' => $id, ])->execute(); if ($affected > 0) { $processed++; } } $this->stdout("{$label} 已处理 {$processed}/{$maxProcess}\n"); if ($this->sleepMs > 0 && $processed < $maxProcess) { usleep($this->sleepMs * 1000); } } $left = (int)$db->createCommand( "SELECT COUNT(*) FROM {$tableName} WHERE salt = ''" )->queryScalar(); $this->stdout("{$label} 完成,本次处理 {$processed} 条,剩余 {$left} 条\n"); return ExitCode::OK; } }