前言
undo 和 redo 是在 mysql 中 事务, 或者 异常恢复 的场景下面 经常会看到的两个概念
这里 来看一下 undo, undo 主要是用于 事务回滚 的场景下面
测试表结构如下
CREATE TABLE `tz_test` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`field1` varchar(128) DEFAULT NULL,
`field2` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `field_1_2` (`field1`,`field2`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8
测试数据如下
记录更新 undo 业务记录
执行 sql 如下 “update tz_test set field1 = 'field13' where id = '2';”
首先是获取 undo 页的 free 记录的偏移, 然后 开始记录数据
记录操作类型, undo_no, table_id 等等 相关上下文信息
记录 info_bits, trx_id, poll_ptr
记录标记当前记录的 字段信息, 这里是 ”where id = 2”
记录更新的相关字段信息, 字段数量, 字段编号, 字段长度, 字段内容
记录当前 记录 的所有的字段信息, 字段编号, 字段长度, 字段内容
记录当前记录的头结点偏移, 下一个记录的偏移, free_ptr 的偏移
在 mtr 中暂存当前 undo log 的 redo log
记录当前这条 undo log 的 redo log, 实际上就是 保存了一下这条 undo log 的快照信息
复制了一份数据到 mtr, mtr 表示 mysql 中的 Mini-Transaction
undo 日志记录完成之后 更新相关元数据, 生成 roll_ptr
更新当前记录的 trx_id, roll_ptr
记录更新 undo 日志格式
查看一下 待更新的记录信息, id 为 2, field1 为 ‘field12’
undo 日志记录如下, 这里具体 拆分到每一个字节
记录新增 undo 业务记录
假设执行 sql 如下 “INSERT INTO `test`.`tz_test`(`field1`, `field2`) VALUES ('field11', '11');”
从下图可以看到待插入记录的 id, field1, field2 的相关信息
记录带新增记录 当前的状态, 因为记录待新增 因此没有字段信息
这里仅仅记录 trx->undo_no, table_id, 主键信息, 当前记录偏移信息, 下一个记录偏移信息
记录当前记录偏移信息, 下一个记录偏移信息, 记录当前 undo 记录的 redo 记录
记录新增 undo 日志格式
新增记录的 undo 日志信息如下, 记录相关的信息 主要是 id
记录删除 undo 业务记录
执行 sql 如下 “delete from tz_test where id = 13;”
因为 mysql 这边先是做的逻辑删除, 因此 就是这边 undo 相关操作 和 记录更新一致, 这里不多赘述
记录新增 undo 的使用
执行 sql 如下
“begin;
INSERT INTO `test`.`tz_test`(`id`, `field1`, `field2`) VALUES (1111, 'field11', '11');
rollback;
”
新增记录的 undo log, 的真实处理是 删除对应 主键 对应的记录
比如这里 查询条件为 ”id = 1111”
具体的删除处理如下, 等价于 普通的 “delete from tz_test where id = 1111;”
记录更新 undo 的使用
执行 sql 如下
“begin;
update tz_test set field1 = 'field33' where id = 2;
rollback;
”
如下这是 事务中的更新语句执行的上下文, field1 的字段由 ”field12” 更新为 ”field33”
如下 这是回滚的时候 更新记录的 undo 的处理
这个 更新的回滚操作如下, 将 field1 字段从 “field33” 更新回 “field12”
完