有四种隔离级别,分别是读未提交(Read uncommitted),读已提交(Read committed),可重复读(Repeatable read),可串行化(Serializable),用来解决数据库操作中产生的各种问题。
看懂图需要先了解MVCC,MVCC基本原理-学习笔记-CSDN博客
读未提交
- 在事务读取数据时不做加锁处理直接读取数据版本链中的最新版本。导致出现脏读、幻读、不可重复读
- 在事务更新数据时加上共享行锁,事务结束时释放。结果是数据修改完毕之前其他事务不能修改这行数据但是可以被其他事务读取
读已提交
-
在事务读取数据时不加锁,但使用快照读,即按照MVCC机制读取符合ReadView要求的版本数据。每次查询都会构造一个新的ReadView这样就解决了脏读,但是无法解决不可重复读、幻读
-
在事务更新数据时加上独占行锁,事务结束时释放,这样在事务修改完毕前其他事务不能修改也不能读取这行数据
在这种隔离级别下,所有事务只能读取其他事务已经提交的内容。能够彻底解决脏读的现象。但在这种隔离级别下,会出现一个事务的前后多次的查询中却返回了不同内容的数据的现象,也就是出现了不可重复读。
注意
这是大多数数据库系统默认的隔离级别,例如Oracle和SQL Server,但mysql不是。
可重复读
-
在事务读取数据时同样不加锁使用快照读,但无论几次查询都只会在首次查询时生成一个Readview。这样就解决了脏读、不可重复读,配合Next-Key行锁可以解决一部分幻读的问题
-
在事务更新数据时加上Next-Key行锁,事务结束时释放。这样一个范围内的数据在修改完毕之前其他事务不能修改、插入、删除这个范围内的数据同时也不能被查询,解决了部分幻读的问题
在这种隔离级别下,所有事务前后多次的读取到的数据内容是不变的。也就是某个事务在执行的过程中,不允许其他事务进行update操作,但允许其他事务进行add操作,造成某个事务前后多次读取到的数据总量不一致的现象,从而产生幻读。
注意
这才是mysql的默认事务隔离级别
可串行化
-
在事务读取数据时直接加共享表锁,事务结束时释放,同时均读取版本链中的最新版本。
-
在事务更新时加独占表锁,事务结束时释放,完全串行操作
在这种隔离级别下,所有的事务顺序执行,所以他们之间不存在冲突,从而能有效地解决脏读、不可重复读和幻读的现象。但是安全和效率不能兼得,这样事务隔离级别,会导致大量的操作超时和锁竞争,从而大大降低数据库的性能,一般不使用这样事务隔离级别。
下面用一张表格来表示他们能够解决的问题
当然,以上的内容是一种规范,不同的数据库厂商可以有不同的实现。例如在mysql的可重复读的级别上,使用间隙锁的方式就已经解决了幻读的问题。详细的加锁处理过程可以参考这篇文章【数据库】MySQL 加锁处理分析
#数据库事务隔离级别