mysql的事务隔离级别
1.读未提交:能读取其他事务未提交的数据, 脏读幻读不可重复读
2.读已提交:只能读取已提交的数据, 幻读不可重复读
3.可重复读(默认):事务内多次查询的结果是一致的 幻读
4.串行化:所有的事务依次逐个执行,不存在数据不一致的问题
幻读和不可重复读的区别
幻读是新增或删除数据导致的, 不可重复读是对数据的更新导致的
mysql如何解决幻读?
前提:当前事务在RR级别下
MVCC多版本并发控制解决快照读
当前读通过next-key lock(记录锁+间隙锁)解决
首先要了解 快照读 和当前读
在MVCC并发控制中,读操作可以分成两类:快照读与当前读
快照读:普通的select语句就是快照读,读的是历史版本,不用加锁
当前读:读取到的最新版本,常见的update/insert/delete,还有select...for update
select...lock in share mode,并且当前读返回的记录都会加锁,保证其他事务不会修改
mvcc多版本并发控制解决幻读(快照读)
通过记录每行记录后面两个隐藏列
一个列保存了创建时的版本号(行版本号),一个保存了删除的版本号(删除版本号)
每开启一个新事务,系统版本号会自动递增,事务开始时的版本号作为新版本号来和查询到的每行记录的版本号比较
1.select查询时只会查找小于等于事务的版本号
2.行的删除版本要么未定义,要么大于当前事务版本号
insert
为新插入的每一行保存当前的版本号为新版本号
delete
为删除的每一行保存到当前系统的版本号作为删除版本号
update
插入新纪录,保存当前版本号为新版本号,同时保存当前版本号到原来行作为删除版本号
间隙锁Next-key lock防止幻读(当前读)
间隙锁:
MySQL InnoDB支持三种行锁定方式,默认加锁方式是next-key 锁
1.行锁(Record Lock):锁直接加在索引记录上面,锁住的是key
2.间隙锁(Gap Lock):锁定索引记录间隙,确保索引记录的间隙不变。间隙锁是针对事务隔离级别为可重复读或以上级别而已的
3.Next-Key Lock :行锁和间隙锁组合起来就叫Next-Key Lock
当InnoDB扫描索引记录的时候,会首先对索引记录加上行锁(Record Lock),再对索引记录两边的间隙加上间隙锁(Gap Lock)。加上间隙锁之后,其他事务就不能在这个间隙修改或者插入记录
Innodb自动使用间隙锁的条件:
1.必须在RR级别下
2.检索条件必须有索引,(无索引的话会全表扫描,锁定整张表所有的记录)
间隙锁在InnoDB的唯一作用就是防止其它事务的插入操作,以此来达到防止幻读的发生
总结:
间隙锁在InnoDB的唯一作用就是防止其它事务的插入操作,以此来达到防止幻读的发生
对于快照读来说,幻读的解决是依赖mvcc解决。而对于当前读则依赖于gap-lock间隙锁解决