参考
- 官方隔离级别介绍 Transaction Isolation Levels
- 14.7.1 InnoDB Locking
-
share (s) 共享锁(读锁)
-
exclusive (X) 排它锁(写锁)
-
Intention Locks(意向锁) 指出将要对表加什么锁
- IS ex:
SELECT ... LOCK IN SHARE MODE
- IX ex:
SELECT ... FOR UPDATE
- IS ex:
-
Record Locks
-
Gap Locks (间隙锁)
-
Next-Key Locks (间隙锁的组合)
-
- 14.7.2.4 Locking Reads
- 范围锁 MySQL Glossary
- 凤凰架构本地事务
凤凰架构本地事务学习笔记
- 三种锁
- 写锁, 当前事务能读能写,其它事务不能读写
- 读锁, 其它事务能读,但不能写,如果只有一个事务加了读锁(该事务本身),可以加写锁
- 范围锁, 对于某个范围直接加排他锁,在这个范围内的数据不能被写入。(不能这个范围内写入数据)
意“范围不能被写入”与“一批数据不能被写入”的差别,即不要把范围锁理解成一组排他锁的集合。加了范围锁后,不仅无法修改该范围内已有的数据,也不能在该范围内新增或删除任何数据,后者是一组排他锁的集合无法做到的。
- 四种隔离级别(由高到低)
- 串行化: 对事务所有读、写的数据全都加上读锁、写锁和范围锁
- 可重复读: 对事务所有读、写的数据全都加上读、写锁,并且一直持有到事务结束
- 读提交: 对事务所有读、写的数据全都加上读、写锁,写锁一直持有到事务结束,读锁查询结束立刻提交
- 读示提交: 对事务写的数据全都加上写锁,写锁一直持有到事务结束,读根本不锁
为什么忙着释放读锁?
当然是为了并发时的性能!!!
MVCC 是对 “读+写”锁场景下一优化
四种隔离级别有一个共同特点,可重复读、脏读等问题都是由于一个事务在读数据过程中,受另外一个写数据的事务影响而破坏了隔离性。
针对这种“一个事务读+另一个事务写”的隔离问题,近年来有一种名为“多版本并发控制”(Multi-Version Concurrency Control,MVCC)的无锁优化方案被主流的商业数据库广泛采用。MVCC 是一种读取优化策略,它的“无锁”是特指读取时不需要加锁。MVCC 的基本思路是对数据库的任何修改都不会直接覆盖之前的数据,而是产生一个新版副本与老版本共存,以此达到读取时可以完全不加锁的目的。在这句话中,“版本”是个关键词,你不妨将版本理解为数据库中每一行记录都存在两个看不见的字段:CREATE_VERSION 和 DELETE_VERSION,这两个字段记录的值都是事务 ID,事务 ID 是一个全局严格递增的数值,然后根据以下规则写入数据。
- 插入数据时:CREATE_VERSION 记录插入数据的事务 ID,DELETE_VERSION 为空。
- 删除数据时:DELETE_VERSION 记录删除数据的事务 ID,CREATE_VERSION 为空。
- 修改数据时:将修改数据视为“删除旧数据,插入新数据”的组合,即先将原有数据复制一份,原有数据的 DELETE_VERSION 记录修改数据的事务 ID,CREATE_VERSION 为空。复制出来的新数据的 CREATE_VERSION 记录修改数据的事务 ID,DELETE_VERSION 为空。
此时,如有另外一个事务要读取这些发生了变化的数据,将根据隔离级别来决定到底应该读取哪个版本的数据。
- 隔离级别是
可重复读
:总是读取 CREATE_VERSION 小于或等于当前事务 ID 的记录,在这个前提下,如果数据仍有多个版本,则取最新(事务 ID 最大)的。 - 隔离级别是
读已提交
:总是取最新的版本即可,即最近被 Commit 的那个版本的数据记录。
另外两个隔离级别都没有必要用到 MVCC,因为读未提交
直接修改原始数据即可,其他事务查看数据的时候立刻可以看到,根本无须版本字段。可串行化
本来的语义就是要阻塞其他事务的读取操作,而 MVCC 是做读取时无锁优化的,自然就不会放到一起用。
总结
事务的隔离级别
事务并发可能出来的情况
- 脏读 : 一个事务读到了另一个未提交事务修改过的数据
- 不可重复读 : 一个事务只能读到另一个已提交的事务修改过的数据,并且其他事务对该数据进行一次修改并提交后,该事务都能查询得到最新值
- 幻读 : A事务先根据某些条件查询出一些记录,之后B又向表中插入了符合条件的记录,A再次按照该条件查询时,不能把B事务插入的记录读出来,B事务依据此查询写入记录时,如果和B插入的记录一致,会存在冲突(因为B已经插入过了,由于数据库主键约束或者其它原因导致的相同记录不能插入两行)。
事务的隔离级别
下表隔离级别由上到下逐渐升高,级别越低,事务请求的锁越少
事务的隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | √ | √ | √ |
读已提交 | × | √ | √ |
可重复读 | × | × | √ |
串行化 | × | × | × |
MySQL默认是 可重复读