cron_schedule 达到数百万行时,常见现象是 Cron 扫描变慢、锁等待增加、后台任务延迟。直接 truncate 会丢失正在排队和失败任务的证据,应先看增长来自哪种状态与哪个 job_code。
统计规模与最老记录
SELECT COUNT(*) rows_count, MIN(created_at), MAX(created_at) FROM cron_schedule;
SELECT status, COUNT(*) cnt, MIN(scheduled_at) oldest
FROM cron_schedule GROUP BY status ORDER BY cnt DESC;
SELECT job_code, status, COUNT(*) cnt
FROM cron_schedule GROUP BY job_code,status ORDER BY cnt DESC LIMIT 30;
pending 持续堆积表示消费者没有按时运行;success 占绝大多数但多年未清理,才是历史生命周期问题。大量 running 旧记录要先确认对应 PID 是否存在。
检查 Cron 与清理配置
php bin/magento cron:run --group default -vvv
ps -ef | grep '[b]in/magento cron:run'
php bin/magento config:show system/cron/default/history_success_lifetime
php bin/magento config:show system/cron/default/history_failure_lifetime
不同 cron group 可有独立配置。系统 crontab 应每分钟触发,且文件所有者、PHP 版本和 Magento CLI 一致。检查日志中是否有 history_cleanup 或数据库死锁异常。
清理要分批并保留失败证据
先备份失败任务摘要,再在维护窗口按主键小批删除过期 success/missed/error 记录。不要一次删除数百万行,否则会产生长事务与大量 undo。
SELECT schedule_id, job_code, status, messages, scheduled_at, executed_at
FROM cron_schedule WHERE status IN ('error','missed')
ORDER BY schedule_id DESC LIMIT 200;
DELETE FROM cron_schedule
WHERE status='success' AND finished_at < UTC_TIMESTAMP() - INTERVAL 7 DAY
ORDER BY schedule_id LIMIT 5000;
重复执行前观察复制延迟和锁等待。删除后根据表空间策略决定是否 OPTIMIZE;生产高峰期不要盲目重建大表。
防止再次增长
连续三天记录总行数、每日新增量、最老 pending 与清理耗时。清理 Job 每轮能覆盖新增量、pending 不跨越预期周期、Cron 运行时间稳定,才算治理完成。
生产环境操作前的检查
针对“Magento 2 cron_schedule 表越来越大”进行处理时,先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT;需要 UPDATE、DELETE、补偿命令或目录删除时,必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、app/etc/env.php 摘要和当前流量节点,避免只修复其中一台。
php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status
命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务;若涉及数据库结构、库存、支付或订单,先在脱敏的生产数据副本验证,再安排维护窗口。
建立可比较的排查记录
每次实验只改变一个变量,并保存“操作前值、执行命令、开始时间、结束时间、结果、回滚方式”。至少准备一个正常对象和一个异常对象作对照,例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复,而新建对象仍会复现,说明根因尚未消除。
| 检查点 | 需要记录 | 通过标准 |
|---|---|---|
| 数据层 | 主键、Store/Website、更新时间、关联行数 | 关系完整且无孤儿记录 |
| 应用层 | 异常堆栈、模块、Cron/消费者状态 | 无新异常并可重复执行 |
| 缓存与索引 | 索引模式、版本、源站和公网响应 | 按预期周期自动更新 |
| 业务回归 | 正常路径、失败路径、重复请求 | 结果一致且没有重复副作用 |
修复后的观察窗口
上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期,并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项;确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息,采集时要脱敏,问题结束后及时关闭。

