MySQL 5.7 新特性:在线truncate undo log文件

在MySQL5.7.5版本中,增加了一个比较有用的功能,即用户可以自己truncate掉undo log。 对应的changeling entry如下:

InnoDB: You can now truncate undo logs that reside in undo tablespaces. This feature is enabled using theinnodb_undo_log_truncate configuration option. For more information, see Truncating Undo Logs That Reside in Undo Tablespaces.

我们知道Undo log是MVCC多版本控制的核心模块,一直以来undo log都存储在ibdata系统表空间中,而从5.6开始,用户可以把undo log存储到独立的tablespace中,并拆分成多个Undo log文件。 但5.6及5.6之前的版本都无法缩小文件的大小。而长时间未提交事务导致大量undo 空间的浪费的例子,在我们的生产场景也不是一次两次了。

5.7的undo log的truncate操作是基于独立undo 表空间来实现的

0.相关参数

在能够使用该特性之前,需要先打开独立undo表空间,注意现在只能在install db的时候才能开启,因为他在初始化阶段是写死占用了最小的几个space id的…这种实现方式。。。只能无限吐槽 了- -..
有几个参数控制undo tablespace:
innodb_undo_directory: Undo文件的存储目录
innodb_undo_tablespaces: undo tablespace的个数,至少大于等于2,因为在truncate一个undo log文件时,要保证另外一个是可用的,这样就无需停止业务了.
innodb_undo_logs: undo回滚段的数量, 至少大于等于35,默认128.官方博客对35这个数字的解释:

The value of 35 comes from how the UNDO logs (rollback segments or rsegs) are allocated—0: REDO enabled rseg allocated in the system tablespace, 1-32: non-REDO enabled rsegs allocated in the temporary tablespace, 33-n: REDO enabled rsegs allocated in UNDO table spaces

0         -> rseg resides always in system tablespace
1..32  -> rseg resides in shared temporary tablespace (ibtmp1)

33     -> undo-tablespace-0
34     -> undo-tablespace-1
….
33+n-1 -> undo-tablespace-n-1 (undo tablespace indexes from 0 so n-1 is last).
33+n   -> undo-tablespace-0
33+n+1 -> undo-tablespace-1
….
m      -> undo-tablespace-x

innodb_purge_rseg_truncate_frequency: 用于控制purge回滚段的频度.

innodb_max_undo_log_size: 控制最大undo tablespace文件的大小,超过这个阀值时才会去尝试truncate. truncate后的大小默认为10M

打开/关闭该特性,使用动态参数innodb_undo_log_truncate控制

root@(none) 06:43:29>set global innodb_undo_log_truncate = ON;
Query OK, 0 rows affected (0.00 sec)

root@(none) 06:43:32>set global innodb_undo_log_truncate = OFF;
Query OK, 0 rows affected (0.00 sec)

下面简单介绍下实现的相关代码
0.新的truncate管理结构体

新的类undo::Truncate被引入,来管理table space truncate的过程
挂在purge_sys->undo_trunc中

1.标记需要truncate的undo tablespace

这个动作实际上是由purge的协调线程发起的,默认情况下每做128次purge后,会调用函数trx_purge_truncate进行清理操作,我们只关心truncate,对应的调用栈为:
trx_purge_truncate
|—>trx_purge_truncate_history
|—>trx_purge_mark_undo_for_truncate
|—>trx_purge_initiate_truncate

trx_purge_mark_undo_for_truncate 是标记truncate undo表空间的入口函数,主要包括如下步骤
step1: 检查是否开启truncate参数,或者已经有table space已经被标记为truncate

step2:检查是否可以进行安全的truncate,也就是上面说的innodb_undo_tablespaces>=2,  innodb_undo_logs>=35

step3:从上次扫描的tablespace开始遍历(round-robin),哪些tablespace可以标记为可truncate,如果发现一个需要truncate的 tablespace,则标记其为需要truncate,并从遍历中break出来:
undo_trunc->mark(space_id);
undo::Truncate::add_space_to_trunc_list(space_id);

step4: 遍历被选中的table space中的回滚段,将其设置为不可分配,判断条件为:

