当前位置: 首页 > news >正文

数据库事务隔离级别的演进

一、 事务并发基础与传统基于锁的并发控制(LBCC)

数据库事务的隔离性(Isolation)是对于并发安全与效率之间的权衡结果,包括脏读(Dirty Read)、不可重复读(Non-repeatable Read)和幻读(Phantom Read)。在早期数据库系统中,保证隔离性的最基础手段是基于锁的并发控制(Lock-Based Concurrency Control, LBCC),其核心理论依据是两阶段锁协议(Two-Phase Locking, 2PL)

两阶段锁协议规定,事务的加锁和解锁必须严格分为两个独立的阶段:

  1. 加锁阶段(Growing Phase):事务可以按需申请共享锁(S锁)和排他锁(X锁),但不能释放任何锁。
  2. 解锁阶段(Shrinking Phase):事务释放锁,但在此阶段不能再申请任何新锁。为了保证事务的原子性(支持安全回滚)和严格的一致性,InnoDB 遵循严格两阶段锁协议(Strict 2PL),即所有排他锁必须持有到事务提交(COMMIT)或回滚(ROLLBACK)时才能释放。

在纯 LBCC 机制下,各隔离级别的实现方式如下:

  • 读未提交(Read Uncommitted, RU):读操作不加锁,写操作加 X 锁并持有到事务结束。导致脏读。
  • 读已提交(Read Committed, RC):读操作加 S 锁,读取完毕后立即释放;写操作加 X 锁持有到事务结束。由于 S 锁提前释放,其他事务可以介入修改并提交,导致同一事务内两次读取结果不同,产生不可重复读。
  • 可重复读(Repeatable Read, RR):读操作加 S 锁,且持有到事务结束;写操作加 X 锁持有到事务结束。由于读锁和写锁均覆盖整个事务生命周期,数据被完全锁定,解决了不可重复读。但由于记录锁(Record Lock)只能锁定已存在的行,无法锁定不存在的“间隙”,其他事务依然可以插入新行,从而导致幻读。
  • 串行化(Serializable):采用表级锁或谓词锁(Predicate Locking),严格禁止任何并发冲突操作。

LBCC 的核心缺陷:读操作和写操作存在严格的互斥(S锁与X锁冲突)。在读多写少的应用场景中,长时间持有的锁会导致极高的锁争用,并发吞吐量极低。


二、 多版本并发控制(MVCC)对读写互斥的优化

为了突破 LBCC “读写互斥”的性能瓶颈,InnoDB 引入了多版本并发控制(Multi-Version Concurrency Control, MVCC)。MVCC 的核心工程思想是**“读写分离”**:通过保留数据的历史版本,使得读操作可以读取旧版本数据,而无需等待写操作释放 X 锁。

MVCC 将数据库的读操作严格区分为两种语义:

  1. 快照读(Snapshot Read):普通的SELECT语句。不加任何显式锁。引擎通过计算可见性,返回数据在此事务开启时的一个历史一致性快照。
  2. 当前读(Current Read):包含SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE,以及所有的写操作(INSERTUPDATEDELETE)。当前读必须读取记录的最新已提交版本,并且强制加物理锁(S锁或X锁)以阻塞其他并发修改。

MVCC 的底层实现依赖于Undo Log(回滚日志)ReadView(读视图)

  • 每次更新记录时,旧值会被写入 Undo Log,数据行中通过隐藏的roll_pointer(回滚指针)将这些日志串联成一条版本链。数据行还会记录最后一次修改该行的事务 ID(trx_id)。
  • ReadView 是事务执行快照读时生成的一个内存结构,记录了当前系统中活跃(未提交)的事务 ID 列表。通过将数据行的trx_id与 ReadView 中的高低水位线进行代数比对,InnoDB 可以在不加锁的情况下,准确判定某个历史版本对当前事务是否可见。

三、 RC 与 RR 在 MVCC 架构下的本质差异

