MySQL升级后事务异常主因是默认配置变更,需重点排查:1.隔离级别默认值(5.7为RR,8.0.22+可能为RC);2.RC下一致性读更严格(每SELECT用最新快照);3.autocommit下DDL隐式提交更严格;4.sql_mode严格化导致警告变错误。
MySQL 升级后事务行为出现异常,通常不是“bug”,而是版本间默认配置、隔离级别实现或 SQL 模式调整导致的预期变化。重点排查 事务隔离级别默认值、READ-COMMITTED 下的一致性读行为、autocommit 默认状态、SQL_MODE 对事务语义的影响 这四类核心差异。
MySQL 5.7 默认隔离级别是 REPEATABLE-READ,而 MySQL 8.0.22+ 在启用 transaction_isolation 系统变量(替代旧的 tx_isolation)后,若未显式配置,可能受启动参数或配置文件影响,部分云厂商镜像甚至默认设为 READ-COMMITTED。
SELECT @@transaction_isolation; 确认当前会话/全局实际值my.cnf 是否有 transaction_isolation = READ-COMMITTED 或类似配置MySQL 8.0 对 RC 隔离级别的 MVCC 实现做了优化:每个 SELECT 语句都基于最新已提交快照,而非事务开始时的快照。这导致同一事务内多次 SELECT 可能返回不同结果——这是标准 SQL 行为,但老版本(尤其 5.6)因实现限制反而“看起来更稳定”。
SELECT ... FOR UPDATE 或升至 RR
改用原子更新:UPDATE account SET balance = balance - ? WHERE id = ? AND balance >= ?
所有 MySQL 版本默认 autocommit = 1,但升级后对 DDL 语句触发隐式提交 的处理更严格。例如,在事务中执行 CREATE TABLE 或 ALTER TABLE,8.0 会立即提交当前事务并清空保存点,而 5.6/5.7 可能允许部分 DDL 在事务块内(非标准且已被弃用)。
SHOW VARIABLES LIKE 'completion_type'; 确认是否启用了 NO_CHAIN 或 CHAIN,它会影响 COMMIT 后的行为MySQL 8.0 默认启用更严格的 sql_mode(含 STRICT_TRANS_TABLES)。当 INSERT/UPDATE 出现警告(如截断字符串、零日期)时,严格模式会让语句直接报错并回滚当前语句——若在事务中,可能打断预期流程,甚至让应用误判为“整个事务失败”。
SELECT @@sql_mode; 对比新旧环境差异SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,...'; 去掉 STRICT*不复杂但容易忽略。升级前做事务路径回归测试,重点覆盖“查-判-改”、并发更新、DDL 混用、空值/边界值写入这几类典型场景。