mysql默认事务隔离级别是repeatable read,由innodb自5.1起硬编码实现;验证需查运行时变量@@session.transaction_isolation或@@global.transaction_isolation;大厂常改read committed以降低锁冲突,但会牺牲可重复读。

MySQL 默认事务隔离级别是 REPEATABLE READ
不是“可以配置出来的默认值”,而是 InnoDB 存储引擎从 MySQL 5.1 起就硬编码实现的默认行为。哪怕你删掉所有配置、不写 transaction-isolation,新连接启动后查 @@transaction_isolation 仍是 REPEATABLE-READ。这是 MVCC + Next-Key Lock 协同保障主从一致性的底层设计结果,不是历史遗留或兼容妥协。
怎么验证当前实际生效的隔离级别
别只看配置文件,得查运行时状态:
- 查当前会话:
SELECT @@SESSION.transaction_isolation; - 查全局默认(影响后续新连接):
SELECT @@GLOBAL.transaction_isolation; - MySQL 5.6 及更早版本用旧变量名:
SELECT @@tx_isolation;
注意:SET SESSION 改的是当前连接,不影响其他连接;SET GLOBAL 需要 SUPER 权限,且只对新连接生效,已存在的连接不变。
为什么大厂常改成 READ COMMITTED
不是因为默认不好,而是业务权衡后的取舍:
-
REPEATABLE READ的间隙锁(Gap Lock)在范围查询时容易锁住一大片,导致更新阻塞、死锁概率上升,尤其在高并发库存扣减、订单创建场景下明显 -
READ COMMITTED每次SELECT都读最新已提交快照,不依赖事务启动时的一致性视图,锁粒度更轻、并发更高 - 代价是同一事务内两次
SELECT可能返回不同结果(不可重复读),需业务层确认能否接受——比如用户中心查状态、日志统计类接口通常没问题,但财务对账、资金流水核对就不适合
改法示例(会话级):SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
配置文件里改默认值要注意什么
在 my.cnf 或 my.ini 中加这一行即可持久化:
transaction-isolation = REPEATABLE-READ
但注意三点:
- 必须重启 MySQL 才对新连接生效(
SET GLOBAL不需要重启,但效果等价) - 如果用了中间件(如 ShardingSphere、ProxySQL),它们可能覆盖或忽略这个配置,得单独检查中间件层的事务行为
- 某些云数据库(如阿里云 RDS、腾讯云 CDB)禁止修改全局隔离级别,只能靠应用层显式
SET SESSION控制
真正容易被忽略的是:即使你把配置改成 READ-COMMITTED,InnoDB 仍会在某些语句(如 SELECT ... FOR UPDATE)中自动升级锁行为,幻读风险并未完全消失——它只是比默认级别“更少锁”,不是“不锁”。










