MVCC(Multi-Version Concurrency Control)是一种并发控制机制,用于解决数据库并发访问中,数据一致性问题。它通过在读写操作期间保存多个数据版本,以提供并发事务间的隔离性,从而避免了传统的锁机制所带来的资源争用和阻塞问题。
所谓的一致性问题,就是在并发事务执行时,应该看到那些数据和不应该看到那些数据。
为了解决并发事务存在的脏读、不可重复读、幻读等问题,数据库大叔设计了四种隔离级别。
数据库是通过加锁,来实现事务的隔离性的。加锁确实好使,可以保证隔离性。比如串行化隔离级别就是加锁实现的。从而避免了脏读、不可重复读、幻读的问题。但是频繁的加锁,导致读数据时,没办法修改,修改数据时,没办法读取,大大降低了数据库性能。
那么,如何解决加锁后的性能问题的?
答案就是:MVCC多版本并发控制! 它实现读取数据不用加锁,可以让读取数据同时修改。修改数据时同时可读取。
四大隔离级别中的 读已提交(RC) 和 可重复读(RR) 隔离级别就是通过MVCC来实现的。
快照读:是指在一个事务中,读取的数据版本是在事务开始时已经存在的数据版本,而不是最新的数据版本。这种读取方式提供了事务在执行期间看到的数据视图的一致性,select 查询就是快照读。
当前读:是指在事务中读取最新的数据版本,以下几种操作都是快照读:
MVCC 主要是依靠以下三部分实现的:
Undo Log 主要是用于数据库中事务回滚的,但在 MVCC 机制中也发挥着重要的作用。
Undo Log 版本链是指在每个数据对象上维护的 Undo Log 记录链表。每张表都会有与之相对应的 Undo Log 版本链,用于记录修改前的数据信息(以方便数据进行回滚)。
Read View(读视图)用于管理事务之间数据可见性的一种机制。Read View 在特定时刻为事务创建的一个快照,该快照包含了在该时刻所有未提交事务的事务标识符,以及其他一些辅助信息。
在 Read View 中包含了以下 4 个主要的字段:
解释:
活跃的事务编号:指的是已经创建,但未commit的事务,即处理中的事务id。
RC 级别中,每次快照读都会生成一个全新的 Read View,而 RR 级别中同一个事务会复用一个 Read View。
有了 Read View 和 Undo Log 链之后,并发事务在查询时就知道要读取那些数据了。
判断方法是根据 Read View 中的 4 个重要字段,先去 Undo Log 中最新的数据行进行比对,如果满足下面 Read View 的判断条件,则返回当前行的数据,如果不满足则继续查找 Undo Log 的下一行数据,直到找到满足的条件的数据为止,如果查询完没有满足条件的数据,则返回 NULL。
对于删除的情况,会将版本链的最新数据复制一份,然后将trx_id修改成删除操作的trx_id,同时会在记录的头信息的标记位(delete_flag)上设置true,用来表示已经删除,在查询时,如果对应记录的delete_flag为true,则表示已经被删除,就不会返回数据。
以上判断规则从 Undo Log 最新的行数据,逐行对比,直到找到匹配的数据,否则查询完未匹配上,则返回 NULL。
MVCC 的实现主要依赖读视图 Read View 和 Undo Log 链,通过 Read View 中的 4 个字段,判断要读取 Undo Log 中数据,从而解决了数据库并发访问中,数据一致性的问题。
MVCC 主要应用于 InnoDB 引擎中的 RC 事务隔离级别和 RR 隔离级别,其中 RC 隔离级别每次快照读都会生成一个新的 Read View,而 RR 隔离级别只在第一次快照读时生成 Read View,之后会复用 Read View,从而解决了(部分)幻读问题。
MVCC是一种用于解决数据库并发问题的乐观锁技术,多版本并发控制通过保存数据在某个时间点的快照来实现。换句话说,读操作不会阻塞写操作,写操作也不会阻塞读操作,以此来提高数据库性能。在每次对数据的操作,都用在undo日志版本链中进行。