数据库事务之隔离性
数据库事务之隔离性
数据库事务
数据库事务是数据库管理系统执行过程逻辑单位,由有限的数据库操作序列构成。
事务与ACID
ACID事务四大特征可以保证事务正确可靠,四大特征分指原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
ACID
- 原子性(Atomicity):一个事务的所有操作,要么全部成功执行、要么全部不执行。如果事务在执行过程中出错,则全部回滚到事务开始前的状态,就像这个事务从未执行过。即事务不可分割。
- 一致性(Consistency):在事务开始之前和事务结束之后,数据库的完整性没有被破坏,这要求写入的数据必须完全符合所有的预设约束、触发器、级联回滚等。
- 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改能力,隔离性可以防止多个事务并发执行由于交叉执行而导致数据不一致。事务隔离分为不同的级别,包括未提交读(Read
uncommitted)、提交读(Read committed)、可重复读(Repeatable
read)和串行化(Serializable)。 - 持久化(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也会丢失。
事务回滚通过回滚日志(undo log)实现、事务持久化主要靠事务结束执行添加重做日志(redo log)实现。下面主要讲隔离性
隔离性所解决的四大问题
脏写(Dirty write)
脏写:一个事务修改另一个事务未提交的修改数据。例如某条记录money=800,现在事务A、事务B并发对其修改,事务A先更新money=1000,事务B再更新money=1200,然后事务A提交事务,但是事务B发现错误回滚至事务开始前的money=800,丢失了事务A的更新money=1000。事务ADB事务B
脏读(Dirty read)
不可重复读:在一次事务中,当一行数据获取两遍得到不同的结果表示发生了"不可重复读"。在解决脏读问题后,还是存在不可重复读问题。例如某条记录money=800,事务A、B并发分别对其写读,事务A更新money=800但未提交,事务B读取money=800,然后事务A提交,事务B再读取money=1000,事务B先后两次读取money值不一致,这就是不可重复读。
幻读(Phantom reading)
幻读:在一次事务中,当两个完全相同的查询语句执行得到不同的结果集。初始化只有记录name, money = (张三,800),事务A开始事务读500<money<2000,读取只有记录(张三, 800) ,然后事务B开始事务插入记录(李四, 1000),相比第一次读取,多了"李四"记录。
幻读导致的灵异事件
note: 四大问题严重性:脏写 > 脏读 > 不可重复读 > 幻读
隔离性四个级别
未提交读是最低的隔离级别,解决了脏写,但是允许脏读,事务可以看到其他事务"尚未提交"的修改。
提交读(Read committed)
提交读是在并发事务中,一个事务不会读到另一个事务未提交的更改,解决未提交读中脏读,但是还是有不可重复读问题。
可重复读(Repeatable read)
可重复读比提交读更严格,在并发事务中,保证一个事务前后两次读到结果是一致的,解决了不可重复读问题。理论上还有幻读问题,但在mysql下可重复读级别已解决幻读问题,具体看下面第二张图。
可串行化(Serializable)
最严格的隔离级别,解决了所有问题,但是因为完全用锁效率低下。
隔离四个级别与四大问题
隔离级别实现相关
读写锁读写锁是计算机程序的并发控制的一种同步机制,也称为"共享-互斥锁"、“多读者-单写者锁”。读操作可并发重入,写操作是互斥的。
- 当读锁已被持有,允许重入读操作,但不允许写操作
- 当写锁已被持有,即不允许重入读操作,也不允许写操作
读锁又称为共享锁(share locks),写锁又称为排它锁(exclusive locks)
一致性无锁读
一致性无锁读通过MVCC(Multi Version Concurrency Control)多版本并发控制实现。MVCC通过数据冗余,版本号控制实现无锁读。通过MVCC可以实现高效的可重复读隔离级别。
间隙锁(Gap lock)
间隙锁与读写锁、互斥锁区别是:读写锁、互斥锁是从锁的方式考虑,而间隙锁是从锁的对象角度考虑。常说的读写锁、互斥锁锁的对象是单个;而间隙锁是锁一个范围内的对象,这个锁可以是读写锁、也可以是互斥锁。幻读问题就是通过间隙锁实现。
记录锁(record lock):单个记录锁 Next key lock:是间隙锁+记录锁,比如next_key_lock锁[5,
10),相当于一个记录锁5和间隙锁(5, 10)组合