MySQL优化--MVCC

目录

概念

MVCC的具体实现

隐式字段

undo log日志

概念

undo log版本链

readview


接上文,redo log保证了事务的持久性,undo log 保证了事务的原子性和一致性

那,隔离性是如何保证的呢?

锁:排他锁(如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁

mvcc : 多版本并发控制

概念

全称 Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突

MySQL优化--MVCC_第1张图片

mvcc最主要的功能就是在多个事务并发的情况下,确定应该并发的访问哪个版本

MVCC的具体实现

主要依赖于数据库记录中的隐式字段undo log日志readView

隐式字段

MySQL优化--MVCC_第2张图片

 

 我们在表中自定义了id,age,name字段,但其实内部还隐藏了三个mysql提供的字段

隐藏字段

含义

DB_TRX_ID

最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID

DB_ROLL_PTR

回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。

DB_ROW_ID

隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。

undo log日志

概念

回滚日志,在insertupdatedelete的时候产生的便于数据回滚的日志

insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除

updatedelete的时候,产生的undo log日志不仅在回滚时需要,mvcc版本访问也需要,不会立即被删除

undo log版本链

MySQL优化--MVCC_第3张图片

假如此时同时有四个事务同时操作。

先来看事务2,此时会先把原来的数据记录到日志中

MySQL优化--MVCC_第4张图片MySQL优化--MVCC_第5张图片

 事务3,此时会重新记录旧数据

 MySQL优化--MVCC_第6张图片MySQL优化--MVCC_第7张图片

事务4也是同理,综上所述,我们可以知道:不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录。

但是,问题来了?事务5呢,事务5进行了两次查询,两次查询返回的内容一样吗?执行的结果一样吗?这个就不是undo log版本链可以决定的了,他只是做一个记录,具体的判断依据就是readview 

readview

ReadView(读视图)是 快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。

当前读

读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select ... lock in share mode(共享锁)select ... for updateupdateinsertdelete(排他锁)都是一种当前读。

快照读

简单的select(不加锁)就是快照读,快照读,读取的是记录数据的可见版本,有可能是历史数据不加锁,是非阻塞读。

而这个也与隔离级别有关

Read Committed:每次select,都生成一个快照读。

Repeatable Read:开启事务后第一个select语句才是快照读的地方。

四大核心字段:

字段

含义

m_ids

当前活跃的事务ID集合

min_trx_id

最小活跃事务ID

max_trx_id

预分配事务ID,当前最大事务ID+1(因为事务ID是自增的)

creator_trx_id

ReadView创建者的事务ID

MySQL优化--MVCC_第8张图片

 以图中标红位置为例,当执行到红框位置时,

m_ids就是事务3,事务4,事务5

min_trx_id就是事务3

max_trx_id就是事务6(预分配事务,最大事务+1

creator_trx_id就是事务5

其中,ReadView为了能获取快照读中最准确的数据,它定义了一些数据访问的规则

MySQL优化--MVCC_第9张图片

 不同的隔离级别,生成ReadView的时机不同

READ COMMITTED :在事务中每一次执行快照读时生成ReadView

RC隔离级别下,在事务中每一次执行快照读时生成ReadView。

MySQL优化--MVCC_第10张图片

REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView

MySQL优化--MVCC_第11张图片

面试回答

MySQL优化--MVCC_第12张图片

面试官:事务中的隔离性是如何保证的呢?(你解释一下MVCC)

候选人:事务的隔离性是由锁和mvcc实现的。 其中mvcc的意思是多版本并发控制。指维护一个数据的多个版本,使得读写 操作没有冲突,它的底层实现主要是分为了三个部分,第一个是隐藏字段, 第二个是undo log日志,第三个是readView读视图。

隐藏字段是指:在mysql中给每个表都设置了隐藏字段,有一个是trx_id(事 务id),记录每一次操作的事务id,是自增的;另一个字段是roll_pointer(回 滚指针),指向上一个版本的事务版本记录地址

undo log主要的作用是记录回滚日志,存储老版本数据,在内部会形成一个 版本链,在多个事务并行操作某一行记录,记录不同事务修改数据的版本, 通过roll_pointer指针形成一个链表

readView解决的是一个事务查询选择版本的问题,在内部定义了一些匹配规 则和当前的一些事务id判断该访问那个版本的数据,不同的隔离级别快照读 是不一样的,最终的访问的结果不一样。如果是rc隔离级别,每一次执行快 照读时生成ReadView,如果是rr隔离级别仅在事务中第一次执行快照读时生 成ReadView,后续复用

 

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