917                 if (rseg != NULL && !trx_sys_is_noredo_rseg_slot(rseg->id)) {
918                         if (rseg->space
919                                 == undo_trunc->get_marked_space_id()) {
920
921                                 /* Once set this rseg will not be allocated
922                                 to new booting transaction but we will wait
923                                 for existing active transaction to finish. */
924                                 rseg->skip_allocation = true;
925                                 undo_trunc->add_rseg_to_trunc(rseg);
926                         }
927                 }

2. truncate operation

在标记需要truncate的tablespace后,需要先检查需要删除的回滚段是否是可释放的。也就是没有任何活跃的事务会应用到其中的Undo log

入口函数:trx_purge_initiate_truncate

step 1: 检查回滚段是否可释放,如果不可以(有活跃事务可能使用undo做MVCC),直接返回

step 2:做一次redo checkpoint,因为如果随后发生crash,可能针对该undo tablespace的redo 就会无效了,因为文件被truncate了。
log_make_checkpoint_at(LSN_MAX, TRUE);  这会刷新所有脏页和redo log.

step 3.开始之前…
1100                 undo_trunc->start_logging(
1101                         undo_trunc->get_marked_space_id());

创建一个命名为undo_<space_id>_trunc.log的文件,如果crash重启发现该文件,则表明truncate tablespace可能没有完成,需要重做.

step 4: 清理对应的purge queue,无需继续做Purge 操作
trx_purge_cleanse_purge_queue(undo_trunc);

step5 : 执行真正的truncate

bool    success = trx_undo_truncate_tablespace(undo_trunc);

入口函数:trx_undo_truncate_tablespace
..truncate文件
success = fil_truncate_tablespace(
space_id, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES);

文件先被truncate到0,再重新设置到10M,相当于一个新建的undo tablespace.

…重新初始化undo log tablespace的头,这个过程不记录redo log.
fsp_header_init(space_id, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr);

…重新初始化该tablespace内的回滚段头

step 6:在完成truncate后,再做一次checkpoint

step 7: 完成后
undo_trunc->done_logging(undo_trunc->get_marked_space_id());

删除undo_<space_id>_trunc.log

step 8: 清理操作

undo_trunc->reset();
undo::Truncate::clear_trunc_list();

worklog:
http://dev.mysql.com/worklog/task/?id=6965

相关代码:
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8631
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8629
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8622
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8615

官方博客描述:
http://mysqlserverteam.com/online-truncate-of-innodb-undo-tablespaces/

时间: 2024-10-26 13:09:55

MySQL 5.7 新特性:在线truncate undo log文件的相关文章

MySQL内核月报 2014.11-MySQL· 5.7特性·在线Truncate undo log 表空间

背景 Innodb使用undo log来实现MVCC,这意味着如果一个很老的事务长时间不提交,那么新产生的undo log都无法被及时清理掉.在MySQL 5.5及之前版本中,undo log是存储在ibdata中.从5.6开始可以使用独立的undo log表空间来存储undo.但是直到5.6,一旦undo log膨胀,依然没有任何办法为其 "减肥".因此我们经常看到ibdata被膨胀到几十上百G. 改进 在MySQL5.7.5版本中终于增加了这个众望所归的功能,实现了在线trunca

MySQL · 特性分析 ·MySQL 5.7新特性系列三

继上两期月报,MySQL5.7新特性之一介绍了一些新特性及兼容性问题,MySQL 5.7新特性之二介绍了临时表的优化和实现. 这期我们一起来学习下undo空间管理,重点介绍truncate功能. 1. 背景 InnoDB存储引擎中,undo在完成事务回滚和MVCC之后,就可以purge掉了,但undo在事务执行过程中,进行的空间分配如何回收,就变成了一个问题. 我们亲历用户的小实例,因为一个大事务,导致ibdata file到800G大小. 我们先大致看下InnoDB的undo在不同的版本上的一

MySQL · 特性分析 ·MySQL 5.7新特性系列四

