[MySQL 学习]show engine innodb status中的history list length

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

Percona bug#1058100提到trx_purge_add_update_undo_to_history函数,不甚了解,用gdb跟踪了下

trx_commit_off_kernel->trx_write_serialisation_history->trx_undo_update_cleanup->trx_purge_add_update_undo_to_history

lsn = trx_write_serialisation_history(trx);

a.首先对当前事务的undo段进行标记,以表明事务提交。

对于update undo日志,为事务分配id(trx_serialisation_number_get->trx_sys_get_new_trx_id),标记undo状态为TRX_UNDO_TO_PURGE(trx_undo_set_state_at_finish),

对于insert undo标记undo回滚段状态为TRX_UNDO_TO_FREE

如果update undo段只占用一个Page,并且使用的字节数小于TRX_UNDO_PAGE_REUSE_LIMIT(3/4的page size)时,则将undo段标记为TRX_UNDO_CACHED,表示下次可以重用该回滚段。

b.对于update undo,还需要将undo加到history list上,并做一些清理工作

trx_undo_update_cleanup(trx, undo_hdr_page, &mtr);

(1)trx_purge_add_update_undo_to_history(trx, undo_page, mgr);

当undo 段的state不为TRX_UNDO_CACHED时,需要更新undo段的history list length,然后将undo加入到改回滚段的TRX_RSEG_HISTORY的链表上(不太了解undo这部分相关的逻辑),将事务号写入undo_header + TRX_UNDO_TRX_NO中,并在TRX_UNDO_DEL_MARKS标注是否存在标记删除记录(需要purge)

在kernel_mutex的保护下trx_sys->rseg_history_len++;

我们在show engine innodb status里看到的History list length实际上就是trx_sys->rseg_history_len值。


由于该函数总是在事务提交时才被调用到,因此我们也可以把history list lengh理解为尚未被清理update undo的事务数.在update/delete为主的工作负载中,可能会看到length明显的增大。

这里有一段被注释的代码,也是Percona bug#1058100提出的质疑

//  if (!(trx_sys->rseg_history_len % srv_purge_batch_size)) { /*should wake up always*/

        /* Inform the purge thread that there is work to do. */

        srv_wake_purge_thread_if_not_active();

//  }


也就是说,在Percona版本中,purge线程总是会被唤醒。在原版MySQL5.5中这个判断逻辑还在。

官方5.6则和Percona版本类似,去除了判断条件。但5.6会在递增rseg_history_len之后,在写入undo_header事务Id之前唤醒purge线程。不知是否有潜在风险

如果每次都无条件的唤醒,这可能破坏了innodb_purge_batch_size的定义。


(2)从事务回滚段上把update undo移除

UT_LIST_REMOVE(undo_list, rseg->update_undo_list, undo);


(3)如果undo的state为TRX_UNDO_CACHED,则将其加入到事务回滚段的rseg->update_undo_cached中,留作下次重用。

UT_LIST_ADD_FIRST(undo_list, rseg->update_undo_cached, undo);


否则直接释放undo内存结构trx_undo_mem_free(undo);

//////////////////////////////////////////////////////////////////////////////////////////


既然我们知道了history list length来自trx_sys->rseg_history_len,那么在何时,这个值会被递减呢?

有两个函数被涉及到trx_purge_truncate_rseg_history以及trx_purge_free_segment

调用栈如下:

trx_purge->que_run_threads->que_run_threads_low->row_purge_step->row_purge->trx_purge_fetch_next_rec->trx_purge_truncate_if_arr_empty->trx_purge_truncate_history->trx_purge_truncate_rseg_history->trx_purge_free_segment


当purge线程清理undo时,会遍历所有的回滚段列表(trx_purge_truncate_history, 最多1024个回滚段,在内存中用try_sys->rseg_list表示),进行undo清理。会对清理的trx_no 和undo_no做限制。

函数trx_purge_truncate_rseg_history有两个参数:

limit_trx_no,移除所有事务id小于这个值的undo log

limit_undo_no,如果事务id等于limit_trx_no,则只清理undo_no小于该值的undo 日志。