在 InnoDB 中,RC 和 RR 隔离级别默认的读操作都是快照读,都不加锁。它们在解决并发异常上的能力差异,完全取决于ReadView 生成时机的不同

  • RC(读已提交)的 ReadView 机制:
    在 RC 级别下,事务中的每一次快照读操作都会生成一个全新的 ReadView。
    结果推演:如果事务 A 在两次快照读之间,事务 B 修改了数据并提交,事务 B 的trx_id将不再存在于事务 A 的第二次 ReadView 的活跃列表中。因此,事务 A 的第二次读取会看到事务 B 的修改。这导致了不可重复读。

  • RR(可重复读)的 ReadView 机制:
    在 RR 级别下,事务仅在第一次执行快照读时生成一个 ReadView,此后整个事务生命周期内的所有快照读都复用这一个 ReadView。
    结果推演:无论其他并发事务如何修改数据并提交,事务 A 的 ReadView 始终保持静态。根据可见性算法,那些在 ReadView 生成之后提交的修改,其trx_id对事务 A 始终不可见。事务 A 只能顺着 Undo Log 版本链找到生成 ReadView 时的那个历史版本。因此,RR 级别通过 MVCC 完美解决了不可重复读,且全程无需加读锁。


四、 幻读的界定与 RR 级别的当前读加锁机制

幻读是指在一个事务内,执行两次相同的范围查询,后一次查询看到了前一次查询未看到的“幻影行”(通常是其他事务新插入的行)。

在 InnoDB 的 RR 级别中,幻读的解决方式根据读取模式的不同被拆分为两套机制:

  1. 快照读下的幻读解决:依赖 MVCC
    由于 RR 级别的 ReadView 是全局静态的,其他事务新插入的记录(其事务 ID 必然大于 ReadView 生成时的活跃事务 ID)对当前事务绝对不可见。因此,连续两次普通的SELECT不会产生幻读,此过程不涉及任何锁机制。

  2. 当前读下的幻读解决:依赖 Next-Key Lock(临键锁)
    当事务执行当前读(如SELECT ... FOR UPDATEUPDATE)时,MVCC 的 ReadView 机制失效。事务被强制要求读取底层数据页上的最新状态。如果仅使用记录锁(Record Lock),无法阻止其他事务在记录间的空隙中执行INSERT

    为此,InnoDB 在 RR 级别的当前读中引入了Gap Lock(间隙锁)

    • 间隙锁的定义:锁定一个范围,但不包括记录本身。其唯一目的是阻止其他事务在此间隙内获取插入意向锁(Insert Intention Lock),从而从物理层面阻断数据的插入。
    • 临键锁(Next-Key Lock):是记录锁和间隙锁的结合,锁定记录本身及其左侧的间隙(左开右闭区间)。

    结果推演:在 RR 级别执行UPDATE table SET ... WHERE id > 10时,InnoDB 不仅对符合条件的现有记录加排他锁,还会对id > 10的整个索引树区间加间隙锁。任何试图在此区间插入新数据的事务将被阻塞,直至当前事务释放锁(提交或回滚)。至此,RR 级别通过物理锁机制解决了当前读下的幻读问题。而在 RC 级别下,当前读仅加记录锁,不加间隙锁(外键检查和唯一键检查除外),因此 RC 级别存在幻读现象。


五、 RR 与串行化(Serializable)的核心隔离边界

既然 InnoDB 的 RR 级别通过“MVCC(针对快照读)+ Next-Key Lock(针对当前读)”已经解决了脏读、不可重复读和幻读,为什么还需要保留串行化(Serializable)隔离级别?二者的核心边界在于对**写倾斜(Write Skew)**这一并发异常的防御逻辑不同。

写倾斜的本质:
写倾斜属于一种特殊的逻辑违例现象,通常发生在“读-修改-写(Read-Modify-Write)”的业务范式中。当两个并发事务基于各自的快照读获取了相同的前提状态,随后又基于此状态执行了物理上不冲突、但逻辑上互斥的更新操作时,业务一致性即被破坏。

  • RR 级别的处理逻辑(放任与开发者显式控制):
    在 RR 级别下,默认的SELECT依然是无锁的快照读。如果业务逻辑依赖SELECT的结果集进行条件判断,再执行UPDATE,由于快照读互不阻塞,两个事务可以同时判定条件成立并各自执行更新。只要它们更新的不是同一行数据(无物理锁冲突),数据库将允许两者均提交成功。RR 级别为了追求极致的并发性能,默认不提供对业务因果关联的校验,必须由开发者显式地在查询时升级为当前读(附加FOR UPDATE),将并发降级为排队,方可避免写倾斜。

  • Serializable 级别的处理逻辑(隐式强制转换与死锁防御):
    串行化隔离级别摒弃了 MVCC 的快照读优势。在此级别下,InnoDB 会在底层隐式地将所有普通的SELECT语句转换为SELECT ... LOCK IN SHARE MODE(当前读,加 S 锁)。

    结果推演:当两个事务并发执行查询时,均在目标数据集上获取了 S 锁(S 锁相互兼容)。随后,当两者试图基于查询结果执行UPDATE时,均需将 S 锁升级为 X 锁。由于 X 锁与对方持有的 S 锁冲突,双方陷入循环等待。InnoDB 的死锁检测机制(Wait-for Graph)将立即介入,主动回滚其中一个事务。串行化级别通过主动制造死锁和强迫回滚,无视任何性能损耗,在引擎底层绝对性地防止了写倾斜和业务规则的破坏。

