mysql事务隔离级别不能靠改配置文件“一劳永逸”生效,必须用set命令显式设置;已有连接不受my.cnf中transaction_isolation配置影响,需通过select @@transaction_isolation和select @@global.transaction_isolation查看实际运行时级别,临时修改须在事务开始前执行,永久修改需重启服务且仅影响新连接。

MySQL事务隔离级别不能靠改配置文件“一劳永逸”生效,必须用SET命令显式设置;已有连接不受my.cnf中transaction_isolation配置影响,这是最常踩的坑。
查看当前会话和全局隔离级别
想确认当前实际生效的级别,不能只看配置文件——得查运行时状态:
-
SELECT @@transaction_isolation:返回当前会话的隔离级别(如'REPEATABLE-READ') -
SELECT @@global.transaction_isolation:返回新连接默认使用的级别,不反映已存在连接的实际值
注意:MySQL 8.0+ 返回值格式为带单引号的字符串(如'READ-COMMITTED'),不是旧版的TX_ISOLATION变量名。
临时修改当前会话隔离级别
仅对当前连接有效,断开重连即恢复,默认值由@@global.transaction_isolation决定:
- 必须在
BEGIN或START TRANSACTION之前执行,否则报错:Can’t change transaction isolation level when a transaction is active - 语法:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED(SESSION可省略) - 支持的值严格区分大小写?不,MySQL不敏感,但建议统一用大写+短横线(如
READ-COMMITTED)避免歧义
典型误操作:在事务中执行SET,或在应用框架(如Spring)开启事务后手动调SET——此时事务已激活,命令直接失败。
永久修改新连接默认值(需重启或重连)
修改my.cnf或my.ini的[mysqld]段落,只影响后续新建连接:
- 添加配置项:
transaction_isolation = READ-COMMITTED - 修改后必须重启MySQL服务,否则不生效
- 已存在的连接仍保持原隔离级别,不会自动更新
- 验证是否生效:新开一个客户端连接,执行
SELECT @@transaction_isolation确认
别指望改完配置就全局统一——应用连接池里的长连接不会重读配置,除非重建连接。生产环境推荐配合连接池最小空闲数清零策略,逐步替换旧连接。
不同隔离级别的关键行为差异
选错级别不是“不够安全”,而是引发具体异常且难以排查:
-
READ-UNCOMMITTED:普通SELECT不加锁,能读到未提交数据——库存扣减后立刻被其他事务读到,但发起方回滚,下游发货逻辑就崩了 -
READ-COMMITTED:每次SELECT都生成新Read View,同一事务内两次查余额可能不同(不可重复读),适合日志类弱一致性场景 -
REPEATABLE-READ(MySQL默认):快照读基于事务开启时的Read View,但幻读仍可能发生——分页查询第二页突然出现第一页漏掉的记录,因其他事务插入了新行 -
SERIALIZABLE:所有SELECT隐式转为SELECT ... LOCK IN SHARE MODE,读也要抢锁,高并发下极易触发Lock wait timeout exceeded
真正容易被忽略的是:InnoDB的REPEATABLE-READ靠Next-Key Lock防幻读,但只覆盖查询条件涉及的索引范围;没走索引的WHERE条件,间隙锁失效,幻读风险陡增——别只改隔离级别,先确保查询走了索引。











