MySQL 5.7 升级到 8.0 后,默认隔离级别虽仍为 REPEATABLE READ,但锁行为收紧、一致性读边界更严格,需通过 performance_schema.data_locks 和 SHOW ENGINE INNODB STATUS 验证实际锁类型与快照点稳定性,而非仅依赖 @@transaction_isolation 变量值。

MySQL 5.7 升级到 8.0 后,REPEATABLE READ 仍是默认隔离级别,但锁行为和一致性读边界已实质收紧——不能只查变量值,必须验证真实执行效果。
查 @@transaction_isolation 只是起点,不是结论
执行 SELECT @@transaction_isolation; 返回 REPEATABLE-READ 是正常的,这仅说明会话变量没被覆盖;但它不反映事务启动时的真实行为,也不代表锁范围没变。尤其要注意:
- ORM(如 Django、MyBatis)可能在连接建立时悄悄执行
SET SESSION TRANSACTION ISOLATION LEVEL ...,覆盖配置文件设置 - 事务内用
SET TRANSACTION ISOLATION LEVEL READ COMMITTED临时改级别后,SELECT @@transaction_isolation仍返回会话初始值,无法捕获运行时变更 - 若用
SELECT @@tx_isolation;(5.7 变量名),在 8.0 会直接报错Unknown system variable 'tx_isolation'
验证锁行为:用 performance_schema.data_locks 看实际加了什么锁
这才是判断升级是否影响业务的关键。在测试环境模拟典型并发操作(比如“查-算-更”流程),然后立即查锁:
- 先确认
performance_schema已启用:SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'performance_schema';返回ON - 执行并发事务后,查当前活跃事务持有的锁:
SELECT ENGINE_TRANSACTION_ID, OBJECT_SCHEMA, OBJECT_NAME, INDEX_NAME, LOCK_TYPE, LOCK_MODE, LOCK_DATA FROM performance_schema.data_locks WHERE THREAD_ID IN (SELECT THREAD_ID FROM performance_schema.threads WHERE PROCESSLIST_COMMAND = 'Sleep'); - 重点对比:相同
WHERE non_unique_col = ?查询,在 5.7 可能只显示RECORD锁,在 8.0 很可能多出GENERIC或INSERT_INTENTION类型,且LOCK_MODE是NEXT-KEY而非RECORD
验证一致性读边界:用 SHOW ENGINE INNODB STATUS\G 观察快照点
隔离级别语义靠 MVCC 实现,而快照点(read view)生成时机在 8.0 更严格。重点关注:
- 执行一个长事务(比如开事务后不做任何 DML,只等几秒),再在另一会话插入新行,然后回到长事务中
SELECT—— 若能看到新插入的行,说明快照点没按预期冻结,可能是隐式转换或索引失效导致优化器跳过 MVCC 路径 - 运行
SHOW ENGINE INNODB STATUS\G,在TRANSACTIONS区段里找你的事务 ID,看Trx read view will not see trx with id后面的数字是否稳定递增;若频繁变化,说明 read view 被意外重建(常见于含隐式类型转换的查询) - 若看到大量
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:且等待对象是间隙(如supremum pseudo-record),基本可判定是 8.0 强化 Next-Key Lock 导致
最容易被忽略的点:DDL 和事务的元数据锁(MDL)互等
这不是隔离级别问题,但常被误判为事务阻塞。升级后出现大量 Waiting for table metadata lock,大概率是:
-
ALTER TABLE正在执行,而你的普通REPEATABLE READ事务试图访问同一张表(哪怕只是SELECT),就会被卡住——8.0 的原子 DDL 对 MDL 要求更高 - 监控脚本执行
SELECT * FROM sys.innodb_lock_waits;时,因该视图依赖information_schema表,也可能被正在运行的 DDL 阻塞,造成连接池雪崩 - 查
performance_schema.metadata_locks比查锁表更直接:SELECT OBJECT_SCHEMA, OBJECT_NAME, LOCK_TYPE, LOCK_STATUS, OWNER_THREAD_ID FROM performance_schema.metadata_locks WHERE LOCK_STATUS = 'PENDING';


