继上三期月报:MySQL 5.7新特性之一介绍了一些新特性及兼容性问题MySQL 5.7新特性之二介绍了临时表的优化和实现MySQL 5.7新特性之三介绍了undo表空间的truncate功能 这期我们一起来学习下MySQL 5.7的并行复制. 1. 背景 MySQL的master<->slave的部署结构,使用binlog日志保持数据的同步,全局有序的binlog在备库按照提交顺序进行回放. 由于新硬件的发展,SSD的引入和多core的CPU,master节点的并发处理能力持续提升,slav

MySQL 5.0 新特性--存储过程

Introduction 简介 MySQL 5.0 新特性教程是为需要了解5.0版本新特性的MySQL老用户而写的.简单的来说是介绍了"存储过程.触发器.视图.信息架构视图",在此感谢译者陈朋奕的努力. 希望这本书能像内行专家那样与您进行对话,用简单的问题.例子让你学到需要的知识.为了达到这样的目的,我会从每一个细节开始慢慢的为大家建立概念,最后会给大家展示较大的实用例,在学习之前也许大家会认为这个用例很难,但是只要跟着课程去学,相信很快就能掌握. Conventions and St

MySQL 5.0新特性教程 存储过程:第一讲

mysql|存储过程|教程 作者:mysql AB;翻译:陈朋奕 Introduction 简介 MySQL 5.0 新特性教程是为需要了解5.0版本新特性的MySQL老用户而写的.简单的来说是介绍了"存储过程.触发器.视图.信息架构视图",在此感谢译者陈朋奕的努力. 希望这本书能像内行专家那样与您进行对话,用简单的问题.例子让你学到需要的知识.为了达到这样的目的,我会从每一个细节开始慢慢的为大家建立概念,最后会给大家展示较大的实用例,在学习之前也许大家会认为这个用例很难,但是只要跟着

MySQL 5.0新特性教程 存储过程:第一讲

Introduction 简介 MySQL 5.0 新特性教程是为需要了解5.0版本新特性的MySQL老用户而写的.简单的来说是介绍了"存储过程.触发器.视图.信息架构视图",在此感谢译者陈朋奕的努力. 希望这本书能像内行专家那样与您进行对话,用简单的问题.例子让你学到需要的知识.为了达到这样的目的,我会从每一个细节开始慢慢的为大家建立概念,最后会给大家展示较大的实用例,在学习之前也许大家会认为这个用例很难,但是只要跟着课程去学,相信很快就能掌握. Conventions and St

MySQL 5.0 新特性--存储过程(1)

Introduction 简介 MySQL 5.0 新特性教程是为需要了解5.0版本新特性的MySQL老用户而写的.简单的来说是介绍了"存储过程.触发器.视图.信息架构视图",在此感谢译者陈朋奕的努力. 希望这本书能像内行专家那样与您进行对话,用简单的问题.例子让你学到需要的知识.为了达到这样的目的,我会从每一个细节开始慢慢的为大家建立概念,最后会给大家展示较大的实用例,在学习之前也许大家会认为这个用例很难,但是只要跟着课程去学,相信很快就能掌握. Conventions and St

MySQL 5.7新特性

    关于MySQL5.7,现在据说也是蛮火的,此文主要参照官方文档整理的,时日有些长了,最新的特性可能没采集进来,各位看客朋友们随意就好~~勿喷 新的特性 1.安全性增强 1)mysql.user表.plugin字段要求非空:新增时间戳字段保存密码最后被修改时间:不再使用password字段,使用authentication_string替代 2)安装与服务.全新的安装方式mysqld --initialize:安装完毕后只创建一个本地root账户,即root@'localhost':无匿名

MySQL · 特性分析 · MySQL 5.7新特性系列一

1. 背景 MySQL 5.7在2015-10-21发布了GA版本,即5.7.9,目前小版本已经到了5.7.12.5.7新增了许多新的feature和优化,接下来一个系列,我们就一起来尝尝鲜.首先这次主要是预览feature的变化以及兼容性问题.后面的系列,会针对重要的feature展开来学习. 2 安全相关的特性 2.1 认证插件 mysql.user表中的plugin更改成not null,5.7开始不再支持mysql_old_password的认证插件,推荐全部使用mysql_native