需要purge的Undo Log被记录在每个回滚段头的TRX_RSEG_HISTORY中,通过遍历列表,来回收Undo 记录。


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
存储 SQL 关系型数据库
MySQL底层概述—2.InnoDB磁盘结构
InnoDB磁盘结构主要包括表空间(Tablespaces)、数据字典(Data Dictionary)、双写缓冲区(Double Write Buffer)、重做日志(redo log)和撤销日志(undo log)。其中,表空间分为系统、独立、通用、Undo及临时表空间,分别用于存储不同类型的数据。数据字典从MySQL 8.0起不再依赖.frm文件,转而使用InnoDB引擎存储,支持事务原子性DDL操作。
244 100
MySQL底层概述—2.InnoDB磁盘结构
|
1月前
|
缓存 算法 关系型数据库
MySQL底层概述—1.InnoDB内存结构
本文介绍了InnoDB引擎的关键组件和机制,包括引擎架构、Buffer Pool、Page管理机制、Change Buffer、Log Buffer及Adaptive Hash Index。
252 97
MySQL底层概述—1.InnoDB内存结构
|
1月前
|
SQL 关系型数据库 MySQL
MySQL底层概述—10.InnoDB锁机制
本文介绍了:锁概述、锁分类、全局锁实战、表级锁(偏读)实战、行级锁升级表级锁实战、间隙锁实战、临键锁实战、幻读演示和解决、行级锁(偏写)优化建议、乐观锁实战、行锁原理分析、死锁与解决方案
118 24
MySQL底层概述—10.InnoDB锁机制
|
17天前
|
缓存 关系型数据库 MySQL
ThinkPHP框架show columns引发mysql性能问题
ThinkPHP框架的show columns引发mysql性能问题,结尾有关闭方式。
35 13
|
1月前
|
存储 缓存 关系型数据库
MySQL底层概述—5.InnoDB参数优化
本文介绍了MySQL数据库中与内存、日志和IO线程相关的参数优化,旨在提升数据库性能。主要内容包括: 1. 内存相关参数优化:缓冲池内存大小配置、配置多个Buffer Pool实例、Chunk大小配置、InnoDB缓存性能评估、Page管理相关参数、Change Buffer相关参数优化。 2. 日志相关参数优化:日志缓冲区配置、日志文件参数优化。 3. IO线程相关参数优化: 查询缓存参数、脏页刷盘参数、LRU链表参数、脏页刷盘相关参数。
MySQL底层概述—5.InnoDB参数优化
|
1月前
|
存储 SQL 关系型数据库
MySQL底层概述—4.InnoDB数据文件
本文介绍了InnoDB表空间文件结构及其组成部分,包括表空间、段、区、页和行。表空间是最高逻辑层,包含多个段;段由若干个区组成,每个区包含64个连续的页,页用于存储多条行记录。文章还详细解析了Page结构,分为通用部分(文件头与文件尾)、数据记录部分和页目录部分。此外,文中探讨了行记录格式,包括四种行格式(Redundant、Compact、Dynamic和Compressed),重点介绍了Compact行记录格式及其溢出机制。最后,文章解释了不同行格式的特点及应用场景,帮助理解InnoDB存储引擎的工作原理。
MySQL底层概述—4.InnoDB数据文件
|
1月前
|
存储 缓存 关系型数据库
MySQL底层概述—3.InnoDB线程模型
InnoDB存储引擎采用多线程模型,包含多个后台线程以处理不同任务。主要线程包括:IO Thread负责读写数据页和日志;Purge Thread回收已提交事务的undo日志;Page Cleaner Thread刷新脏页并清理redo日志;Master Thread调度其他线程,定时刷新脏页、回收undo日志、写入redo日志和合并写缓冲。各线程协同工作,确保数据一致性和高效性能。
MySQL底层概述—3.InnoDB线程模型
|
1月前
|
存储 SQL 缓存
MySQL原理简介—2.InnoDB架构原理和执行流程
本文介绍了MySQL中更新语句的执行流程及其背后的机制,主要包括: 1. **更新语句的执行流程**:从SQL解析到执行器调用InnoDB存储引擎接口。 2. **Buffer Pool缓冲池**:缓存磁盘数据,减少磁盘I/O。 3. **Undo日志**:记录更新前的数据,支持事务回滚。 4. **Redo日志**:确保事务持久性,防止宕机导致的数据丢失。 5. **Binlog日志**:记录逻辑操作,用于数据恢复和主从复制。 6. **事务提交机制**:包括redo日志和binlog日志的刷盘策略,确保数据一致性。 7. **后台IO线程**:将内存中的脏数据异步刷入磁盘。
104 12
|
3月前
|
存储 缓存 关系型数据库
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
MySQL的存储引擎是其核心组件之一,负责数据的存储、索引和检索。不同的存储引擎具有不同的功能和特性,可以根据业务需求 选择合适的引擎。本文详细介绍了MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案。
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
|
3月前
|
存储 关系型数据库 MySQL
MySQL存储引擎详述:InnoDB为何胜出?
MySQL 是最流行的开源关系型数据库之一,其存储引擎设计是其高效灵活的关键。InnoDB 作为默认存储引擎,支持事务、行级锁和外键约束,适用于高并发读写和数据完整性要求高的场景;而 MyISAM 不支持事务,适合读密集且对事务要求不高的应用。根据不同需求选择合适的存储引擎至关重要,官方推荐大多数场景使用 InnoDB。
106 7