并发事物带来的问题
脏读:一个事物读取到另外个事物修改未提交的数据
丢失修改:两个事物对数据进行了相同的修改
不可重复读:事物提交前重复读取结果不一致(另外个事物可修改数据导致)
幻读:事务的两次查询的结果集记录数不一致(受INSERT和DELETE影响的不可重复读的一种特殊场景)
数据库隔离级别
READ-UNCOMMITTED(读取未提交):最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
READ-COMMITTED(读取已提交):允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
REPEATABLE-READ(可重复读):多次读取数据和第一次结果一致,mysql默认隔离级别,可能发生幻读。
SERIALIZABLE(可串行化):最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读
MVCC如何防止幻读
InnoDB
存储引擎在 RR 级别下通过 MVCC
和 Next-key Lock
来解决幻读问题
1、执行普通 select
,此时会以 MVCC
快照读的方式读取数据
在快照读的情况下,RR 隔离级别只会在事务开启后的第一次查询生成 Read View
,并使用至事务提交。所以在生成 Read View
之后其它事务所做的更新、插入记录版本对当前事务并不可见,实现了可重复读和防止快照读下的 “幻读”
2、执行 select...for update/lock in share mode、insert、update、delete 等当前读
在当前读下,读取的都是最新的数据,如果其它事务有插入新的记录,并且刚好在当前事务查询范围内,就会产生幻读!InnoDB
使用 Next-key Lock (opens new window) 来防止这种情况。当执行当前读时,会锁定读取到的记录的同时,锁定它们的间隙,防止其它事务在查询范围内插入数据。只要我不让你插入,就不会发生幻读