事务隔离级别:可重复读

MySQL [pom_5]> select @@global.tx_isolation;

+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ       |
+-----------------------+

若是事务隔离级别显示REPEATABLE-READ,便是可重复读。html

事务的四种隔离级别

(引自: Innodb中的事务隔离级别和锁的关系)sql

在数据库操做中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。咱们的数据库锁,也是为了构建这些隔离级别存在的。数据库

隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read)
未提交读(Read uncommitted) 可能 可能 可能
已提交读(Read committed) 不可能 可能 可能
可重复读(Repeatable read) 不可 不可 可能
可串行化(Serializable ) 不可能 不可能 不可能

未提交读(Read Uncommitted):容许脏读,也就是可能读取到其余会话中未提交事务修改的数据bash

提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)并发

可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,可是还存在幻象读性能

串行读(Serializable):彻底串行化的读,每次读都须要得到表级共享锁,读写相互都会阻塞测试

可重复读和幻读

在可重复读中,该sql第一次读取到数据后,就将这些数据加锁(悲观锁),其它事务没法修改这些数据,就能够实现可重复读了。但这种方法却没法锁住insert的数据,因此当事务A先前读取了数据,或者修改了所有数据,事务B仍是能够insert数据提交,这时事务A就会发现莫名其妙多了一条以前没有的数据,这就是幻读,不能经过行锁来避免。须要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么作能够有效的避免幻读、不可重复读、脏读等问题,但会极大的下降数据库的并发能力。code

可是MySQL、ORACLE、PostgreSQL等成熟的数据库,出于性能考虑,都是使用了以乐观锁为理论基础的MVCC(多版本并发控制)来实现。htm

实际测试结果

对相同db实例建立两个链接:a和b,来测试select, select for update, update语句的生效状况事务

不使用select for update行级锁

a先提交 b先提交
a先开启事务 b的update内容 a的update内容
a先开启事务 b的update内容 a的update内容

结果是谁最后提交,谁的结果生效

a先使用select for update, update行级锁

a使用select for update a使用select for update a使用update
a开启事务,b不开启 b里面的select for update和update被阻塞 b不受影响 b里面的select for update和update被阻塞
a不开启事务,b开启 b不受影响 b不受影响 b不受影响
a,b开启事务 b里面的select for update和update被阻塞 b不受影响 b里面的select for update和update被阻塞
a,b不开启事务 b不受影响 b不受影响 b不受影响

结果是只有使用begin显式开启事务时,使用select for update才会对数据加上行级锁,对其余链接的的select for update(对select没有影响)和update形成阻塞效果。

a上锁后修改提交,b读取到的内容

下面是a开启事务,而后使用a使用select for update,接着b使用select for update/select,a执行updat,最后commit,观察整个过程当中b的查询效果。

b使用select for update b使用select
b开启事务 b里面的select for update被阻塞,a提交后,b读到的是a修改的内容 b不受a阻塞,读到的还是b事务开启时的内容
b不开启事务 b里面的select for update被阻塞,a提交后,b读到的是a修改的内容 b不受a阻塞,读到的数据在a提交后变化

在链接a使用begin开启事务以后,select for update和update对链接b的阻塞效果

a先执行select for update a先执行update
b后执行select 未阻塞 未阻塞
b后执行select for update 阻塞 阻塞
b后执行update 阻塞 阻塞
相关文章
相关标签/搜索