InnoDB存储引擎MVCC

一、MVCC是什么

MVCC,全称Multi-Version Concurrency Control 多版本并发控制,MVCC是一种并发控制方法,一般在数据库管理系统中,实现对数据库的并发访问;在编程语言中实现事务的内存。那InnoDB存储引擎是如何实现MVCC呢,首先InnoDB存储引擎MVCC是通过表记录隐藏列的事务ID和回滚指针、undo log、read view来实现的。

二、MVCC实现原理

刚才提到InnoDB存储引擎MVCC是通过表记录隐藏列、undo log、read view来实现,以下是对它们作用进行详解。

表记录隐藏列

表记录有三个隐藏字段分别是:

  • DB_ROW_ID:隐藏的自增主键ID,当表没有主键时InnoDB会自动创建DB_ROW_ID并把它作为主键。
  • DB_TRX_ID:最近修改(update、insert、delete)表记录的事务ID。
  • DB_ROLL_ID:回滚指针,指向这条记录的上一版本。

看了这些表记录隐藏列可能有些抽象,我们通过表格来展示可能更直观,如下student表记录:

name age sex DB_ROW_ID DB_TRX_ID DB_ROLL_ID
张三 18 1 100 0x1234567

undo log

undo log是InnoDB实现MVCC很重要的组成部分。我们在修改(update、insert、delete)数据时就会产生undo log。undo log日志分两种:

  • insert undo log:事务在insert新记录时会产生undo log,只在事务回滚时需要,因此事务提交后该undo log会直接被删除。
  • update log:事务对记录进行update和delete操作会产生undo log,该undo log有可能需要提供MVCC机制,因此事务提交时不能删除而是放到undo链表,只有等所有事务所使用快照不涉及该undo log才会被purge工作线程回收。

read view

当事务执行sql查询语句时就会执行快照读,实际上是创建一个read view读视图,read view会记录3个非常重要的属性:

  • m_ids:当前系统中所有活跃的事务id,活跃事务是指当前系统开启但没有提交的事务。

  • min_trx_id:m_ids事务数组最小事务id值。

  • max_trx_id:当前系统中已创建的最大事务id。

read view会根据这3个属性,结合undo log版本链实现MVCC机制,决定一个事务对那些数据可见,那些数据不可见。以下是read view和undo log版本链比对规则:

  1. 当前行数据row_trx_id
  2. 当前行数据row_trx_id>max_trx_id,表示这数据是在当前事务开启后,过段时间又有新的事务开启修改了该行数据,因此当前事务对该行数据是不可见的。
  3. 当前行数据row_trx_id即min_trx_id<=row_trx_id<=max_trx_id,需要分两种情况:如果row_trx_id是属于m_ids的事务id,表示其他事务修改了这行数据但没有提交事务,因此对当前事务是不可见的。如果row_trx_id不在m_ids事务数组中,对当前事务是可见的。

这里有两点需要注意:
1.当前行数据row_trx_id等于当前事务id,那么当前行数据对当前事务是可见的。
2.当前行数据row_trx_id不在m_ids数组中,又小于max_trx_id,在已提交读隔离级别会出现这种想象。

通过上面undo log版本链比对规则我们可以总结大概流程,在执行select语句时会产生read view,然后拿当前修改最新记录中DB_TRX_ID和read view的属性值进行比对,如果不可见就取出DB_ROLL_PTR回滚指针去取出undo log中版本的DB_TRX_ID继续比较,相当于遍历链表,直到找到符合条件为止,此时的DB_TRX_ID是当前事务能看到最新的老版本数据。

三、MVCC作用

MVCC是一种用来解决读写冲突无锁的并发多版本控制,也就是在读的时候不会阻塞其他事务写操作,写操作不会阻塞其他事务读数据,提高了数据库读写并发性能。在InnoDB存储引擎已提交读事务隔离级别使用MVCC机制当前事务每次执行select语句会创建新的readview,因此解决了脏读,在可重复读事务隔离级别使用MVCC机制当前事务执行select语句时只创建一次readview,因此解决了脏读、不可重复、幻读。

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