[笔记]数据库四种隔离级别以及相关问题(脏读,不可重复读,幻读)
前置知识
事务,即一组保证原子性的数据库操作语句,其中任意一条语句操作失败都会造成整组语句失效,事务只有两种结果,全部执行成功,全部执行失败。任一操作失败,数据库都会回滚至事务操作前。
建议了解:事务四要素ACID
隔离级别
在SQL中定义了4种隔离级别,分别是未提交读,提交读,可重复读,可串行化。每种级别的隔离程度不同,系统开销也不同。(隔离级别越高,系统开销越大,对高并发的支持越低)
未提交读(脏读问题)
即事务之间可见,事务可以读取其他事务过程中尚未提交的数据。
假设存在两个事务A,B,以及某表上的某行数据ROW=1。
事务A: 修改ROW值=2,。。业务操作。。 ,操作失败回滚,
事务B: 获得ROW值=2,。。业务操作。。 ,再次查询ROW值=1,。。业务操作。。,
事务B获得事务A修改的ROW值(2)后,继续进行相关业务操作,后面再次查询ROW值时,由于事务A回滚,事务B再次查询得到了ROW值(1)。
提交读(解决脏读,无法解决不可重复读问题)
事务间不可见,事务只能读取到其他事务提交后产生的结果.
假设存在两个事务A,B,C, 以及某表上的某行数据ROW=1。
事务A: 修改ROW值=2,提交。
事务B: 获得ROW值=1,再次查询获得ROW值=2,再次查询获得ROW值=3
事务C:。。。。。。 ,修改ROW值=3 ,提交
由于隔离级别:提交读,只能读取其他事务提交后的结果,所以能够解决隔离级别:未提交读由于事务回滚所造成的脏读问题,但某些情况下,我们希望在同个事务内,多次查询某一数据的结果是一致的,这就引申出了此隔离级别的问题:不可重复读。在事务过程中,如果其他事务完成提交,那么期间的多次查询的结果可能会不一致,这就是不可重复读。
可重复读(解决脏读、不可重复读,无法解决幻读问题)
事务间不可见,并且保证同一事务中多次读取同样记录的结果是一致的。
假设存在两个事务A,B,C, 以及某表上的某行数据ROW=1。
事务A: 修改ROW值=2,提交。
事务B: 获得ROW值=1,再次查询获得ROW值=1,再次查询获得ROW值=1
事务C:。。。。。。 ,修改ROW值=3 ,提交
防的了已有的,防不了新加的。当事务读取某一范围内的记录时,另外一个事务在此范围内插入了新的数据,此时事务再次查询该范围的记录便会得到新加的数据,即产生幻读问题。
假设存在两个事务A,B, 以及某表上的数据为ROWS[1,2,3]。
事务A: 插入新值ROWS[1,2,3,4],提交。
事务B: 获得ROWS<5的数据[1,2,3],再次查询ROWS<5的数据[1,2,3,4](幻读)
可串行化(解决幻读)
最高隔离级别,强制事务串行执行,可以避免幻读问题
由于此隔离级别会在读取的每一行都加上锁,可能会导致大量超时和锁争用情况。只有非常需要确保数据一致性而且可以接受没有并发的情况下,才考虑采用此级别。
参考
- 高性能MySql
- 大白话讲解脏写、脏读、不可重复读和幻读