mysql默认事务隔离级别是什么_mysql配置与行为分析

来源:这里教程网 时间:2026-02-28 20:51:51 作者:

MySQL默认隔离级别就是REPEATABLE-READ

InnoDB(MySQL 5.7+ 默认存储引擎)的默认事务隔离级别是

REPEATABLE READ
,不是
READ COMMITTED
,也不是
SERIALIZABLE
。这点和 Oracle、PostgreSQL 等主流数据库不同,容易在迁移或调优时踩坑。

验证方式很简单,在任意 MySQL 客户端执行:

SELECT @@GLOBAL.transaction_isolation, @@SESSION.transaction_isolation;

输出结果通常是:

@@GLOBAL.transaction_isolation @@SESSION.transaction_isolation
REPEATABLE-READ REPEATABLE-READ

注意:MySQL 5.6 及更早版本用的是

tx_isolation
变量名,命令要换成
SELECT @@GLOBAL.tx_isolation

为什么默认选REPEATABLE-READ?它真能防幻读吗

官方文档和很多资料说 InnoDB 在

REPEATABLE READ
下“解决了幻读”,但这是有前提的——仅针对**快照读(普通 SELECT)**。而**当前读(如 SELECT ... FOR UPDATE、UPDATE、DELETE)仍可能遇到幻读**,因为 InnoDB 会加间隙锁(gap lock)或 next-key lock 来阻塞插入,但这依赖索引结构和查询条件是否命中索引。

没走索引的 WHERE 条件 → 可能退化为表锁,或间隙锁失效 → 幻读风险高 WHERE 条件是等值且命中唯一索引 → 间隙锁不生效 → 其他事务仍可 INSERT 相邻值,造成幻读 显式使用
SELECT ... LOCK IN SHARE MODE
FOR UPDATE
→ 触发当前读,InnoDB 才真正尝试用锁规避幻读

所以不能只靠隔离级别“躺平”,得结合 SQL 写法、索引设计、是否需要加锁来综合判断。

怎么安全地改隔离级别?别只改 session

临时改当前会话级别很常见,比如调试时执行:

SET SESSION transaction_isolation = 'READ-COMMITTED';

但上线前如果想全局生效,必须改配置文件(如

/etc/my.cnf
),否则重启后就回去了:

[mysqld]
transaction_isolation = READ-COMMITTED

注意三点:

配置项值必须用短横线分隔(
READ-COMMITTED
),不能写成下划线或大驼峰
改完要重启 MySQL 实例(
systemctl restart mysqld
),
SET GLOBAL
不持久
某些云数据库(如阿里云 RDS、腾讯云 CDB)不开放全局变量修改权限,只能通过控制台参数模板设置

READ-COMMITTED vs REPEATABLE-READ:性能与行为差异在哪

切换隔离级别不是“越高级越好”。实际影响集中在三方面:

MVCC 快照生成时机
READ COMMITTED
每次 SELECT 都新建 ReadView;
REPEATABLE READ
在事务第一次 SELECT 时建一次,后续复用 → 后者一致性更强,但长事务可能拖慢 purge 线程
锁范围:RC 下只对命中记录加行锁,不加间隙锁(除非外键或唯一约束检查);RR 下默认加 next-key lock → RC 并发写入冲突更少,但幻读风险明确存在 主从延迟敏感度:RC 下 binlog 是 statement 格式时,某些函数(如
NOW()
UUID()
)可能导致主从不一致;RR + ROW 格式更稳妥

真实项目中,若业务能接受“同一事务内两次 SELECT 结果可能不同”,且写多读少(如订单状态流),

READ COMMITTED
往往更轻量;若强依赖事务内读一致性(如财务对账),就别动默认值。

最常被忽略的一点:应用层 ORM(如 MyBatis、Hibernate)可能隐式开启事务并指定隔离级别,此时数据库配置只是兜底,优先级低于代码传参。查问题前,先确认是不是框架自己设了

ISOLATION_REPEATABLE_READ
或类似值。

相关推荐