ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

“三级:二级 + S锁保持到事务结束 → 防止不可重复读”是对数据库事务隔离级别的一种简略描述

“三级:二级 + S锁保持到事务结束 → 防止不可重复读”是对数据库事务隔离级别的一种简略描述 “三级二级 S锁保持到事务结束 → 防止不可重复读”是对数据库事务隔离级别的一种简略描述但存在概念混淆需澄清SQL标准定义的隔离级别中并没有官方称为“三级”的说法通常指读未提交Read Uncommitted—— 最低级可能读脏数据读已提交Read Committed—— 防止脏读但允许不可重复读可重复读Repeatable Read—— 防止脏读和不可重复读通过快照读或S锁长期持有实现具体取决于DBMS串行化Serializable—— 最高级防止幻读完全串行执行。您描述的“二级 S锁保持到事务结束”实际对应的是可重复读RR级别的一种实现方式如传统两阶段锁协议中SELECT加的共享锁S锁持续到事务结束这确实能防止不可重复读即同一事务内多次读同一行结果一致。但注意MySQL InnoDB 默认 RR 级别不依赖长持S锁而是基于MVCC多版本并发控制 间隙锁来避免不可重复读和部分幻读而 SQL Server 在可重复读下会将S锁保持到事务结束单纯延长S锁不能防止幻读新插入满足条件的行需更高隔离级别或范围锁。✅ 正确理解“可重复读”隔离级别旨在解决不可重复读问题其实现机制可以是MVCC如InnoDB→ 无锁、基于快照2PL 长期S锁如某些锁实现→ 保证读一致性但并发性较低。-- 示例在支持S锁长持的系统中以下事务将阻塞其他事务修改该行SETTRANSACTIONISOLATIONLEVELREPEATABLEREAD;BEGINTRANSACTION;SELECT*FROMaccountsWHEREid1;-- 加S锁并保持至COMMIT/ROLLBACK-- 其他事务UPDATE accounts SET balance... WHERE id1 将被阻塞COMMIT;可重复读Repeatable Read, RR与串行化Serializable在防止幻读Phantom Read方面的本质区别在于RR 通常不保证防止幻读而 Serializable 是唯一能严格防止幻读的标准隔离级别这一差异源于二者对范围查询range predicate下新插入行的可见性控制机制不同。✅核心本质区别维度可重复读RR串行化Serializable标准定义SQL-92保证同一事务中多次读取相同行结果一致防不可重复读不保证范围查询结果集不变即允许幻读要求事务执行效果等价于某种串行顺序执行必须阻止所有并发异常包括脏读、不可重复读和幻读幻读定义同一事务内两次执行相同范围查询如SELECT * FROM t WHERE age 25第二次返回了第一次不存在的新行由其他事务插入并提交任何导致逻辑上无法串行化的并发行为含幻读均被禁止实现机制对比• InnoDBMVCC 间隙锁Gap Lock或临键锁Next-Key Lock→实际中可阻止部分幻读仅针对当前已存在的索引区间内的插入但快照读普通SELECT仍可能看到幻行若插入发生在快照之后且未加锁• 其他DB如PostgreSQL纯MVCCRR级明确允许幻读因无间隙锁快照基于事务开始时的全局快照• InnoDB将范围查询视为锁定整个搜索范围升级为范围S/X锁或使用序列化调度器如SI 冲突检测• PostgreSQL通过可串行化快照隔离SSI检测写偏序冲突自动中止导致幻读的事务• 本质主动阻塞或回滚任何可能破坏串行等价性的操作 关键澄清MySQL InnoDB 的 RR 级别通过临键锁Next-Key Lock Record Lock Gap Lock在加锁读如SELECT ... FOR SHARE/UPDATE时防止幻读但普通快照读无LOCK IN SHARE MODE不加锁依赖MVCC快照因此仍可能“感知”到幻行注意这不是标准幻读而是快照一致性下的正常现象真正幻读指加锁读结果不一致InnoDB RR下加锁读已规避。而 Serializable 强制所有读操作包括普通SELECT都加范围锁或等效机制确保事务间完全互斥彻底消除幻读语义。 示例对比MySQL InnoDB-- 事务ARR级别STARTTRANSACTION;SELECT*FROMusersWHEREage30;-- 返回3条记录快照读不加锁-- 此时事务B插入 age35 的新用户并 COMMITSELECT*FROMusersWHEREage30;-- 仍返回3条MVCC快照不变→ *非幻读*-- 若改为SELECT * FROM users WHERE age 30 LOCK IN SHARE MODE;-- 则事务B的INSERT会被阻塞 → *防止幻读*-- 事务ASERIALIZABLE级别STARTTRANSACTION;SELECT*FROMusersWHEREage30;-- 自动等价于加临键锁事务B INSERT被阻塞✅ 结论RR 通过锁或MVCC提供“行级稳定性”但不承诺“范围结果集稳定性”Serializable 则通过强制范围控制或冲突检测保障整个查询谓词predicate的结果集在事务生命周期内绝对不变——这是防止幻读的本质所在。
返回列表