内容简介:自我理解: MVCC可以允许非阻塞式读, 在锁操作时只锁定必要的记录。锁保证更新的并发性,MVCC主要保证读的并发性和锁时只锁必要的记录。 线程该不该看到别的线程操作的东西因为innodb为了读的并发性使用的是非锁定读,所以在读的时候使用MVCC来保证事务更新的隔离性
自我理解: MVCC可以允许非阻塞式读, 在锁操作时只锁定必要的记录。
锁保证更新的并发性,MVCC主要保证读的并发性和锁时只锁必要的记录。 线程该不该看到别的线程操作的东西
因为innodb为了读的并发性使用的是非锁定读,所以在读的时候使用MVCC来保证事务更新的隔离性
目录
5.2 为什么insert undo log对其他事务不可见?
1.InnoDB MVCC 简介
InnoDB是一个多版本的存储引擎:为了支持事务的一些特性诸如并发和回滚,它保持着被修改行的旧版本信息。这些信息被存储在一个被叫做回滚段( rollback segment) 的表空间中。InnoDB在回滚段中用这些信息来执行undo操作,以此支持事务回滚。它也用这些信息来构造行的更早的版本,以此支持一致性读(快照读)。
Multi-Version Concurrency Control 多版本并发 控制
前置知识: 隔离级别
2.InnoDB 实现MVCC的方式
MVCC只在repeatable-read和read-committed两个隔离级别下才工作,其他两个隔离级别都和MVCC不兼容,因为read uncommitted总是读取最新的数据行,而不是符合当前事务版本的数据行,而serializeble则会对所有读取的行都加锁(与多版本 并发相悖)。
在REPEATABLE READ隔离级别下,InnoDB MVCC是如何操作的:
-
SELECT
InnoDB 会根据以下两个条件检查每行记录 :
a. InnoDB只查找版本早于当前事务版本的行数(也就是,行的系统版本号小于或等于事物的系统版本号),这样可以确保事务读取的行,要么是事务开始前已经存在,要么是事务自身插入或者修改的。
b. 行的删除版本要么未定义,要么大于当前事务版本号。这样可以确保事务读取到的行,在事务开始前没有被删除。
-
INSERT
InnoDB为新插入的每一行保存当前的系统版本号作为行版本号。
-
DELETE
InnoDB为删除的每一行保存当前的系统版本号作为删除版本号。 -
UPDATE
InnoDB为新插入的每一行保存当前的系统版本号作为行版本号,同时保存当前版本号直到原来的行作为删除标识。
MVCC在RR和RC隔离级别下的区别:在RR隔离级别下,一个事务只能读取到事务开始的那个时刻的数据快照,在RC隔离级别下,事务总是读取数据行的最新快照,即会产生不可重复读的问题。
RC是语句级多版本(事务的多条只读语句,创建不同的ReadView,代价更高),RR是事务级多版本(一个ReadView);
3.InnoDB行记录格式
InnoDB支持多种行格式,大同小异,以Compact行记录为例,
变长字段长度列表 | NULL标识位 | 记录头信息(包含删除标记) | RowID | TransactionID | Roll Pointer | 列1数据 | 列2数据 | ….. |
---|---|---|---|---|---|---|---|---|
在内部,InnoDB为数据库中存储的每一行添加三个隐藏字段。
- DB_TRX_ID: 表明插入或者修改这一行的最后一个事务的事务标识符。 如何查看行事务ID
- DB_ROLL_PTR: 指向回滚段中的一个undo log记录,如果行被修改了,那么这个undo log记录包含的信息必须先于行修改被重新修改。
- DB_ROW_ID: 单调递增的行ID。如果InnoDB自动生成了一个聚集索引,那么这个索引包含行ID值,否则DB_ROW_ID列不会出现在任何索引中。
delete在内部被当做update来对待,就是在行的特定位做一个标记,以表明这一行已经被删除。
可以把一条记录看成一个链表。
4.Read View与可见性
一致非锁定读,也可以称为快照读,即普通SELECT语句,既然是快照读,故 SELECT 的时候,会生成一个快照。
生成快照的时机:事务中第一次调用SELECT语句的时候才会生成快照,在此之前事务中执行的update、insert、delete操作都不会生成快照。
不同事务隔离级别下,快照读的区别:
READ COMMITTED 隔离级别下,每次读取都会重新生成一个快照,所以每次快照都是最新的,也因此事务中每次SELECT也可以看到其它已commit事务所作的更改;
REPEATED READ 隔离级别下,快照会在事务中第一次SELECT语句执行时生成,只有在本事务中对数据进行更改才会更新快照,因此,只有第一次SELECT之前其它已提交事务所作的更改你可以看到,但是如果已执行了SELECT,那么其它事务commit数据,你SELECT是看不到的。
简单来说,Read View记录读开始时,所有的活动事务,这些事务所做的修改对于Read View是不可见的。除此之外,所有其他的小于创建Read View的事务号的所有记录均可见。可见包括两层含义:
- 记录可见,且Deleted bit = 0;当前记录是可见的有效记录。
- 记录可见,且Deleted bit = 1;当前记录是可见的删除记录。此记录在本事务开始之前,已经删除。
4.1 事务链表
事务在开始后到被提交的过程中,会被存储到事务链表中。当事务提交或回滚后,将其从事务链表中删除。
事务35事务39事务40事务41trx_sys
4.2 Read View结构
在事务中执行第一条语句(查询或更新都可以)后,会生成一个Read View。
Read View主要包含3个成员:
-
low_limit_id:表示创建read view时,当前事务活跃读写链表最大的事务ID,即最近创建的除自身外最大的事务ID
-
up_limit_id:表示创建read view时,当前事务活跃读写链表最小的事务ID。
-
trx_ids:创建read view时,活跃事务链表里所有事务ID
例子:对于4.1中的事务40 low_limit_id=41,up_limit_id=35,trx_ids={35,39,40,41}
4.3 可见性判断
可见行判断是基于行的,所有数据行上都有最后操作的事务ID( DB_TRX_ID )。
-
如果 DB_TRX_ID 小于 up_trx_id(查询开始时最小的活跃事务ID) 的记录,说明修改该行的事务在当前事务开启之前都已经提交完成,所以对当前事务来说,都是可见的。
-
如果 DB_TRX_ID 大于 low_trx_id(查询开始时最大的活跃事务ID) 的记录,说明修改该行记录的事务在当前事务之后,所以对于当前事务来说是不可见的。
-
如果 DB_TRX_ID 介于 low_trx_id与low_trx_id 之间,则需要区分隔离级别
-
RR级别要求可重复读,所以已经开始的事务链表中的事务的所有修改都是不可见的,所以对于当前事务来说是不可见的。
-
RC级别要求读最新的记录,所以已经开始的事务链表中的事务提交后是可见的。
-
5.Undo log格式
Undo log分为insert undo log 和update undo log。insert undo log对其他事务不可见,所以插入完成后就会丢弃。
MVCC相关的是update undo log。此处介绍的是update undo log的格式。
next | 2字节,记录的是下一个undo log的位置 |
---|---|
type_cmpl | 1字节,记录的是Undo的类型,对于insert undo log 该值总是为11 |
*undo no | |
*table id | 记录undo log所对应的表 |
info_bits | |
*DATA_TRX_ID | 旧事务的ID |
*DATA_ROLL_PTR | 旧记录回滚段的指针 |
5.1 insert undo log有什么用?
insert 需要回滚时可以用insert undo log 进行数据删除。
5.2 为什么insert undo log对其他事务不可见?
首次插入,不存在多版本问题,可以直接根据该行的隐藏事务ID来判断是否可见。
5.3 那第一条记录插入后的读取的都是当前行?
是的
6.各写操作下Undo log的变化
Undo Log的两个用处分别是:MVCC和Rollback。所以可以认为Undo log存储的是事务的逆操作(编辑一行存一条)。
可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。实际不是,但是这样容易理解。
6.1 Insert操作
- 产生一条insert undo log,并在事务提交后删除。
6.2 Update操作
- 如果未更新主键列,在undo log中直接反向记录是如何update的。即update是直接进行的。
- 如果更新了主键列,update分两部执行:先删除该行,再插入一行目标行。
6.3 Delete操作
- 不会真实删除数据,而是把该行标记为删除,最终删除是由purge进行的。
6.4 Select
- 读取记录行,如果当前记录不可见,根据db_roll_ptr回溯历史记录
MySQL MVCC实现 &version=12020810&nettype=WIFI&fontScale=100&pass_ticket=lvYDkS697l2%2FqlJyvzV9O3xv0CkyvL1Nllw4n%2FZEIf9PD6D2JBaFFaJ2Bhg9Y2bg)
《MySQL技术内幕 InnoDB存储引擎》
《高性能MySQL》
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。