mysql默认隔离级别是repeatable read,innodb支持全部四种标准级别;myisam不支持事务,无隔离级别概念;可通过select @@transaction_isolation等命令查询、set session/global修改级别;配置文件可永久设置;autocommit和客户端初始化语句可能影响实际效果;各级别通过mvcc与锁机制实现不同一致性行为;serializable并非万能,需结合业务逻辑与锁机制保障一致性。

MySQL 默认隔离级别是 REPEATABLE READ,但支持全部四种标准级别
MySQL 的 InnoDB 存储引擎完整支持 SQL 标准定义的四种事务隔离级别:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。注意:MyISAM 不支持事务,所以谈隔离级别毫无意义——它压根没有事务上下文,所有操作都是自动提交的“伪事务”。你只要用的是 InnoDB(推荐且默认),就可以自由切换隔离级别。
怎么查和改当前会话或全局的隔离级别?
查当前会话级别:SELECT @@transaction_isolation; 或 SELECT @@tx_isolation;(旧版本兼容)
查全局默认级别:SELECT @@global.transaction_isolation;
改当前会话(退出即失效):SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
改全局(需 SUPER 权限,重启后失效,除非写进配置):SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
- 配置文件永久生效:在
my.cnf或my.ini的[mysqld]段下加一行transaction-isolation = READ-COMMITTED(注意用短横线,不是下划线) - 别漏掉
autocommit的影响:即使设了REPEATABLE READ,如果autocommit=ON(默认),每条UPDATE都是独立事务,根本不会体现“可重复读”的效果 - 某些客户端(如 MySQL Workbench)连接时可能带初始化语句,会悄悄覆盖你的会话设置,建议连接后立刻
SELECT @@transaction_isolation确认
不同级别实际行为差异,关键看 MVCC 和锁怎么配合
READ UNCOMMITTED:能读到别人未提交的数据,脏读必现;InnoDB 几乎不加行锁(只在写时加),性能高但业务基本不用。
READ COMMITTED:每次 SELECT 都生成新快照,所以同一事务内两次查询可能结果不同(不可重复读);间隙锁(Gap Lock)不生效,幻读更易发生;适合对一致性要求不高、读多写少的场景(如日志归档)。
REPEATABLE READ(InnoDB 默认):事务启动时拍一次快照,后续所有 SELECT 都基于该快照(MVCC 实现),因此不会不可重复读;但更新/删除时仍会加间隙锁,部分抑制幻读;注意:INSERT ... SELECT 或 UPDATE ... WHERE 仍可能因锁范围导致幻读,不能完全依赖隔离级别解决。
SERIALIZABLE:所有 SELECT 都隐式加上共享锁(LOCK IN SHARE MODE),写操作加排他锁,彻底串行化;并发能力极低,仅用于极强一致性要求(如金融核对),日常慎用。
容易被忽略的坑:隔离级别 ≠ 锁策略,也不等于业务一致性
很多人以为设成 SERIALIZABLE 就万事大吉,但实际中:
- DDL(如
ALTER TABLE)会无视事务隔离,直接阻塞所有并发查询 - 长事务会拖住 InnoDB 的 purge 线程,导致历史版本堆积、undo 表空间暴涨
- 隔离级别解决不了应用层逻辑错误:比如两个事务都读到库存=1,各自扣减后写回=0,这就是典型的“更新丢失”,得靠
SELECT ... FOR UPDATE或乐观锁(version 字段)来兜底 - Spring 的
@Transactional(isolation = ...)注解,底层仍是调用 MySQL 的 SET 命令,但如果事务跨越多个数据源(如分库),数据库层的隔离级别就失效了
真正要稳,得结合业务语义选级别,再配合适当的锁、重试机制和幂等设计——隔离级别只是拼图里的一块,不是万能胶水。










