MySQL的幻读

134 阅读3分钟

1、 什么是MySQL的幻读

"幻读"(Phantom Read)是数据库并发控制中的一个概念,指的是一个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入新的记录,当之前的事务再次读取该范围的记录时,会发现有些新的“幻影”记录。

更具体的说,幻读是在数据库事务中发生的现象,当一个事务(T1)在读取几行记录后,另一个并发的事务(T2)可能会插入一些记录。当事务T1再次读取原来的记录时,会发现有新的“幻影”记录,这些是在T1读取后被T2插入的。

与"非重复读"(Non-repeatable Read)相比,非重复读关注的是已有记录的修改,而幻读关注的是新记录的插入。

为了防止幻读,可以使用更严格的隔离级别,比如MySQL的可串行化(SERIALIZABLE)级别。在这种隔离级别下,事务串行执行,因此并发事务无法插入“幻影”记录。然而,这种级别的隔离会对数据库性能产生较大影响,因此在实际应用中需要根据具体情况进行权衡。

2. MySQL的Repeatable Read(RR)隔离级别解决幻读(Phantom Read)问题了吗?

在MySQL中,使用InnoDB存储引擎的情况下,Repeatable Read(RR)隔离级别可以解决幻读(Phantom Read)问题。这主要是因为InnoDB存储引擎在这个隔离级别下使用了一种称为"next-key locking"的技术来防止幻读问题。

在其他数据库系统中,Repeatable Read隔离级别可能不能解决幻读问题,因为它们可能没有实现像InnoDB那样的next-key locking机制。在这些系统中,通常需要使用更高的隔离级别,如Serializable,来防止幻读问题。

需要注意的是,尽管InnoDB的Repeatable Read隔离级别可以防止幻读,但它可能无法防止其他一些并发问题,如非可重复读(Non-Repeatable Read)或丢失更新(Lost Update)。因此,选择适当的隔离级别应根据特定应用的需求和特点来决定。

3.采用所谓的next-key lock解决幻读的问题,那会带来什么问题呢?

MySQL的InnoDB存储引擎在Repeatable Read(RR)隔离级别下使用Next-Key Locking确实可以大大减少幻读(phantom reads)的发生。然而,它并不能解决所有的问题。在某些场景中,可能会有所谓的"间隙锁异常"(gap locks anomaly),这是因为间隙锁可能会锁住比实际需要更多的范围,这可能导致一些无法预期的行为。

例如,假设一个事务在一个范围上设置了间隙锁,防止新的记录被插入。然而,这可能会阻止另一个事务在该范围内的一个完全不同的键上插入记录,即使这两个键在业务逻辑上是完全不相关的。这是因为InnoDB的间隙锁是在索引层面上实现的,而不是在业务逻辑层面。因此,它可能会阻止一些实际上应该被允许的操作。

所以,虽然Next-Key Locking可以防止幻读,但它并不是没有问题。在设计数据库和事务时,你需要仔细考虑你的具体需求,并确保你了解所选择的隔离级别的行为和潜在问题。