爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文基于 MySQL 8.0.32 源码,存储引擎为 InnoDB。
正文
创建测试表:
CREATE TABLE `t1` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`i1` int DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_i1` (`i1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
示例 SQL:
INSERT INTO `t1` (`id`, `i1`)
VALUES (50, 501);
插入一条记录到表中,首先会插入记录到主键索引,然后遍历二级索引,把记录插入到各个二级索引中。
插入记录到主键索引之前,会生成 Undo 日志,并写入 Undo 页。插入记录到二级索引,不会生成 Undo 日志。插入记录的 Undo 日志格式比较简单,如下图所示。
各属性详细说明如下:
TRX_UNDO_INSERT_REC
。如果主键是由多个字段组成的联合主键,插入记录产生的 Undo 日志中,会按照联合主键定义的字段顺序写入所有主键字段的长度和值:len_1、value_1、len_2、value_2、...、len_N、value_N。
示例 SQL 插入记录到 t1 表中产生的 Undo 日志,如下图所示。
各属性值详细说明如下:
TRX_UNDO_INSERT_REC
。这个值不会压缩,固定占用 1 字节。undo_no
属性。事务产生的第一条 Undo 日志编号为 0,第二条 Undo 日志编号为 1,依此类推。int unsigned
,占用 4 字节。InnoDB 存储引擎的表中,每条记录都有个隐藏字段 DB_ROLL_PTR
,字段长度固定为 7 字节。通过这个字段值可以找到 Undo 日志(也是 MVCC 中记录的历史版本)。
从整体上来看,我们可以认为它是 Undo 日志的地址。但是,这个字段值实际上由 4 部分组成,如下图所示。
各属性详细说明如下:
DB_ROLL_PTR 的计算公式如下:
is_insert << 55 | undo_space_id << 48 | page_no << 16 | offset
以示例 SQL 为例,插入记录时产生 Undo 日志得到的各属性值如下:
用 Shell 按照以上公式计算得到 DB_ROLL_PTR,如下:
# 输出结果为 36591747009937680
echo $((1 << 55 | 2 << 48 | 573 << 16 | 272))
没有需要总结的内容。