博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
InnoDB undo log解析(一)
阅读量:4106 次
发布时间:2019-05-25

本文共 4615 字,大约阅读时间需要 15 分钟。

在InnoDB存储引擎中,undo log用来完成事务的回滚以及MVCC的功能。但是InnoDB本身提供对于undo log的分析或者查询功能非常有限。用户仅能通过SHOW ENGINE INNODB STATUS中的History list length信息的值当前undo log在history列表中的数量。网上已经有些文章分析了undo log的存储结构,但很少对InnoDB的undo log进行解析。本博文将详细介绍InnoDB存储引擎中的undo log格式,使读者能更为深入了解其实现。

在InnoDB存储引擎中,undo log可分为以下两种类型:

  • insert undo log
  • update undo log

insert undo log是指在insert操作中产生的undo log。因为insert操作的记录,只对事务本身可见,对其他事务不可见(这是事务隔离性的要求),故该undo log可以在事务提交后直接删除。不需要进行purge操作。insert undo log的格式如左图所示(点击可看原图)

图中*表示对存储的字段进行了压缩。insert undo log开始的前两个字节next记录的是下一个undo log的位置,通过该next的字节可以知道一个undo log所站的空间字节数。类似地,尾部的两个字节记录的是undo log的开始位置。type_cmpl占用一个字节,记录的是undo地类型,对于insert undo log,该值总是为11。undo_no记录事务的ID,table_id记录undo log所对应的表对象。这两个值都是用于进行压缩的。接着的部分记录了所有主键的列和值。在进行rollback操作时,根据这些值可以定位到具体的记录,然后进行删除即可。

 

update undo log记录的是对delete和update操作产生的undo log。该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行最后的删除。update undo log的结构如右图所示(点击可看原图)。

update undo log相对于之前介绍的insert undo log,记录的内容更多,所需占用的空间也更大。next、start、undo_no、table_id与之前介绍的insert undo log部分相同。这里的type_cmpl,由于update undo log本身还有分类,故其可能的值如下:

  • 12 (TRX_UNDO_UPD_EXIST_REC)
  • 13 (TRX_UNDO_UPD_DEL_REC)
  • 14 (TRX_UNDO_DEL_MARK_REC) 

undo log可以分为上述3种类型,其分别代表了更新non-delete-mark的记录,将delete的记录标记为not delete,将记录标记为delete。


紧接着的部分记录update_vector信息,update_vector表示update操作导致发生改变的列。每个修改的列信息都要记录的undo log中。对于不同的undo log类型,可能还需要记录对索引列所做的修改。

Oracle和Microsoft SQL Server数据库都由内部的数据字典来观察当前undo的信息,InnoDB存储引擎在这方面做得还是不够,DBA只能通过原理和经验来进行判断。InnoSQL对information_schema进行了扩展,添加了两张数据字典表,这样用户可以非常方便和快捷地查看undo的信息。

首先增加的数据字典表为INNODB_TRX_ROLLBACK_SEGMENT。顾名思义,这个数据字典表用来查看rollback segment(回滚段)。InnoDB 1.1版本开始,其一共有128个rollback segment,每个rollback segment支持1024个undo log段,因此一共支持128*1024个同时并发在线事务。而之前的版本仅有1个回滚段,故最大支持并发事务为1024。

例如,用户可以通过下面的命令来查看rollback segment所在的页(InnoDB 1.2版本之前,rollback segment都放在共享表空间内,故space值都为0。InnoDB 1.2版本开始支持独立的rollback segment表空间):

mysql> SELECT segment_id,space,page_no FROM INNODB_TRX_ROLLBACK_SEGMENT; +------------+-------+---------+ | segment_id | space | page_no | +------------+-------+---------+ |          0 |     0 |       6 | |          1 |     0 |      45 | |          2 |     0 |      46 | ...... 128 rows in set (0.00 sec)

另一张数据字典表为INNODB_TRX_UNDO,用来记录事务对应的undo log,方便DBA和开发人员详细了解每个事务产生的undo量。下面将演示如和使用INNODB_TRX_UNDO表,首先根据如下代码创建测试表t。

CREATE TABLE t (      a INT,      b VARCHAR(32),      PRIMARY KEY(a),      KEY(b) )ENGINE=InnoDB;

接着插入一条记录,并尝试通过INNODB_TRX_UNDO观察该事务的undo log的情况:

