MVCC(Multi-Version Concurrency Control)多版本并发控制

文章目录

  • 数据库三种并发场景
  • 什么是快照读和当前读
  • 版本链
    • 为什么MySQL在一定程度上解决了幻读,但没有彻底解决
  • 什么是MVCC
  • MVCC的实现原理
  • MVCC下InnoDB的增删改查时版本号是怎么变更的
  • undo log日志
  • MVCC适用条件

数据库三种并发场景

数据库并发场景有三种,分别为:
(1)读-读:不存在任何问题,也不需要并发控制
(2)读-写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读
(3)写-写:有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失

  • 数据库的两种并控制方式
    (1)LBCC Lock-Based Concurrent Control 基于锁的并发控制
    (2) MVCC Muti-Version Concurrent Control 多版本并发控制

什么是快照读和当前读

  • 当前读
    select lock in share mode(共享锁),select for update,update, insert,delete(排他锁),这些操作都是一种当前读。当前读读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。
  • 快照读
    (1)快照读的前提是: 数据库隔离级别是可重复读级别或者读已提交级别
    (2)快照读是基于MVCC(多版本并发控制)机制实现的,用来解决读-写冲突的无锁并发控制,可以简单理解为维持一个数据的多个版本,使得读写操作没有冲突。

注意:快照读是无锁的,当前读是用悲观锁实现的

版本链

读已提交隔离级别下,事务在每次查询的开始都会生成一个独立的ReadView
可重复读隔离级别下,则在第一次读的时候生成一个ReadView,之后的读都复用之前的ReadView。

为什么MySQL在一定程度上解决了幻读,但没有彻底解决

  • MySQL事务中始终使用快照读读取同一份快照,则不会产生幻读。
  • MySQL事务中如果触发了当前读,则会产生幻读,因为当前读每次会读取最新的数据。

注意:begin/start transaction命令并不是一个事务的起点,在执行到它们之后的第一个操作InnoDB表的语句,事务才会真正启动,才会向mysql申请事务id,mysql内部严格安装事务的启动顺序来分配事务id。

什么是MVCC

  • MVCC是大牛们不满意采用悲观锁的方式解决读-写冲突问题而提出的解决方案。
  • MVCC是用来解决读-写冲突的无锁并发控制,为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。
  • 使用MVCC在并发读写数据库时,读写不会互斥,从而提高了并发性能,同时还解决了脏读等问题,但不能解决第一类和第二类数据丢失更新。

MVCC和乐观锁的区别: MVCC用来解决读写冲突问题,乐观锁用来解决写写冲突问题,是MySQL在已提交读(READ COMMITTD)和可重复读(REPEATABLE READ)这两种隔离级别下的事务对于SELECT操作会访问版本链中的记录的过程。

MVCC的实现原理

经典参考文章: MVCC实现机制
MVCC的实现,通过保存数据在某个时间点的快照来实现的。这意味着一个事务无论运行多长时间,在同一个事务里能够看到数据一致的视图。根据事务开始的时间不同,同时也意味着在同一个时刻不同事务看到的相同表里的数据可能是不同的。

一行数据有多个版本,至少有1个版本。

MySQL数据库的每行记录除了自定义的字段外,还有隐藏了DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID等字段,而MVCC就主要依赖这三个字段来实现的。
(1)DB_TRX_ID 最近修改事务ID
记录创建这条记录或最近一次修改这条记录的事务ID

每次开启事务(begin、start transaction),innodb引擎会为这个事务分配事务编号,顺序递增。

(2)DB_ROLL_PTR 回滚指针
用于配合undo日志,指向这行记录的上一个版本(存储于rollback segment里)

(3)DB_ROW_ID
隐藏的自增主键ID,如果该表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引

MVCC下InnoDB的增删改查时版本号是怎么变更的

下图仅限于理解事务版本号是如何变更的
MVCC(Multi-Version Concurrency Control)多版本并发控制_第1张图片

undo log日志

undo log主要分为两种:insert undo log和update undo log

  • insert undo log是事务在insert插入新记录时产生的undo log,只在事务回滚时需要,事务提交后就可以被立即丢弃。
  • update undo log事务在进行update或delete时产生的undo log,不仅在事务回滚时需要,在快照读时也需要,所以不能随便删除。只有在快照读或事务回滚不涉及该日志是,对应的日志才会被purge线程统一清除。

MVCC适用条件

  • MVCC主要作用于支持行锁和事务的数据库模型
  • MVCC手段只适用于MySQL隔离级别中的读已提交和可重复读。
    (1)读未提交:由于能读取到为提交事务的数据,而MVCC的创建版本和删除版本只在事务提交后才会产生。
    (2)串行化:由于会对所涉及到的表加锁,并非行锁
  • MVCC只解决了读已提交和可重复读,没有解决幻读。

你可能感兴趣的:(MySQL数据库,数据库,mysql,java)