0 才执行,0 = 永久跳过) if ($rawDays > 0) { $rawDeleted = $this->cleanRawTable($rawDays); } // 4. stat 表清理(statDays > 0 才执行,0 = 永久跳过) if ($statDays > 0) { $statDeleted = $this->cleanStatTables($statDays); } return json_encode([ 'raw_deleted' => $rawDeleted, 'stat_deleted' => $statDeleted, ], JSON_UNESCAPED_UNICODE); } /** * 分批清理 raw 表 ul_nginx_access_log. * * 时间阈值基于 time_local(nginx 记录的请求时间戳),不是 create_time(入库时间)。 * 每批 5000 行 + usleep 100ms,避免长事务锁表。 * * @param int $rawDays 保留天数(>0) * @return int 累计删除行数 */ protected function cleanRawTable(int $rawDays): int { $threshold = time() - ($rawDays * 86400); $total = 0; Log::info("nginx_log_clean: raw 阈值 time_local<" . date('Y-m-d H:i:s', $threshold) . " ({$rawDays} 天)"); // 循环分批 DELETE:每批 limit 5000,直到该阈值区间内无残留 while (true) { // Db::name 自动加表前缀;limit 保证单次 DELETE 行数可控 $deleted = Db::name('nginx_access_log') ->where('time_local', '<', $threshold) ->limit(self::RAW_BATCH_SIZE) ->delete(); if ($deleted <= 0) { break; } $total += $deleted; // 批次间休眠,降低 DB 压力(避免主从延迟) if ($deleted === self::RAW_BATCH_SIZE) { usleep(self::RAW_BATCH_USLEEP); } else { // 末批(< 5000)说明已清完该阈值区间 break; } } Log::info("nginx_log_clean: raw 删除 {$total} 行"); return $total; } /** * 清理 4 张 stat 表(按 stat_date). * * stat_date 是 YYYYMMDD 整数(如 20260728),不是 Unix 时间戳。 * - stat 表一行 = 一天的聚合(stat_hour 按小时拆,但 stat_date 仍是当天 YYYYMMDD) * - 阈值用 (int) date('Ymd', strtotime('today') - statDays*86400)(同为 YYYYMMDD 格式) * 保证整天边界,不会误删"今天聚合了 N 小时但今天整体还没过期"的数据 * * 各表独立 DELETE,不做级联(如 stat_url 不依赖 stat_hour,可单独保留)。 * * @param int $statDays 保留天数(>0) * @return int 累计删除行数(4 张表合计) */ protected function cleanStatTables(int $statDays): int { // strtotime('today') 返回当天 0 点时间戳;转 YYYYMMDD 整数与 stat_date 对齐 $threshold = (int) date('Ymd', strtotime('today') - ($statDays * 86400)); $total = 0; Log::info("nginx_log_clean: stat 阈值 stat_date<{$threshold} ({$statDays} 天)"); foreach (self::STAT_TABLES as $table) { $deleted = Db::name($table) ->where('stat_date', '<', $threshold) ->delete(); $total += $deleted; if ($deleted > 0) { Log::info("nginx_log_clean: {$table} 删除 {$deleted} 行"); } } Log::info("nginx_log_clean: stat 合计删除 {$total} 行"); return $total; } }