MySQL - mvcc
mvcc 是什么?
MVCC(多版本并发控制)是一种数据库并发控制机制,旨在提高数据库的并发性,避免锁定操作,从而减少等待和提高性能。MVCC 主要解决数据库读写操作之间的线程安全问题。
MVCC 主要有两种读取数据的方式:
-
快照读(Snapshot Read) :
- 快照读是一种普通的查询操作(例如 SELECT 语句),在读取数据时不需要加锁。
- 这意味着多个事务可以同时进行快照读操作,而不会争夺读取锁,从而提高了读取效率。
- 但快照读可能会读取到历史版本的数据,因为它不阻止其他事务对数据进行更改。
-
当前读(Current Read) :
- 当前读是一种悲观锁的操作,它会对读取的数据进行加锁,以确保读取的数据是最新的版本。
- 例如,使用
SELECT ... FOR UPDATE
或SELECT ... LOCK IN SHARE MODE
进行当前读,或在更新、插入和删除操作中使用排他锁。 - 当前读保证了数据的一致性,但会导致读写操作之间的争用,可能降低并发性能。
MVCC 的优势在于它允许读取操作并发执行而不争夺锁,从而提高了数据库的并发性和性能。同时,MVCC 也能够保证数据的一致性,因为它允许读取到历史版本的数据,而不会读取到正在被其他事务修改的数据。
事务的特性与MVCC实现:
- MVCC 通过数据版本控制来支持事务的特性。
- 原子性(A)通过
undolog
实现,持久性(D)通过redolog
实现,一致性(C )是通过undolog
、redolog
和隔离性(I)一起实现的。以我的理解就是AID -> C
事务的隔离级别与MVCC:
-
不同的事务隔离级别在MVCC中有不同的实现方式:
- 读未提交:允许读取尚未提交的数据变更,可能导致脏读、幻读或不可重复读。
- 读已提交:允许读取已经提交的数据,可能导致幻读和不可重复读。
- 可重复读:对同一字段的多次读取结果都是一致的,可能导致幻读。
- 可串行化:最高的隔离级别,通过MVCC完全隔离事务。
MVCC实现原理:
-
MVCC的核心实现依赖如下:
trx_id
:事务ID,每次事务操作都会增加。roll_pointer
:回滚指针,用于查找上一个版本的数据,与undolog
协同实现回滚。readview
:读取视图,用于限制当前事务可读取的数据版本。
-
当执行SELECT查询时,数据可能有多个版本,但
readview
决定了当前事务能够读取哪个版本。
MVCC如何实现不同隔离级别:
-
在MVCC中,不同隔离级别:
- 读已提交:每个快照读都生成并获取最新的
readview
,以确保读取已提交的数据版本。 - 可重复读:只有在同一个事务的第一个快照读时才会创建新的
readview
,之后的每次快照读都使用同一个readview
,确保查询结果一致。
- 读已提交:每个快照读都生成并获取最新的
幻读问题的解决:
- 幻读问题是指在并发事务中,一个事务在两次查询之间,另一个事务插入或删除了数据,导致第一个事务看到了不一致的数据。
- MVCC通过版本控制和锁机制来解决幻读问题。在可重复读隔离级别下,通过行锁和间隙锁(gap锁)来阻止其他事务插入或删除相关数据,从而解决幻读问题。