bin/magento setup:upgrade 停在某个模块几分钟没有输出,不一定真的死锁。大表 DDL、数据补丁或搜索引擎操作可能很慢。先用另一个终端取证,不要连续按 Ctrl+C 后重复执行。
确认进程是否还在工作
pgrep -af 'bin/magento setup:upgrade'
ps -o pid,etime,%cpu,%mem,state,cmd -p PID
cat /proc/PID/io
ls -l /proc/PID/fd | head
CPU、I/O 或数据库查询在变化,任务可能仍推进;进程处于长时间睡眠且数据库无对应活动,再查外部连接和锁。
MySQL 正在执行什么
mysql -e 'SHOW FULL PROCESSLIST'
mysql -e 'SHOW ENGINE INNODB STATUSG'
SELECT * FROM performance_schema.metadata_locks
WHERE LOCK_STATUS = 'PENDING';
Waiting for table metadata lock 常由未提交事务、后台导出或长查询阻塞 DDL。找出持有者的业务用途,确认后再终止;不能看到运行久就 kill。
定位执行到哪个 Patch
SELECT patch_name FROM patch_list ORDER BY patch_name;
grep -R "class .* implements.*Patch" app/code/Vendor/Module/Setup/Patch
tail -f var/log/system.log var/log/exception.log
自定义 Data Patch 若一次加载全表、每行调用 Repository 或访问外部 API,可能数小时不输出。应改为稳定游标分批、记录进度,并保证重复执行安全。Patch 中不要调用不可控的远程服务。
终止前先判断 DDL 状态
MySQL 正在 ALTER 大表时强制终止可能触发长时间回滚或残留临时表。记录 SQL、表大小、数据库版本和执行时间,评估在线 DDL 能力。生产环境应在维护窗口执行,并准备可验证的数据库备份。
安全恢复流程
# 确认旧进程已退出后再运行
pgrep -af 'bin/magento setup:upgrade'
bin/magento maintenance:enable
bin/magento setup:upgrade -vvv
bin/magento setup:di:compile
bin/magento cache:clean
bin/magento maintenance:disable
不要手工向 patch_list 插入 Patch 名称来“跳过”。那只会告诉 Magento 已执行,却没有完成数据修改。失败 Patch 必须修成可重入,或从已验证备份恢复后重跑。
升级完成后核对模块版本、表结构、Patch 记录、Cron、Indexer 和核心下单流程。命令返回 0 不代表业务数据一定迁移正确。
给每个自定义 Patch 增加可观察性
大数据迁移应按批次输出已处理主键范围和耗时,但不能输出客户敏感字段。使用 startSetup/endSetup 不能自动解决长事务;批量提交策略要根据 Patch 是否允许中断恢复设计。为 Patch 建立独立测试数据,至少覆盖首次执行、中途失败后重跑、空数据和大批量四种情况。
升级前先估算大表
SELECT table_name, table_rows,
ROUND((data_length+index_length)/1024/1024) AS mb
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY data_length+index_length DESC
LIMIT 20;
预发布数据量远小于生产时,DDL 时间没有参考意义。使用接近生产规模的副本演练并记录回滚时间,发布计划才知道何时应该继续等待、何时回退。

