本文共 2269 字,大约阅读时间需要 7 分钟。
会话1 | 会话2 |
---|---|
begin | begin |
update table set age = 10 where id = 1 | |
select age from table where id = 1 | |
commit | commit / rollback |
会话2将age的值改变,且并未提交,此时会话1select查询结果为10.
如果会话2 最终的结果是commit,那么此查询没有问题 但是如果会话2 最终选择rollback回滚,那么会话1 的查询结果是不正确的。会话1 | 会话2 |
---|---|
begin | begin |
select age from table where id = 1 | |
update table set age = 10 where id = 1 | |
commit | |
select age from table where id = 1 | |
commit |
会话1 两次查询结果不一致,原因是会话2 进行了事务的提交。
需要注意的是两次查询是在同一个事务中的。会话1 | 会话2 |
---|---|
begin | begin |
select age from table where id > 2 | |
insert into table(id,age) values (5,10) | |
commit | |
select age from table where id > 2 | begin |
commit |
会话2 进行了数据的插入或删除操作,并且提交。
MYSQL中(InnoDB引擎)的四种事务隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read Uncommitted (读未提交) | V | V | V |
Read Committed(读已提交) | X | V | V |
Repeatable Read(可重复读)(默认级别) | X | X | V |
Serializable(串行化) | X | X | X |
InnoDB引擎针保证数据一致性的原理:
1.MVCC
在每一行数据中加上两个隐藏字段,记录行的创建时间和过期时间,但实际存储的是版本号,而不是时间,每开启一个新的事物,版本号加一。2.InnoDB实现MVCC的方式:Consistent Read
首先看两个概念 快照读:读取的是快照版本,也就是历史版本 当前读:读取的是最新版本 普通的SELECT就是快照读,而UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE是当前读。 一致性非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过多版本控制(MVVC)读取当前数据库中行数据的方式。如果读取的行正在执行DELETE或UPDATE操作,这时读取操作不会因此去等待行上锁的释放。相反地,InnoDB会去读取行的一个快照。 一致性非锁定读是InnoDB默认的读取方式,即读取不会占用和等待行上的锁。事务隔离级别READ COMMITTED和REPEATABLE READ,InnoDB使用一致性非锁定读。
然而对于快照数据的定义却不同:
READ COMMITTED事务隔离级别下,一致性非锁定读总是读取被锁定行的最新一份快照数据。 而在REPEATABLE READ事务隔离级别下,则读取事务开始时的行数据版本。如果只是有MVCC,并不能保证增删改查一致性:
假设事务A更新表中id=1的记录, 而事务B也更新这条记录,并且B先提交, 如果按照前面MVVC说的,事务A读取id=1的快照版本,那么它看不到B所提交的修改, 此时如果直接更新的话就会覆盖B之前的修改,B的修改就丢失了,这是不允许的。所以,在修改的时候一定不是快照读,而是当前读。
3.间隙锁
防止其他事务在锁定的区域内插入数据,防止了幻读。总结
本来只有 Serializable 隔离级别才可以解决幻读问题, 而实际上由于 InnoDB 快照读 的特性使 Repeatable Read 也解决了幻读问题。 当前读 中的幻读问题,innodb默认为它加入了间隙锁,从而避免出现幻读。使用场景:
快照读(snapshot read)
简单的select操作(不包括 select … lock in share mode, select … for update)当前读(current read)
select … lock in share mode select … for update insert update delete在Repeatable Read(可重复读)(默认级别)下:
快照读 是通过MVVC(多版本控制)实现; 当前读 是通过加record lock(记录锁)和gap lock(间隙锁)来实现的。转载地址:http://tojxi.baihongyu.com/