http://www.jsqmd.com/news/718188/

相关文章:

  • CSS按钮点击阴影跨浏览器修正_使用appearance- none重置外观
  • 7小时TIKTOK高手饭局后,我发现AI短视频已不是“选不选“的问题
  • 2026年4月知名的施建筑工资质延期公司有哪些厂家推荐榜,建筑施工总承包、专业承包、劳务资质延期厂家选择指南 - 海棠依旧大
  • 2026年4月热门的江汉区净水机品牌哪家好厂家推荐榜,即热式开水器/商用直饮水机/工厂饮水机/办公室饮水机厂家选择指南 - 海棠依旧大
  • 智能储气技术在双膜气柜中的应用
  • 深度技术解析:BepInEx框架在Unity游戏中的架构稳定性挑战与多运行时环境解决方案
  • VS Code MCP生态搭建终极图谱(含23个官方/社区插件兼容性矩阵):仅限首批订阅者获取的2024 Q3兼容性白皮书
  • 2026智造进化论:从人工排程到AI智能排产,制造业生产模式正在如何变革?实在Agent技术解决方案
  • CompressO:开源免费的跨平台视频图像压缩神器,让大文件变小不再是难题
  • Nano-Banana与OpenCV结合:实时图像风格迁移应用
  • 拒绝AIGC痕迹:4个手改技巧+1款实用工具,亲测论文AI率从90%压到10%
  • 2026年4月知名的图书货源与代发公司找哪家厂家推荐榜:图书一件代发/图书批发/图书分销/正版货源厂家选择指南 - 海棠依旧大
  • 饮用水包装设计公司哪家专业靠谱 瓶装水矿泉水品牌包装升级首选哲仕设计 - 设计调研者
  • Matlab与Qianfan-OCR-4B联动:科学计算环境中的文档数据分析
  • JVM底层揭秘:Vector API如何绕过C2编译器屏障直驱SIMD单元,实现零拷贝向量计算
  • Qwen3.5-9B-GGUF开源可部署:基于Qwen3.5-9B-GGUF的RAG系统搭建
  • Jasminum插件:三步搞定中文文献管理,让Zotero效率提升10倍!
  • AI火了,个人博客反而又活过来了?2026年“部落格文艺复兴”真相
  • Hypnos-i1-8B应用场景:开源硬件项目——电路设计逻辑完整性自动审查
  • 2026年4月知名的协作机器人公司推荐榜厂家推荐榜,协作机器人、六轴/七轴/双臂协作机器人厂家选择指南 - 海棠依旧大
  • Java 25升级后ZGC GC次数暴涨5倍?5分钟诊断清单+2行JVM参数紧急回滚方案
  • 2026年离散制造业生产全流程智能化的最新趋势是什么?基于实在Agent的柔性生产实践
  • NoFences:用11欧元省下的钱,打造你的智能桌面分区系统
  • Wan2.1 VAE社区贡献指南:如何向GitHub开源项目提交代码
  • Codeforces评级预测工具Carrot的架构演进:从单点依赖到弹性系统的技术重构
  • 2026年4月知名的缅甸玉公司怎么选择厂家推荐榜,源头直供/私人定制/矿区合作/毛料批发厂家选择指南 - 海棠依旧大
  • 2026年4月值得信赖的石家庄电子电气员ETO一条龙培训机构排行厂家推荐榜,专业型、综合型、定制型厂家选择指南 - 海棠依旧大
  • WarcraftHelper完整攻略:让经典魔兽争霸在现代PC上焕发新生
  • 基于模型的自动化测试用例设计平台AutoTCG
  • Moonlight Internet Hosting Tool:零配置远程游戏串流终极解决方案