mysql跨大版本升级易触发死锁,因其需持mdl写锁执行系统表重构等操作,与业务dml形成锁等待环路;停机升级须断连、停监控、刷脏页;仅小版本支持在线升级。

升级时为什么容易触发死锁
MySQL 升级(尤其是跨大版本,如 5.7 → 8.0)常伴随元数据锁(MDL)变更、系统表重构、InnoDB 字典缓存刷新等隐式操作。这些操作会持有全局或表级 MDL 写锁,而业务 SQL 若正在执行 SELECT ... FOR UPDATE、INSERT ... ON DUPLICATE KEY UPDATE 或长事务中的 DML,就极易与升级脚本的 DDL(如 ALTER TABLE mysql.user)形成锁等待环路。典型错误日志里会出现:Deadlock found when trying to get lock; try restarting transaction。
关键点在于:升级不是纯只读操作,它本身是高权限、高侵入性的 DDL 批处理,和业务并发天然冲突。
停机窗口内必须做的三件事
- 确保所有应用连接已断开,且无残留事务:SELECT * FROM information_schema.INNODB_TRX; 返回空结果后再开始升级
- 关闭监控/备份工具的自动采集(如 Percona Toolkit 的 pt-heartbeat、pt-table-checksum),它们可能在后台发起 SELECT 并持有 MDL 读锁
- 用 SET GLOBAL innodb_fast_shutdown = 0; 确保 InnoDB 彻底刷脏页和清理缓冲池,避免升级时因恢复逻辑异常加锁
不停服升级时的并发控制手段
真正支持“在线”升级的只有小版本(如 8.0.32 → 8.0.33),且需满足:二进制日志格式为 ROW、主从复制延迟 LOCK TABLES 操作。此时仍需主动限流:
- 对业务端启用连接层熔断(如 ProxySQL 的
mysql-users.active = 0 临时下线写流量)
- 使用
pt-online-schema-change 替换原生 ALTER(仅适用于用户表,不适用于系统表升级)
- 监控
SHOW PROCESSLIST 中状态为 Waiting for table metadata lock 的线程数,超过 3 个立即中止升级流程
8.0 升级后最容易被忽略的锁风险点
MySQL 8.0 引入了原子 DDL 日志(mysql.ibd + ddl_log 表),但该机制依赖 innodb_redo_log_capacity 和磁盘 I/O 稳定性。若升级后立即执行大量并发 CREATE TABLE,可能因 redo 日志切换卡住 MDL,表现为新表创建 hang 住,进而阻塞后续所有 DML。建议升级后首小时禁用自动化建表任务,并检查 SHOW ENGINE INNODB STATUS 中的 LOG 部分是否有 pending log writes。
ROW、主从复制延迟 LOCK TABLES 操作。此时仍需主动限流:
- 对业务端启用连接层熔断(如 ProxySQL 的
mysql-users.active = 0临时下线写流量) - 使用
pt-online-schema-change替换原生ALTER(仅适用于用户表,不适用于系统表升级) - 监控
SHOW PROCESSLIST中状态为Waiting for table metadata lock的线程数,超过 3 个立即中止升级流程










