前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[MYSQL] mysql undo文件解析(1)

[MYSQL] mysql undo文件解析(1)

原创
作者头像
大大刺猬
发布2024-08-02 12:05:57
1290
发布2024-08-02 12:05:57
举报
文章被收录于专栏:大大刺猬

导读

之前解析过mysql的各种文件, 比如:ibd,redo,binlog,frm,myd. 貌似漏了个undo文件没有解析... 现在来补上 -_-

第一篇先简单看下, 尽量不涉及到具体的页解析

介绍

undo日志是要un do的时候使用的日志. 我们可以使用innodb_undo_directory控制undo日志的路径(默认在@@datadir目录下), 可以使用innodb_undo_tablespaces控制undo的文件数量.

undo里面记录的是修改前的数据(MVCC实现).每个事务最多分配4个undo日志. (主要分为insert/update(含delete)两种, 但又涉及到临时表, 所以可以看作是4种).

Each undo tablespace and the global temporary tablespace individually support a maximum of 128 rollback segments. The innodb_rollback_segments variable defines the number of rollback segments.

既然段的数量是有限的,那么支持的事务数量也就是有限的了. 官方给了个计算方式:

代码语言:txt
复制
-- 如果每个事务都只有Insert或者update/delete
(innodb_page_size / 16) * innodb_rollback_segments * number of undo tablespaces = (16384/16)*128*2 = 262144

-- 如果每个事务都有insert和update/delete
(innodb_page_size / 16 / 2) * innodb_rollback_segments * number of undo tablespaces = (16384/16/2)*128*2 = 131072

-- 如果每个事务都是对临时表做insert (不存在只update/insert临时表)
(innodb_page_size / 16) * innodb_rollback_segments = (16384/16)*128 = 131072

-- 如果每个事务都是对临时表做insert和update/delete
(innodb_page_size / 16 / 2) * innodb_rollback_segments = (16384/16/2)*128 = 65536

看起来支持的事务数量是有限的, 但一般达不到这么多的事务量, 所以也不用关心这个.

按65536看, 那都得至少65536个连接在跑事务

undo_001

扯远了, 我们还是来看看undo的文件结构吧

我这是两个undo文件, 均为16MB(实际上可能某一个会大很多). undo也是innodb实现的,那么应该和ibd文件之类的格式类似, 我们使用如下python代码解析下:

代码语言:python
代码运行次数:0
复制
import struct
filename = '/data/mysql_dev/data/undo_001'
f = open(filename,'rb')
linesize = 20
f.seek(0,0)
for i in range(int(os.stat(filename).st_size/16384)):
	bdata = f.read(16384)
	FIL_PAGE_SPACE_OR_CHKSUM, FIL_PAGE_OFFSET, FIL_PAGE_PREV, FIL_PAGE_NEXT, FIL_PAGE_LSN, FIL_PAGE_TYPE, FIL_PAGE_FILE_FLUSH_LSN, FIL_PAGE_SPACE_ID = struct.unpack('>4LQHQL',bdata[:38])
	print(f'{FIL_PAGE_TYPE} ',end = '\n' if i%linesize == 0 else '')

可以看到

第一页是8(FIL_PAGE_TYPE_FSP_HDR),

第二页是5(FIL_PAGE_IBUF_BITMAP),

第三页是3(FIL_PAGE_INODE) -- ibd文件记录索引段的

和ibd文件是一样的.

第4页是21(FIL_PAGE_TYPE_RSEG_ARRAY) 是undo特有的页(Rollback Segment Array page )

剩下的都是 6(FIL_PAGE_TYPE_SYS) 2(FIL_PAGE_UNDO_LOG)和0(FIL_PAGE_TYPE_ALLOCATED)了.

也就是我们只需要再了解FIL_PAGE_TYPE_RSEG_ARRAY,FIL_PAGE_TYPE_SYS和FIL_PAGE_UNDO_LOG 就可以解析undo文件了.

先不急, 我们利用下之前的工具ibd2sql的debug功能来获取下rollptr.

我们先准备下测试表吧

代码语言:sql
复制
create table t20240802(id int, name varchar(200));
insert into t20240802 values(1,'ddcw');
insert into t20240802 values(2,'ddcw'); 
insert into t20240802 values(3,'ddcw');
update t20240802 set name='newddcw' where id=2;

然后使用ibd2sql解析这行被修改的数据

代码语言:shell
复制
python3 main.py /data/mysql_dev/data/db1/t20240802.ibd --sql --debug

这个回滚指针roll pointer的格式为:

对象

大小

描述

offset

2字节

在page中的位置

page_no

4字节

在哪个页面

rseg_id

7bit

rollback segment ID

is_insert

1bit

是否为insert

所以我们可以使用如下python代码解析回滚指针

代码语言:python
代码运行次数:0
复制
rolll_ptr = 562949973550095
offset = rolll_ptr & 0xFFFF
page_no = (rolll_ptr>>16) & 0xFFFFFFFF
rseg_id = (rolll_ptr>>48) & 0x7F
is_insert = True if rolll_ptr>>55 == 1 else False
print(f"PAGENO:{page_no}  OFFSET:{offset}  rseg_id:{rseg_id}  is_insert:{is_insert}")

然后我们去undo里面对应的位置解析瞧瞧

代码语言:python
代码运行次数:0
复制
import struct
filename = '/data/mysql_dev/data/undo_002'
f = open(filename,'rb')
f.seek(page_no*16384,0)
data = f.read(16384)
data[offset:offset+100]

这个record格式前两字节为下一record位置(绝对), 最后2字节为上一record位置(绝对)

保存的数据是使用lv格式的, 即长度+数据(后面再讲吧. 这里我们就已经看到我们删除前的数据了).

参考:

https://dev.mysql.com/doc/refman/8.0/en/innodb-undo-logs.html

https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html

https://github.com/mysql/mysql-server/blob/trunk/storage/innobase

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导读
  • 介绍
  • undo_001
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档