InnoDB undo log解析(一)

本文详细介绍了InnoDB存储引擎中的undo log格式,包括insert undo log和update undo log的区别及应用场景,通过实例展示了如何利用InnoDB提供的信息schema表来观察undo log。

InnoDB undo log解析(一)

277人阅读 评论(0) 收藏 举报
在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

InnoDB undo log解析(一) - insidemysql - Inside MySQL

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操作时,根据这些值可以定位到具体的记录,然后进行删除即可。


InnoDB undo log解析(一) - insidemysql - Inside MySQL
 

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值