innodb事务隔离级别

  SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

Read Uncommitted(读取未提交内容)

在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

Read Committed(读取提交内容)

这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别也支持所谓的不可重复读(Nonrepeatable Read),即在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新了原有的数据,所以同一select可能返回不同结果。

Repeatable Read(可重读)

这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control 间隙锁)机制解决了该问题。注:其实多版本只是解决不可重复读问题,而加上间隙锁(也就是它这里所谓的并发控制)才解决了幻读问题。

Serializable(可串行化)

这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

不可重复读(Non-repeatableread):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新了原有的数据。

幻读(Phantom Read):当对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围时,会发生幻像读问题。事务第一次读的行范围显示出其中一行已不复存在于第二次读或后续读中,因为该行已被其它事务删除。同样,由于其它事务的插入操作,事务的第二次或后续读显示有一行已不存在于原始读中。幻读其实也应该算是一种不可重复读现象,只是它只是相对于insert和delete操作,而上面的不可重复读现象但注重的是update操作。这里这样称呼的原因是insert的新的row是没有版本信息的,它要通过一个范围来确定。

脏读演示

set session transaction isolation level read uncommitted; //设置Read Uncommitted(读取未提交内容)
set autocommit=0; //关闭自动提交

客户端1

客户端2

通过上面两张图可以清楚的看到当tx_isolation=readuncommitted的时候,当一个事务(事务1)修改了数据但并没有提交的时候,另外的事务(事务2)是可以访问到该修改的数据。而此时如果前一个事务又取消了之前的修改(rollback)的时候,那么事务2得到的数据就是一个“脏”数据。

下面我们看一下Read Committed是否有会这种情况。

客户端1

客户端2

通过图3可以看到即客户端2 update了(但还没commit),此时客户端1读到的还是之前的数据,当客户端2真正的commit之后,客户端1才能读到更新后的数据。另外通过图3我们同时可以看到另一个现象,不可重复读,即在一个事务内(客户端1)两次读取的数据不一致。

下面我们看一下在Repeatable Read级别下是否有该现象。

客户端1

客户端2

通过图5可以看到即使客户端2commit之后但客户端1还没commit的话,那么在该事务内的任何时候,访问同一条记录的结果都是一样的。所以repeatable read不存在不可重复读问题。

幻读:其实跟不可重复读差不多,只是幻读指的是行记录数(一个范围),而不可重复读相对的是一条记录。如在事务1里第一次读取这个范围的记录数为10条,但另一个事务删除了这个范围内的某一条记录,这时就会导致事务2的再次读取与第一次读取的结果不一致。Innodb通过MCVV+间隙锁解决了这个问题。所以对于innodb在repeatable read等级上也不会出现幻读。

当前Serializable串行化更不会出现上面的问题

客户端1

客户端2

时间: 2024-10-11 07:59:59

innodb事务隔离级别的相关文章

Innodb中的事务隔离级别和锁的关系

前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在.这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么. #一次封锁or两段锁? 因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道

Innodb中的事务隔离级别和锁的关系(转)

原文:http://tech.meituan.com/innodb-lock.html 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在.这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么. 一次封锁or两段锁? 因为有大量的并

MySQL InnoDB中的事务隔离级别和锁的关系

前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在.这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么. 一.一次封锁or两段锁因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道会

Innodb 中的事务隔离级别和锁的关系

转自:https://tech.meituan.com/innodb-lock.html 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在.这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么. #一次封锁or两段锁?因为有大量的

Mysql InnoDB的四个事务隔离级别和(分别逐级解决的问题)脏读,不可重复读,虚读

MySqlInnoDB的事务隔离级别有四个:(默认是可重复读repeatable read) 未提交读 read uncommit : 在另一个事务修改了数据,但尚未提交,在本事务中SELECT语句可能会查询到这些未被提交的数据,而发生脏读. 提交读 read commit : 在一个事务中发生两次SELECT查询,当第一次SELECT执行完查询到一些数据,接下来另一个事务修改了这些数据并提交了,当第二次SELECT执行的时候查询到的数据和第一次SELECT的不同,而发生不可重复读.幻读问题,但

数据库事务的四大特性和事务隔离级别

Reference: [1] http://www.cnblogs.com/fjdingsd/p/5273008.html [2] http://blog.csdn.net/fg2006/article/details/6937413 数据库事务四大特性 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全

MySQL事务隔离级别详解

SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的.低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销.Read Uncommitted(读取未提交内容) 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果.本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少.读取未提交的数据,也被称之为脏读(Dirty Read).Read Committed(读取提交内容) 这是大多数数据库系统的默认隔离级别(但不是MySQL默认的).

事务隔离级别,操作

然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE. 2 [mysqld] 3 transaction-isolation = REPEATABLE-READ 这里全局默认是REPEATABLE-READ,其实MySQL本来默认也是这个级别 2.对当前session修改,在登录mysql客户端后,执行命令: 要记

mysql-Innodb事务隔离级别-repeatable read详解

http://blog.csdn.net/dong976209075/article/details/8802778 经验总结: Python使用MySQLdb数据库后,如使用多线程,每个线程创建一个db链接,然后再各自创建一个游标cursor,其中第一个线程读一个表中数据为空,第二个写入该表一条数据并提交,第一个线程再读该表数据将仍然无法读出.和多数据库的事务级别应该有关系:还可以在第一个读之前先插入一条,将能够读出第二个线程写入并提交过的数据. 转载自:http://blog.csdn.ne