mysql> BEGIN; Query OK, 0 rows affected (0.00 sec) mysql> INSERT INTO t SELECT 1,’1’; Query OK, 1 row affected (0.00 sec) Records: 1  Duplicates: 0  Warnings: 0 mysql> SELECT * FROM information_schema.INNODB_TRX_UNDO\G; *************************** 1. row ***************************        trx_id: 3001       rseg_id: 2   undo_rec_no: 0 undo_rec_type: TRX_UNDO_INSERT_REC          size: 12         space: 0       page_no: 334        offset: 272 1 row in set (0.00 sec)

通过数据字典表可以看到,事务ID为3001,rollback segment的ID为2,因为是该条事务的第一个操作,故undo_rec_no为0。之后可以看到插入的类型为TRX_UNDO_INSERT_REC,表示是insert undo log。size表示undo log的大小,占用12字节。最后的space、page_no、offset表示undo log开始的位置。打开文件ibdata1,定位到页(334,272),并读取12字节,可得到如下内容:

01 1c 0b 00 16 04 80 00 00 01 01 10


上述就是undo log实际的内容,之前对于insert undo log格式的介绍,可以整理得到:

01 1c       # 下一个undo log的位置 272+12=0x011c 0b          # undo log的类型,TRX_UNDO_INSERT_REC为11 00          # undo log的记录,等同于undo_rec_no 16          # 表的ID 04          # 主键的长度 80 00 00 01 # 主键的内容 01 10       # undo log开始的偏移量,272=0x0110

此外,由于知道该undo log所在的rollback segment的ID为2,用户还可以通过数据字典表INNODB_TRX_ROLLBACK_SEGMENT来查看当前rollback segment的信息,如:

mysql> SELECT segment_id,insert_undo_list,insert_undo_cached      -> FROM information_schema.INNODB_TRX_ROLLBACK_SEGMENT      -> WHERE segment_id=2\G; *************************** 1. row ***************************         segment_id: 2   insert_undo_list: 1 insert_undo_cached: 0 1 row in set (0.00 sec)

可以看到insert_undo_list为1。若这时进行事务的COMMIT操作,再查看该数据字典表:

mysql> COMMIT; Query OK, 0 rows affected (0.00 sec) mysql> SELECT segment_id,insert_undo_list,insert_undo_cached      -> FROM information_schema.INNODB_TRX_ROLLBACK_SEGMENT      -> WHERE segment_id=2\G; *************************** 1. row ***************************         segment_id: 2   insert_undo_list: 0 insert_undo_cached: 1 1 row in set (0.00 sec)

可以发现,insert_undo_list变为0,而insert_undo_cached增加为1。这就是undo页重用,即下次再有事务需要向该rollback segment申请undo页时,可以直接使用该页。

update undo log较之insert undo log要复杂的多,因此将在第二篇中进行分析。so,预知后事如何,待听下回分解InnoDB undo log解析(一) - insidemysql - Inside MySQL

  登录后你可以发表评论,请先登录。
登录>>
2013-04-25 17:10
看大小的功能GJ啊,这个功能加上后拿不同事物隔离级别对undo大小影响来量化测一下.
有个问题,如果异常崩溃,如果之前有事务没提交,起来以后回滚会在实例可连通后继续进行,只不过这个表上的事务会有影响.这个情况下,能通过这个功能知道有多少待回滚的undo,来估算回滚时间么?
2013-04-26 10:41
 回复 

转载地址:http://ocnsi.baihongyu.com/

你可能感兴趣的文章
PHP底层的运行机制与原理
查看>>
深入了解php底层机制
查看>>
PHP中的stdClass 【转】
查看>>
XHProf-php轻量级的性能分析工具
查看>>
PHP7新特性 What will be in PHP 7/PHPNG
查看>>
比较strtr, str_replace和preg_replace三个函数的效率
查看>>
ubuntu 下编译PHP5.5.7问题:configure: error: freetype.h not found.
查看>>
PHP编译configure时常见错误 debian centos
查看>>
configure: error: Please reinstall the BZip2 distribution
查看>>
OpenCV gpu模块样例注释:video_reader.cpp
查看>>
【增强学习在无人驾驶中的应用】
查看>>
OpenCV meanshift目标跟踪总结
查看>>
人工神经网络——神经元模型介绍
查看>>
一种函数指针的运用
查看>>
今天,Python信息量很大!
查看>>
Flash 已死,Deno 当立?
查看>>
编程差的程序员,90%都是吃了数学的亏!骨灰级开发:方法不对,努力也白费...
查看>>
都无代码了,还要程序员吗?
查看>>
面试想拿 10K,HR 说我只配7k?
查看>>
那些人生“开挂”的程序员,都在干什么?
查看>>