|
|
@@ -97,73 +97,141 @@ class SaltController extends Controller
|
|
|
|
|
|
/**
|
|
|
* 补充 xhClear 结账单历史数据的 salt 字段
|
|
|
- * 职责:查询全部 xhClear 记录,循环重新生成并设置 salt
|
|
|
+ * 职责:利用主键游标进行分页查询,分批重新生成并设置 salt,确保线上大表安全
|
|
|
*/
|
|
|
public function actionFillClear()
|
|
|
{
|
|
|
$db = Yii::$app->db;
|
|
|
- // 查询全部结账单 ID
|
|
|
- $ids = $db->createCommand("SELECT id FROM xhClear ORDER BY id DESC")->queryColumn();
|
|
|
- $count = 0;
|
|
|
- foreach ($ids as $id) {
|
|
|
- // 支持 limit 参数限制更新数量
|
|
|
- if ($this->limit > 0 && $count >= $this->limit) {
|
|
|
+ $this->stdout("开始分页重新设置 xhClear 表的 salt 字段...\n");
|
|
|
+
|
|
|
+ $processed = 0;
|
|
|
+ $lastId = null;
|
|
|
+ $batchSize = $this->batchSize > 0 ? $this->batchSize : 1000;
|
|
|
+
|
|
|
+ while (true) {
|
|
|
+ // 如果设置了 limit 且已达到上限,则退出
|
|
|
+ if ($this->limit > 0 && $processed >= $this->limit) {
|
|
|
break;
|
|
|
}
|
|
|
- if ($this->dryRun) {
|
|
|
- $this->stdout("[dry-run] xhClear id={$id}\n");
|
|
|
- $count++;
|
|
|
- continue;
|
|
|
+
|
|
|
+ // 计算当前批次需要查询的数量
|
|
|
+ $currentBatchSize = $batchSize;
|
|
|
+ if ($this->limit > 0) {
|
|
|
+ $currentBatchSize = min($batchSize, $this->limit - $processed);
|
|
|
}
|
|
|
- // 重新生成 10 位随机 salt 并更新
|
|
|
- $salt = stringUtil::charsShuffleLowerCase(10);
|
|
|
- $db->createCommand("UPDATE xhClear SET salt = :salt WHERE id = :id")
|
|
|
- ->bindValues([':salt' => $salt, ':id' => $id])
|
|
|
- ->execute();
|
|
|
- $count++;
|
|
|
-
|
|
|
- // 支持 sleepMs 降低数据库压力
|
|
|
- if ($this->sleepMs > 0) {
|
|
|
- usleep($this->sleepMs * 1000);
|
|
|
+
|
|
|
+ // 使用主键游标分页查询 ID(利用主键索引,性能极高,避免大表全表扫描)
|
|
|
+ if ($lastId === null) {
|
|
|
+ $ids = $db->createCommand("SELECT id FROM xhClear ORDER BY id DESC LIMIT :limit")
|
|
|
+ ->bindValue(':limit', $currentBatchSize)
|
|
|
+ ->queryColumn();
|
|
|
+ } else {
|
|
|
+ $ids = $db->createCommand("SELECT id FROM xhClear WHERE id < :lastId ORDER BY id DESC LIMIT :limit")
|
|
|
+ ->bindValues([':lastId' => $lastId, ':limit' => $currentBatchSize])
|
|
|
+ ->queryColumn();
|
|
|
}
|
|
|
+
|
|
|
+ if (empty($ids)) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 循环更新当前批次的记录
|
|
|
+ foreach ($ids as $id) {
|
|
|
+ if ($this->dryRun) {
|
|
|
+ $this->stdout("[dry-run] xhClear id={$id}\n");
|
|
|
+ $processed++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重新生成 10 位随机 salt 并更新
|
|
|
+ $salt = stringUtil::charsShuffleLowerCase(10);
|
|
|
+ $db->createCommand("UPDATE xhClear SET salt = :salt WHERE id = :id")
|
|
|
+ ->bindValues([':salt' => $salt, ':id' => $id])
|
|
|
+ ->execute();
|
|
|
+ $processed++;
|
|
|
+
|
|
|
+ // 每次更新后休眠,降低数据库写入压力
|
|
|
+ if ($this->sleepMs > 0) {
|
|
|
+ usleep($this->sleepMs * 1000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新游标为当前批次中最小的 ID
|
|
|
+ $lastId = min($ids);
|
|
|
+ $this->stdout("xhClear 已处理 {$processed} 条记录,当前 ID 游标: {$lastId}\n");
|
|
|
}
|
|
|
- $this->stdout("xhClear salt 全部重新设置完成,共处理 {$count} 条记录\n");
|
|
|
+
|
|
|
+ $this->stdout("xhClear salt 全部重新设置完成,共处理 {$processed} 条记录\n");
|
|
|
return ExitCode::OK;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 补充 xhSettle 结算单历史数据的 salt 字段
|
|
|
- * 职责:查询全部 xhSettle 记录,循环重新生成并设置 salt
|
|
|
+ * 职责:利用主键游标进行分页查询,分批重新生成并设置 salt,确保线上大表安全
|
|
|
*/
|
|
|
public function actionFillSettle()
|
|
|
{
|
|
|
$db = Yii::$app->db;
|
|
|
- // 查询全部结算单 ID
|
|
|
- $ids = $db->createCommand("SELECT id FROM xhSettle ORDER BY id DESC")->queryColumn();
|
|
|
- $count = 0;
|
|
|
- foreach ($ids as $id) {
|
|
|
- // 支持 limit 参数限制更新数量
|
|
|
- if ($this->limit > 0 && $count >= $this->limit) {
|
|
|
+ $this->stdout("开始分页重新设置 xhSettle 表的 salt 字段...\n");
|
|
|
+
|
|
|
+ $processed = 0;
|
|
|
+ $lastId = null;
|
|
|
+ $batchSize = $this->batchSize > 0 ? $this->batchSize : 1000;
|
|
|
+
|
|
|
+ while (true) {
|
|
|
+ // 如果设置了 limit 且已达到上限,则退出
|
|
|
+ if ($this->limit > 0 && $processed >= $this->limit) {
|
|
|
break;
|
|
|
}
|
|
|
- if ($this->dryRun) {
|
|
|
- $this->stdout("[dry-run] xhSettle id={$id}\n");
|
|
|
- $count++;
|
|
|
- continue;
|
|
|
+
|
|
|
+ // 计算当前批次需要查询的数量
|
|
|
+ $currentBatchSize = $batchSize;
|
|
|
+ if ($this->limit > 0) {
|
|
|
+ $currentBatchSize = min($batchSize, $this->limit - $processed);
|
|
|
}
|
|
|
- // 重新生成 10 位随机 salt 并更新
|
|
|
- $salt = stringUtil::charsShuffleLowerCase(10);
|
|
|
- $db->createCommand("UPDATE xhSettle SET salt = :salt WHERE id = :id")
|
|
|
- ->bindValues([':salt' => $salt, ':id' => $id])
|
|
|
- ->execute();
|
|
|
- $count++;
|
|
|
-
|
|
|
- // 支持 sleepMs 降低数据库压力
|
|
|
- if ($this->sleepMs > 0) {
|
|
|
- usleep($this->sleepMs * 1000);
|
|
|
+
|
|
|
+ // 使用主键游标分页查询 ID(利用主键索引,性能极高,避免大表全表扫描)
|
|
|
+ if ($lastId === null) {
|
|
|
+ $ids = $db->createCommand("SELECT id FROM xhSettle ORDER BY id DESC LIMIT :limit")
|
|
|
+ ->bindValue(':limit', $currentBatchSize)
|
|
|
+ ->queryColumn();
|
|
|
+ } else {
|
|
|
+ $ids = $db->createCommand("SELECT id FROM xhSettle WHERE id < :lastId ORDER BY id DESC LIMIT :limit")
|
|
|
+ ->bindValues([':lastId' => $lastId, ':limit' => $currentBatchSize])
|
|
|
+ ->queryColumn();
|
|
|
}
|
|
|
+
|
|
|
+ if (empty($ids)) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 循环更新当前批次的记录
|
|
|
+ foreach ($ids as $id) {
|
|
|
+ if ($this->dryRun) {
|
|
|
+ $this->stdout("[dry-run] xhSettle id={$id}\n");
|
|
|
+ $processed++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重新生成 10 位随机 salt 并更新
|
|
|
+ $salt = stringUtil::charsShuffleLowerCase(10);
|
|
|
+ $db->createCommand("UPDATE xhSettle SET salt = :salt WHERE id = :id")
|
|
|
+ ->bindValues([':salt' => $salt, ':id' => $id])
|
|
|
+ ->execute();
|
|
|
+ $processed++;
|
|
|
+
|
|
|
+ // 每次更新后休眠,降低数据库写入压力
|
|
|
+ if ($this->sleepMs > 0) {
|
|
|
+ usleep($this->sleepMs * 1000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新游标为当前批次中最小的 ID
|
|
|
+ $lastId = min($ids);
|
|
|
+ $this->stdout("xhSettle 已处理 {$processed} 条记录,当前 ID 游标: {$lastId}\n");
|
|
|
}
|
|
|
- $this->stdout("xhSettle salt 全部重新设置完成,共处理 {$count} 条记录\n");
|
|
|
+
|
|
|
+ $this->stdout("xhSettle salt 全部重新设置完成,共处理 {$processed} 条记录\n");
|
|
|
return ExitCode::OK;
|
|
|
}
|
|
|
|