mysql升级过程中如何防止死锁_mysql并发安全措施

来源:这里教程网 时间:2026-02-28 20:52:14 作者:

升级时为什么容易触发死锁 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

相关推荐