mysql查改事务隔离级别:查会话用select @@transaction_isolation,查全局用select @@global.transaction_isolation;改会话用set session transaction isolation level,改全局需super权限。

怎么查和改 MySQL 当前事务隔离级别
MySQL 默认用 REPEATABLE READ,但很多开发者连自己连上去用的是啥都不知道,结果幻读出了问题才回头翻配置。
实操建议:
- 查当前会话级别:
SELECT @@transaction_isolation;(注意是双@) - 查全局默认:
SELECT @@global.transaction_isolation; - 临时改本会话:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; - 改全局(需 SUPER 权限,慎用):
SET GLOBAL transaction_isolation = 'READ-COMMITTED';
常见错误现象:执行 SET TRANSACTION ISOLATION LEVEL ... 没加 SESSION 或 GLOBAL,MySQL 会静默忽略,不报错也不生效。
兼容性影响:MySQL 5.7+ 支持四种标准级别;但如果你用的是 Percona 或 MariaDB,READ-COMMITTED 的 MVCC 行为可能略有差异,尤其在二级索引更新时。
READ COMMITTED 真的能防脏读?但为什么还看到“刚改完就查不到”
能防脏读,但“刚改完就查不到”不是隔离级别问题,而是你没在同一个事务里查 —— READ COMMITTED 只保证“读到已提交”,不保证“立刻可见”。
典型场景:
- 事务 A 执行
UPDATE user SET status=1 WHERE id=100;,还没COMMIT - 事务 B 此时执行
SELECT * FROM user WHERE id=100;→ 阻塞或返回旧值(取决于引擎和锁策略) - 事务 A
COMMIT后,事务 B 再查 → 立刻看到新值(因为每次 SELECT 都拉最新快照)
容易踩的坑:
- 误以为
READ COMMITTED= 实时同步,其实它只控制“读什么”,不控制“什么时候读到” - 在长事务中反复执行相同
SELECT,结果可能逐次变化 → 这就是“不可重复读”,属于该级别允许的行为 - 某些 ORM(如 Django 默认)自动开启事务,但没显式
BEGIN,导致你以为在事务里,其实每次查询都是独立事务
REPEATABLE READ 下为什么还会出现幻读
MySQL InnoDB 的 REPEATABLE READ 用 MVCC + Next-Key Lock 防止大部分幻读,但**仅对“当前读”(带锁的 SELECT)生效**;纯快照读(普通 SELECT)不锁间隙,插入仍可发生。
示例:
- 事务 A 执行
SELECT * FROM order WHERE status=0;→ 返回 5 行 - 事务 B 插入
INSERT INTO order (status) VALUES (0);并COMMIT - 事务 A 再执行同样
SELECT→ 仍是 5 行(MVCC 快照) - 但事务 A 执行
SELECT * FROM order WHERE status=0 LOCK IN SHARE MODE;→ 这次会看到 6 行,且可能触发间隙锁等待
关键点:
- 幻读是否发生,取决于你用的是“快照读”还是“当前读”
-
UPDATE/DELETE/SELECT ... FOR UPDATE都是当前读,会加锁,InnoDB 在此级别下会用 Next-Key Lock 锁住范围 - ORM 自动生成的批量更新(如 Django 的
.update())默认不加锁,也可能绕过幻读防护
SERIALIZABLE 不是银弹,上线前必须压测锁表现
设成 SERIALIZABLE 后,MySQL 会把所有普通 SELECT 自动转成 SELECT ... LOCK IN SHARE MODE,相当于给每条读加行锁 —— 并发一高,锁等待就堆起来。
实操教训:
- 某订单查询接口设了
SERIALIZABLE,QPS 从 800 掉到 40,慢查询日志里全是Waiting for table metadata lock -
SELECT COUNT(*) FROM huge_table在该级别下会锁全表(或大范围),其他写操作全被堵住 - Spring @Transactional(isolation = Isolation.SERIALIZABLE) 在连接池复用场景下,可能让后续非敏感操作也继承该级别
真正需要它的场景极少:比如金融核心账务的轧差、库存超卖强校验等,且往往配合应用层重试+幂等更稳妥。大多数所谓“必须强一致”的业务,用 REPEATABLE READ + 显式 SELECT ... FOR UPDATE + 唯一约束,已经足够。
复杂点在于:隔离级别不是开关,它是和 SQL 类型、索引设计、事务粒度绑在一起的。调低级别省下的锁,可能被应用层补偿逻辑吃掉更多 CPU 和延迟。










