逻辑存储结构
表空间
段
区
页
行
行,InnoDB 存储引擎数据是按行进行存放的。
在行中,默认有两个隐藏字段:
Trx_id:每次对某条记录进行改动时,都会把对应的事务id赋值给trx_id隐藏列。
结构
内存结构
磁盘结构
事务原理
redo log
重做日志,记录的是事务提交时数据页的物理修改,是用来实现事务的持久性该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中, 用于在刷新脏页到磁盘,发生错误时, 进行数据恢复使用。
![](https://img-blog.csdnimg.cn/a3e3cf1aebe241e9aafe0b0e5aeef899.png)
![](https://img-blog.csdnimg.cn/8552e4abc7bb46a9b7c7e06cb27ab669.png)
undo log
Undo log存储:undo log采用段的方式进行管理和记录,存放在前面介绍的 rollback segment 回滚段中,内部包含1024个undo log segment。
MVCC
概念
当前读
![](https://img-blog.csdnimg.cn/461ccf99eb53490385bf92e7452869a7.png)
快照读
- Read Committed:每次select,都生成一个快照读。
- Repeatable Read:开启事务后第一个select语句才是快照读的地方。
- Serializable:快照读会退化为当前读。
MVCC
原理
隐藏字段
当我们创建了上面的这张表,我们在查看表结构的时候,就可以显式的看到这三个字段。 实际上除了这三个字段以外,InnoDB还会自动的给我们添加三个隐藏字段及其含义分别是:
隐藏字段
|
含义
|
DB_TRX_ID
|
最近修改事务
ID
,记录插入这条记录或最后一次修改该记录的事务
ID
。
|
DB_ROLL_PTR
|
回滚指针,指向这条记录的上一个版本,用于配合
undo log
,指向上一个版本。
|
DB_ROW_ID
|
隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。
|
ibd2sdi stu.ibd
![](https://img-blog.csdnimg.cn/8f25495faac24fccb260bdccd3d44ecd.png)
undolog
版本链
DB_TRX_ID : 代表最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID,是自增的。
DB_ROLL_PTR : 由于这条数据是才插入的,没有被更新过,所以该字段值为null。
最终我们发现,不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录。
readview
字段
|
含义
|
m_ids
|
当前活跃的事务
ID
集合
|
min_trx_id
|
最小活跃事务
ID
|
max_trx_id
|
预分配事务
ID
,当前最大事务
ID+1
(因为事务
ID
是自增的)
|
creator_trx_id
|
ReadView
创建者的事务
ID
|
条件
|
是否可以访问
|
说明
|
trx_id == creator_trx_id
|
可以访问该版本
|
成立,说明数据是当前这个事务更改的。
|
trx_id < min_trx_id
|
可以访问该版本
|
成立,说明数据已经提交了。
|
trx_id > max_trx_id
|
不可以访问该版本
|
成立,说明该事务是在
ReadView
生成后才开启。
|
min_trx_id <= trx_id <= max_trx_id
|
如果
trx_id
不在
m_ids
中,
是可以访问该版本的
|
成立,说明数据已经提交。
|
原理分析
RC(Read commit)隔离级别
![](https://img-blog.csdnimg.cn/626ebb9c6b9b486c83f8b95491c34494.png)
在进行匹配时,会从undo log的版本链,从上到下进行挨个匹配
![](https://img-blog.csdnimg.cn/72bde2def8614f1198d46fb873c7914a.png)
![](https://img-blog.csdnimg.cn/b2e2dc3c30704db7802a53efbc5d32b8.png)
记录对应的trx_id为3,也就是将3带入右侧的匹配规则中。①不满足 ②不满足 ③不满足 ④也 不满足 ,都不满足,则继续匹配undo log版本链的下一条。
再匹配第三条
![](https://img-blog.csdnimg.cn/4641ea4d09a842c884196424f5d9417a.png)
![](https://img-blog.csdnimg.cn/99e5a368aa384725bac618dfa7495452.png)
RR隔离级别
RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。 而RR 是可重复读,在一个事务中,执行两次相同的select语句,查询到的结果是一样的。
那MySQL是如何做到可重复读的呢? 我们简单分析一下就知道了
MVCC总结
![](https://img-blog.csdnimg.cn/77da1934f8c14bd3a6d3b46bbb97461d.png)
总结