mysql中InnoDB存储引擎的事务隔离级别

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

MySQL InnoDB 默认隔离级别是
REPEATABLE READ

启动一个新连接后,执行

SELECT @@transaction_isolation;
SELECT @@tx_isolation;
(旧版本),返回值通常是
'REPEATABLE-READ'
。这是 InnoDB 的默认设置,不是 MySQL Server 层的全局默认(Server 层默认是
REPEATABLE READ
,但实际生效由引擎决定)。

READ COMMITTED
能避免不可重复读,但需注意 MVCC 行为变化

InnoDB 在

READ COMMITTED
下,每个
SELECT
语句都会创建新的快照(即“语句级快照”),而
REPEATABLE READ
是“事务级快照”——第一次
SELECT
就确定了整个事务可见的数据版本。

这意味着在
READ COMMITTED
中,同一事务内两次
SELECT
可能返回不同结果(如果其他事务已提交修改)
UPDATE
/
DELETE
语句在
READ COMMITTED
下只看到已提交版本,不会像
REPEATABLE READ
那样基于事务初态做一致性读
某些场景下,
READ COMMITTED
的锁范围更小(例如非唯一条件更新时,可能不加间隙锁),但具体取决于查询是否命中索引

SERIALIZABLE
会强制将所有普通
SELECT
转为
SELECT ... LOCK IN SHARE MODE

这不是加个表锁那么简单。InnoDB 在

SERIALIZABLE
下,对没有显式加锁的
SELECT
语句自动加上共享锁(S 锁),导致并发读写阻塞明显升高。

例如:事务 A 执行
SELECT * FROM t WHERE id = 10;
,事务 B 同时执行
UPDATE t SET x=1 WHERE id = 10;
,B 会被阻塞直到 A 提交或回滚
即使查询走的是二级索引,也可能触发临键锁(next-key lock),进一步限制并发 除非业务强依赖绝对顺序一致性,否则一般不建议全局启用
SERIALIZABLE

修改隔离级别要注意作用域和生效时机

隔离级别可以在会话级、全局级甚至单条语句级设置,但行为有差异:

会话级:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
—— 只影响当前连接后续事务
全局级:
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
—— 新建连接继承该值,已有连接不受影响
事务级:
START TRANSACTION WITH CONSISTENT SNAPSHOT;
不指定隔离级别,仍按当前会话设置;若要覆盖,必须在
START TRANSACTION
前用
SET TRANSACTION ISOLATION LEVEL ...
MySQL 8.0+ 支持在
SELECT
语句末尾加
FOR UPDATE
LOCK IN SHARE MODE
,但这属于加锁语义,不改变事务隔离级别本身
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT * FROM orders WHERE status = 'pending'; -- 使用 READ COMMITTED 快照
UPDATE orders SET status = 'processing' WHERE id = 123;
COMMIT;

真正容易被忽略的是:隔离级别只约束“读可见性”和“锁行为”,它不能替代应用层的逻辑校验。比如两个事务同时读到同一行并各自更新,在

READ COMMITTED
下可能产生覆盖写,这不是隔离级别能解决的——得靠乐观锁(
version
字段)或应用层重试机制。

相关推荐