隔离级别与锁,MVCC
大约 3 分钟
隔离级别与锁,MVCC
相关链接
以下内容摘抄总结自:本地事务 | 凤凰架构
内容以 ARIES 理论为讨论目标的,具体的数据库并不一定完全遵照理论实现。
数据库隔离性与锁
不同隔离级别以及幻读、不可重复读、脏读等问题都只是表面现象,是各种锁在不同加锁时间上组合应用产生的结果,以锁为手段来实现隔离性才是数据库表现出不同隔离级别的根本原因。
悲观锁
写锁(Write Lock,也叫 排他锁 eXclusive Lock,简称 X-Lock)
如果数据有加写锁,只有持有写锁的事务才能进行写入,其他事务此时不能写入数据,也不能加读锁。
读锁(Read Lock,也叫 共享锁 Shared Lock,简称 S-Lock)
多个事务可以对同一数据加读锁,数据被加上读锁后不能加写锁,其他事务只能对该数据进行读取不能写入。对于只持有一个事务读锁的数据,允许其升级为写锁。
范围锁(Range Lock)
对某个范围加排他锁,这个范围内的数据不能被写入。
隔离级别
可串行化(Serializable)
可简化理解为对事务所有读、写数据全部加上读锁、写锁、范围锁。
可重复读(Repeatable Read)
对事务涉及的数据加写锁和读锁,且一直持有至事务结束,但不加范围锁。
读已提交(Read Committed)
对事务数据加的写锁会一直持续至事务结束,但加的读锁在查询操作结束后立即释放。
读未提交(Read UnCommitted)
对事务数据加的写锁会一直持续至事务结束,但完全不加读锁。
完全不加读锁,能令其读到其他事务加了写锁的数据; 因为 写锁禁止事务加锁,但不禁止事务直接读取数据。
幻读、不可重复读、脏读等问题都是由于一个事务在读数据过程中,受另一个写数据的事务影响而破坏了隔离性;
针对“一个事务读+另一个事务写”的隔离问题,多版本并发控制的无锁优化方案(读取时无需加锁)被广泛采用。
多版本并发控制(Multi-Version Concurrency Control,MVCC)
对数据的任何更改都不会直接覆盖原先数据,而是产生一个新版副本与老版本共存,以此达到读取时完全无需加锁的目的。
如果有一个事务要读取发生变化的数据,根据隔离级别决定读取哪个版本的数据:
- 可重复读:读取 CREATE_VERSION 小于或等于当前事务 ID 的记录,如果小于/等于当前事务 ID 的数据存在多个版本,取事务 ID 最大的版本。
- 读已提交:总是读取最新版本的数据。