数据库事务四种隔离级别
在阅读《高性能MySQL》中第一次接触到了四种隔离级别,遇到了一些疑惑,故对这几种级别进行一下总结
1. 概念
在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。
2. 分类
Read Uncommitted(未提交读)
望文生义,事务中所做的修改,没有修改,对其他事务也可见。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。避免了更新丢失,却可能出现脏读。这也就引出了脏读 的概念,即事务可以读取未提交的数据。
Read Committed(提交读)
一个事务开始时,只能“看见”已经提交的事务所做的修改,也就是说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。该隔离级别避免了脏读,但是却可能出现不可重复读 。即事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
大多数数据库系统的默认隔离级别都是Read Committed(但MySQL不是)
Repeatable Read(可重复读)
读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。避免了不可重复读取和脏读,但是有时可能出现幻读 。所谓幻读 ,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入(删除)记录,当之前的事务再次读取某个范围内的记录时,会产生幻行。这可以通过“共享读锁”和“排他写锁”实现。
可重复读是MySQL的默认事务隔离级别
Serializable(可串行化)
可串行化是最高的隔离级别。它用过强制事务串行执行,避免了前面说的幻读的问题。通过在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题。
表格总结
隔离级别 | 脏读可能性 | 不可重复读可能性 | 幻读可能性 | 加锁读 |
---|---|---|---|---|
Read Uncommitted | YES | YES | YES | NO |
Read Committed | NO | YES | YES | NO |
Repeatable Read | NO | NO | YES | NO |
Serializable | NO | NO | NO | YES |
3. 不可重复读和幻读的区别
不可重复读真正含义应该包含虚读 和幻读 。
所谓的虚读,也就是大家经常说的不可重复读 ,是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
一种更易理解的说法是:在一个事务内,多次读同一个数据。在这个事务还没有结束时,另一个事务也访问该同一数据。那么,在第一个事务的两次读数据之间。由于第二个事务的修改,那么第一个事务读到的数据可能不一样,这样就发生了在一个事务内两次读到的数据是不一样的,因此称为不可重复读,即原始读取不可重复。
简单来说,不可重复读是由其他事务的写操作引起的 。
所谓幻读,是指事务A读取与搜索条件相匹配的若干行。事务B以插入或删除行等方式来修改事务A的结果集,然后再提交。
幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样.一般解决幻读的方法是增加范围锁RangeS,锁定检锁范围为只读,这样就避免了幻读。
简单来说,幻读是由插入或者删除引起的。
4. 参考资料
《高性能MySQL》