MySQL中各事务隔离级别的底层原理

MySQL中的锁类型

  • 排它锁:写锁或X-Lock,持有X-Lock的事务才能对数据进行写操作,加持X-Lock的数据不能被其它事务修改,不能再被其它事务加持读锁(但可以被其它事务直接读)。
  • 共享锁:读锁或S-Lock,多个事务可以对同一数据添加多个读锁,加读锁的数据不能再被其它事务加持写锁,故不能对其它事务写;数据只有一个读锁,则可自动升级为写锁
  • 范围锁:Rang-Lock,对某个范围的数据加排它锁,不能被其它事务读取和写入;范围锁在不同数据库下有不同实现,mysql内部的实现包括Next-key Lock(临键锁,后码锁,MySQL排它锁默认都是临键锁)和Gap-Lock(间隙锁)

MySQL中的读操作类型

快照读:MySQL默认是快照读,即首次读取的时候会创建快照,同一事务内后续select读快照,RR级别可能会读到历史数据

当前读:update/delete/insert/select***for update等采用当前读,会读最新的数据

MySQL事务隔离级别

读未提交

含义:在一个事务中读取到另一个事务未提交的数据
存在的问题:脏读,在一个事务中读取到另一个事务未提交的数据
读未提交实现原理:读未提交对事务涉及到的数据只加写锁,这会一直持续到事务结束,但完全不加读锁。注意:加写锁的数据不能被其它事务加读锁和写锁,但可以被其它数据直接读
举例说明

SELECT * FROM books WHERE id = 1;               /* 时间顺序:1,事务: T1 ,读操作完全不加读锁*/
UPDATE books SET price = 90 WHERE ID = 1;          /* 时间顺序:2,事务: T2 ,加写锁直到事务结束*/
SELECT * FROM books WHERE id = 1;                /* 时间顺序:3,事务: T1 ,读操作完全不加读锁*/
COMMIT;                            /* 时间顺序:4,事务: T2 */

读已提交

含义:在一个事务中能读到其它事务提交的数据
存在的问题:不可重复读,即在同一事务中对同一行数据的两次查询得到的结果不同
读已提交实现原理:读已提交对涉及的数据加的写锁会一直持续到事务结束,但加的读锁在查询操作完成后会立马释放
举例说明

SELECT * FROM books WHERE id = 1;               /* 时间顺序:1,事务: T1 */
UPDATE books SET price = 110 WHERE ID = 1; COMMIT;      /* 时间顺序:2,事务: T2 */
SELECT * FROM books WHERE id = 1; COMMIT;           /* 时间顺序:3,事务: T1 */

可重复读

含义:在同一事务中对同一行数据的两次查询得到的结果一定相同
按照数据库标准定义中存在的问题:幻读,在同一事务中,两个相同的范围查询得到不同的结果集
MySQL的解决方案:MVVC+临键锁(临键锁也是一种范围锁,所以可以理解为MySQL对可重复读这个隔离级别的实现没有按照标准来)
可重复读实现原理:可重复读对事务涉及的数据加读写锁,直到事务结束,但不会加范围锁
举例说明

SELECT count(1) FROM books WHERE price < 100          /* 时间顺序:1,事务: T1 */
INSERT INTO books(name,price) VALUES ('深入理解Java虚拟机',90)  /* 时间顺序:2,事务: T2 */
SELECT count(1) FROM books WHERE price < 100          /* 时间顺序:3,事务: T1 */

串行化

原理:对事务所有读写涉及到的数据都加上读锁、写锁和范围锁

你可能感兴趣的:(MySQL中各事务隔离级别的底层原理)