概述
之前已经介绍了一次MYSQL UNDO方面的内容,今天主要再介绍一下UNDO的其他几个方面,下面先简单说下概念。
一、undo概述
undo log有两个作用:提供回滚和多个行版本控制(MVCC)。
在数据修改的时候,不仅记录了redo,还记录了相对应的undo,如果因为某些原因导致事务失败或回滚了,可以借助该undo进行回滚。
5.6以前undo都存储在内存和ibdata1中,5.6以后undo可以独立成单独的文件,更可以进行truncate表空间,减少磁盘容量
二、undo三阶段
1、回滚段分类
update_undo: 只用于事务内的update和delete语句 这里会加入到其对应rollback segment的history list数据页列表上,history list长度加1。该log需要提供mvcc机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行清除。
insert_undo:只用于事务内的insert语句 新插入的记录产生的Undo不会被任何查询语句所引用,因此可以直接释放undo,这里的undo log不会累加到history list上。这里的insert操作的记录只对事务本身可见。所以该undo log在事务提交后直接删除,不需要进行purge操作。
2、事务开始后,针对读写事务,会预先在内存中分配一个回滚段
3、事务进行中,将历史数据写入undo page中
1)事务commit
2)事务rollback
- 对于标记删除的记录清理标记删除标记;
- 对于in-place更新,将数据回滚到最老版本;
- 对于插入操作,直接删除聚集索引和二级索引记录(row_undo_ins)
三、purge机制
purge用来最终完成delete和update操作。
- 全局动态参数innodb_purge_batch_size用来设置每次purge操作需要清理的undo page数量。默认值为300
- 全局动态参数innodb_max_purge_lag用来控制history list的长度,若大于该参数时,其会延缓DML的操作
- 全局动态参数innodb_max_purge_lag_delay,用来控制DML操作每行数据的最大延缓时间,单位为毫秒。
1、清理事务提交后不需要的undo信息 从回滚段的HISTORY 文件链表上开始遍历释放Undo log segment,由于history 链表是按照trx no有序的,因此遍历truncate直到完全清除,或者遇到一个还未purge的undo log(trx no比当前purge到的位置更大)时才停止。
2、清理已经被打上delete标记的数据实现物理删除
3、相关参数变量 innodb_purge_threads=1(默认值)
四、相关 innodb status信息
show engine innodb status \G;
Purge done for trx's n:o < 2463087 undo n:o < 0 state: running but idle History list length 26
说明:
- purge done 代表已经完成的事务量
- n:0< 代表正在执行的purge
- state:代表线程是否繁忙
- history-list-length 代表存在的undo个数 16KX3228 代表使用的undo大小 一页是16K
这里要注意 一般情况下history-list不可能为零,因为 update_undo有一部分会进行cache重用,而这部分也算在没有清理的列表之中
五、undo的构成和布局
1、由128个回滚段构成,32个回滚段用于系统的临时表空间,96个回滚段用于事务
2、每个回滚段维护了一个段头页,在该page中又划分了1024个slot,每个slot又对应到一个undo log对象,因此理论上InnoDB最多支持 96 * 1024个普通事务。
3、独立表空间的space id都是从1 开始,0被预留在ibdata中.space id必须是连续分配的,不能断档
4、8.0之前的版本默认只能创建128个回滚段
六、查看undo信息
1.查看rollback segment所在页
select segment_id,space,page_no from information_schema.innodb_trx_rollback_segment;
2.记录事务对应的undo log信息
select * from information_schema.INNODB_TRX_UNDO\G;
七、各版本UNDO说明
1、5.5
undo位置:默认ibdata1中,不支持独立表空间
缺点:大事务可能造成ibdata1暴涨,只能dump导出导入或者从新搭建
参数:rollback_segment(默认128个回滚段)
2、5.6
undo位置:默认ibdata1中,支持独立表空间
参数:
innodb_undo_logs(代替5.5的名字,默认128个回滚段) innodb_undo_directory 设置undo位置,默认当前文件夹 innodb_undo_tablespaces 默认关闭,开启需要设置为1
缺点:mysql5.6只支持初始化设置独立表空间,不可中途开启.而且也不能解决回收undo表空间问题.但是可以支持分布在不同磁盘,用来提高IO能力
建议:不建议5.6开启独立undo空间,没什么意义
3、5.7
undo位置:默认ibdata1中,支持独立表空间
参数:
innodb_max_undo_log_size=1073741824 innodb_undo_directory=./ 独立undo表空间路径 innodb_undo_log_truncate=OFF 支持truncate回收表空间,默认关闭 innodb_undo_logs=128 128个回滚段 innodb_undo_tablespaces=0 独立表空间,默认为0,需要设置>=2 innodb_purge_rseg_truncate_frequency=128 purge undo轮询128次后,进行一次undo的truncate
注意点:
1)mysql5.7同样是只支持初始化设置,不可中途开启
2)truncate会进行清理undo文件的条件: 1 触发 max_undo_log阈值(undo tablespace超过1GB(参数innodb_max_undo_log_size来控制))
3)存在至少一个可用的undo文件
4)被清理对象皆为free,也即为事务不需要
以上三点都达到时候才会触发truncate进行undo表空间收缩,由purge线程执行
5)尽量避免大事务,将大事务进行拆分
4、8.0的持续改进:
1)默认开启独立undo表空间,更改undo表空间命名方式,默认大小为10M
2)在8.0之前只能创建128个回滚段,而在8.0版本开始,每个Undo tablespace可以创建128个回滚段,也就是说,总共有innodb_rollback_segments * innodb_undo_tablespaces个回滚段。这个改变的好处是在高并发下可以显著的减少因为分配到同一个回滚段内的事务间产生的锁冲突
3)Innodb_undo_truncate参数默认打开,会自动进行删除
4)支持undo tablespace加密
5)在8.0中直接在内存中为其创建单独的内存结构,这32个slot可以用于持久化的undo回滚段
6)允许动态的增加undo tablespace的个数,也就是说可以动态调整innodb_undo_tablespaces。当调大该参数时,会去创建新的undo tablespace。但如果设小该值,则仅仅是不实用多出来的Undo tablespace,目前不会去主动删除它们
后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下~
如果你觉得这篇文章对你有帮助, 请小小打赏下~