从Purge机制说起,详解GaussDB(for MySQL)的优化策略

purge,gaussdb,for,mysql · 浏览次数 : 0

小编点评

本文分享了华为云社区关于GaussDB(for MySQL) Purge优化的文章,主要介绍了InnoDB引擎中Purge机制的重要性、实现原理以及优化方法。Purge机制有助于回收undo log、清理过期数据、减少磁盘占用,维护数据库整洁与高效。文章首先解释了Purge机制的作用,然后详细描述了Purge操作的三个主要步骤。接着,文章提出了优化Purge机制的方法,包括coordinator与worker流水线化、undo记录二次分发以及Purge线程优先级调整。最后,通过测试验证了优化方法的有效性。 1. **Purge机制的重要性**: - 解释了Purge机制的作用:回收undo log、清理过期数据、减少磁盘占用。 - 介绍了Purge机制的工作原理:通过遍历已提交的update undo log,判断是否存在过期数据,然后进行物理删除。 2. **Purge操作的三个主要步骤**: - 遍历已提交的update undo log:根据undo log header中的信息判断事务是否存在过期数据。 - 通过undo log进行数据的物理删除:扫描undo页面获取undo记录,遍历以确认是否进行清理,然后删除索引中的过期数据。 - 回收undo log:在purge速度影响下,通过截断undo tablespace来实现空间的回收。 3. **Purge优化方法**: - coordinator与worker流水线化:将Purge任务分为coordinator和worker两部分,提高执行效率。 - undo记录二次分发:根据Purge线程数将undo记录分组,增加二次分发机制,避免单线程执行。 - Purge线程优先级调整:提高Purge相关线程的优先级,确保Purge任务能够及时被调度。 4. **测试验证优化效果**: - 空载场景下Purge速度提升:优化后Purge速度有1倍提升。 - SQL执行性能影响:优化特性对业务性能基本可以忽略,QPS基本持平。 总的来说,GaussDB(for MySQL)的Purge优化功能通过流水线化、二次分发和优先级调整等手段,有效避免了数据库undo log堆积,提升了Purge性能,改善了用户体验。

正文

本文分享自华为云社区《【华为云MySQL技术专栏】GaussDB(for MySQL) Purge优化》,作者:GaussDB 数据库。

在MySQL中,尤其是在使用InnoDB引擎时,Purge机制至关重要。它可以回收undo log【1】,清理过期数据,减少磁盘占用,维护数据库的整洁与高效。

Purge机制

MySQL InnoDB引擎使用undo log来保存事务修改记录的历史信息。事务提交后, update undo log(指在delete和update操作中产生的回滚日志)未被立即删除,而是会被记录到undo history list【2】,等待Purge线程进行最后的删除。当undo log不再被任何事务依赖时,系统就会扫描这个undo log,将过期的索引数据删除并清理undo log本身,这个整体的清理过程就是MySQL InnoDB引擎的Purge机制。

Purge的操作可以分成三个主要步骤:
 

1.遍历已经提交的update undo log

根据undo log header中的信息判断这些事务是否存在过期数据,如果判断存在过期数据,就要触发Purge机制进行清理,否则就不需要。

2.通过undo log进行数据的物理删除

其过程主要包括:扫描undo 页面来获取undo记录,遍历undo记录以确认是否要进行清理,如果需要则删除索引中的过期数据。

3.回收undo log

purge的速度会影响已提交的undo log的清理回收,如果purge的清理速度赶不上事务生成undo log的速度,undo log就会出现堆积。如果条件允许的话,对undo tablespace进行truncate(截断)来实现undo空间的回收。

undo log堆积主要会产生两方面的影响:

第一, 额外的存储占用

undo log和索引都有历史版本数据,undo log未及时清理会导致undo log自身以及undo关联的过期索引数据产生堆积,占用额外的存储空间,容易引起不必要的扩容和开销,对客户业务而言是不利的。

第二,性能下降

undo log堆积会导致过期索引数据堆积,索引页面中会存在大量已经标记为delete的数据,这时候每个索引页面实际的有效数据占比就会很低,业务SQL执行中会出现获取少量数据却需要进行大量页面IO的情况,最终导致SQL执行性能劣化。

Purge优化实现

当前undo堆积已经成为数据库运行的一个痛点问题,因此华为云GaussDB(for MySQL)团队专门针对Purge机制存在的问题进行了如下优化。

优化点一:coordinator 与 worker流水线化

Purge任务是由Purge线程完成的,是InnoDB的常驻线程。其线程主要分成两个角色,分别是一个purge coordinator线程和若干个purge worker线程,以下简称为coordinator和worker。

事务的修改可能会残留过期数据在索引中,而老数据的相关信息又存留在undo记录中,事务提交时的undo log会被记录在回滚段的History List中,coordinator负责从History List中获取undo log,读取其中的undo记录,并将可能残留过期数据的undo记录分发给worker来进行处理。所以,当前purge的流程可以简单划分成以下两个阶段:

阶段一:coordinator读取undo log包含的undo页面,获取undo记录。

阶段二:coordinator将读取到的undo记录批量分发给worker来进行处理,线程之间并发执行,且coordinator也会负责一部分undo记录的处理,待coordinator和所有worker都执行完毕后开启下一轮处理。

1.png

图1 purge原生流程

图1所示为原本的Purge流程,阶段一coordinator是单线程执行,阶段二worker是多线程并发,即并行执行,但整体两个阶段是串行执行,即阶段一执行完,阶段二才会继续执行。如果阶段一存在大量undo 页面都需要进行IO,串行执行就会严重影响整体的执行效率。不过,这种两阶段串行化执行的方式是可以优化的。

优化的整体思想即是:将coordinator和worker的执行流水线化。从图1可以看到,在原生Purge流程中,coordinator除了负责扫描获取undo记录的任务,本身也会承担一部分Purge任务,且必须同步等待所有已分发的Purge任务完成之后,才能开始下一批次的undo记录扫描任务,这样就导致阶段一和阶段二是一个串行过程。

若令coordinator只单一地负责undo记录的扫描,不再兼职Purge清理任务,这样在worker执行的过程中,coordinator就能直接继续去获取undo记录, 不再需要同步等待所有的Purge任务完成,这样就可以达到将原本串行的两阶段执行变成流水线执行的目的。

2.png

图2 purge优化流程

图2为优化后的Purge流程,Purge优化会先将innodb_purge_batch_size指定的undo页面拆成若干个小的batch, 拆分的批次数量由innodb_rds_purge_subbatch_size决定。coodinator会先扫描第一个小batch的undo 记录,然后分发给各个worker并行处理,在worker处理过程中,coordinator可以去扫描第二个小batch的undo记录,等到所有worker执行完第一批purge任务后,coordinator将立即分发第二批undo记录,worker继续并行执行,而coordinator则立即开始并行地解析第三个小batch的undo记录,以此类推。

  • 优化效果评估

当coordinator获取完第一个小batch之后,后续coordinator和worker都是同时运行的,每个batch运行的时间由coordinator和worker运行时间较长者决定,为了避免不必要的线程间等待,需要通过调整参数来令两个线程的耗时接近。

目前通过开启innodb_monitor_enable的module_purge监控,观察coordinator的耗时以及worker的耗时,再通过调整innodb_purge_batch_size和innodb_rds_purge_subbatch_size参数,将coordinator和worker的耗时调整到接近,让每个batch整体耗时降低。当前测试结果,innodb_purge_batch_size(600),innodb_rds_purge_subbatch_size(150)为最优配置,在此配置下purge速度有1倍提升。

优化点二:undo记录二次分发

我们发现当前在Purge过程中,coordinator分发undo记录给worker的策略是基于InnoDB层的table id,即对于同一个表的undo记录都会分发给一个worker。

这就会出现一种场景:当单个热点表被频繁执行DML时,会生成大量基于这个表的undo记录,此时无论innodb_purge_threads值设置多大,Purge的任务都只会由一个线程承担,Purge机制由原本设计上的并发执行回退成单线程执行,Purge效率降低。

针对这个问题,我们在保持基于table id分发逻辑的基础上,增加一轮二次分发机制。

  • 整体思路

01 根据Purge线程数将undo记录进行分组(如图3),Purge线程数量为4,因此将undo记录划分为四个分组。

02 第一次分发(基于table id分发):将获取出来的undo记录根据table id进行分配,如果当前分组已存在该table id对应的undo记录,则继续分配至该分组;如果不存在包含该table_id的undo记录的分组,则寻找一个容量最小的分组,然后分配给小容量分组。

03 检测当前分配是否均衡,确认当前是否每个分组的记录数都小于max_n= (m_total_rec + n_purge_threads - 1) / n_purge_threads。

如果是大于max_n则说明当前分组过载,否则就认为是均衡的。如图3中,max_n = (11+4 - 1) / 4 = 3,因此第二个、第四个分组均过载,需要进行二次分发。

04 第二次分发(基于分组负载分发):如果当前分组过载,则将过载部分数据转移至相邻下一个分组,然后校验下一个分组是否过载,循环校验,最多遍历2次所有分组。图4中,最终每个分组的记录数不超过3条,相同table id的undo记录也会分发到不同分组,例如rec3和rec4属于相同的table,经过二次分发最终会分发到不同的分组,但是分发到不同分组对应最后的Purge结果并不影响。

3.png图3 二次分发

4.png

图4 最终分发结果

优化点三:Purge线程优先级调整

考虑到Purge相关的线程均为后台常驻线程,对于GaussDB(for MySQL)而言,有较多后台线程,因此本身Purge相关线程的调度不处于高优先级,Purge线程不会被系统频繁调度。所以,第三个优化点是调整Purge相关线程的优先级,GaussDB(for MySQL)将以高优先级启动Purge线程,确保Purge任务能够及时被调度。

测试验证

预备条件

innodb_rds_fast_purge_enabled: 以上三个优化开启的特性开关,开启后特性全部生效。

innodb_purge_batch_size :单个大batch处理的undo页面数,设置为600,一个大batch会被划分成多个小batch。

innodb_rds_purge_subbatch_size:单个小batch处理的undo页面数,设置为150。

测试模型一:验证空载场景下Purge速度

  • 实例规格:8U32G

  • 数据库版本:GaussDB(for MySQL)-2.0.51.240300

  • 操作系统:EulerOS 2.0(SPS)

  • 数据量:64 张sysbench宽表,单表1000万行数据

  • 并发数: 1/4/8/16/32/64/128/256/512 线程并发,读写模型

  • 数据文件 :为了精确对比purge速度提升效果,我们对比空载场景即无业务负载。使用history length已经达到5亿的数据文件,在空载场景下对比开启优化和未开启优化的清理速度。

实际开启优化后,空载Purge清理速度大约有1倍提升,具体结果展示如下:

5.png

图5 purge速度对比

测试模型二:验证特性开启后对SQL执行性能的影响

  • 实例规格:8U32G

  • 数据库版本:GaussDB(for MySQL)-2.0.51.240300

  • 操作系统:EulerOS 2.0(SPS)

  • 数据量:64 张sysbench宽表,单表1000万行数据

  • 并发数: 1/4/8/16/32/64/128/256/512 线程并发,读写模型

开启和关闭开关后,执行sysbench不同并发下的性能表现如下,开启关闭优化特性后,QPS基本持平,说明优化特性对于业务性能基本可以忽略。

6.png

图6 性能对比

总结

Purge机制负责GaussDB(for MySQL) InnoDB过期数据的清理,对于数据库高性能平稳运行起到至关重要的作用。Purge机制不及时不仅会导致过期数据的堆积,占用大量磁盘空间,还会影响SQL执行效率。当前GaussDB(for MySQL)的Purge优化功能,通过任务流水线化、线程优先级调整、二次分发等手段,避免数据库undo log堆积,极大提升Purge的性能,大幅改善用户体验。

相关概念

【1】Undo Log:即回滚日志,保存了记录修改前的数据。在InnoDB存储引擎中,undo log分为insert undo log和update undo log。

insert undo log是指在insert操作中产生的undo log。由于insert操作的记录,只是对本事务可见,其它事务不可见,所以undo log可以在事务提交后直接删除,而不需要额外操作。

update undo log是指在delete和update操作中产生的undo log。该undo log可能要用于多版本并发控制的老版本数据获取,因此不能在提交的时候删除。

【2】Undo History List:即记录所有已提交事务的undo log的链表,可以通过该链表找到所有未被清理的已提交事务关联的undo log。事务提交时,insert undo log会被回收掉(reused或者free), update undo log则会被移动到Undo History List链表。因此Undo History List的长度即History Length反应了未被处理和回收的update undo log的数量,我们一般通过History Length来评估undo log堆积的情况,可以通过 show engine innodb status实时获取这个值。

 

点击关注,第一时间了解华为云新鲜技术~

 

与从Purge机制说起,详解GaussDB(for MySQL)的优化策略相似的内容:

从Purge机制说起,详解GaussDB(for MySQL)的优化策略

当前GaussDB(for MySQL)的Purge优化功能,通过任务流水线化、线程优先级调整、二次分发等手段,避免数据库undo log堆积,极大提升Purge的性能,大幅改善用户体验。

从安装到配置,教你用Argo CD对接CCE集群完成测试、生产部署

本文使用两个CCE集群模拟测试及生产环境,使用gitlab仓库作为应用部署yaml文件存储仓库,通过Argo CD对接不同CCE集群完成测试、生产环境业务部署。

从PDF到OFD,国产化浪潮下多种文档格式导出的完美解决方案

前言 近年来,中国在信息技术领域持续追求自主创新和供应链安全,伴随信创上升为国家战略,一些行业也开始明确要求文件导出的格式必须为 OFD 格式。OFD 格式目前在政府、金融、税务、教育、医疗等需要文件开放、共享和长期保存的行业中广泛应用。这种趋势在未来几年内将进一步增强。 相较于 PDF,OFD 在

.net入行三年的感想回顾

从21年毕业到现在,还差几天就三年了 工作后才知道,工作年限分为1年以下 、3~5年、5~10年、晋升老板,每段都有每段的故事和总结 回顾下我的前三年工作心路,思考下未来发展之路(emmm,我是觉得我是干不了一辈子程序员的 我的工作地点不在大城市,因为我爸不让我出去,家里也不是很缺钱,所以薪资不会辣

嵌入式行业入行6年的一点小感想

从18年毕业到现在已经工作6年了。 熟悉招聘的人都知道,对于工作年限来说,工作开始的前3年是一个分水岭,3~5年是一个分水岭,5~10年又是一个分水岭。10年以上又是一个分水岭...... 我曾经以工作第3年为一个节点,做过一些小小的总结;现在又是3年了,我想借此机会简单概括一下这些年(21年到~2

从JDK8升级到JDK17

一、概述 鉴于JDK8已经是老古董,还有性能问题,兼且各个公司已经不再维护1.8的JDK,所以升级公司的核心产品之一的后端到JDK到17是相对要紧的事情。 通过升级到jdk17,具有以下好处: 不要在头疼同时适应两个jdk,放下适应JDK8的负担 在生产环境基本上只需要部署一个jdk即可 具有更好的

我的日常AI使用

从去年年初开始,AI技术真正走入了我们的日常生活。从OpenAI到如今字节跳动的coze,我们通过AI大模型可以做很多事情,工具和平台众多,如何选择和使用有必要总结一下。 编程和debug方面 尽管gpt-4和gpt-4o确实很强,但对于持续代码改进和代码调试方面,依然不够好,并且它对于非Plus会

从 Docker Hub 拉取镜像受阻?这些解决方案帮你轻松应对

最近一段时间 Docker 镜像一直是 Pull 不下来的状态,感觉除了挂,想直连 Docker Hub 是几乎不可能的。更糟糕的是,很多原本可靠的国内镜像站,例如一些大厂和高校运营的,也陆续关停了,这对我们这些个人开发者和中小企业来说是挺难受的。之前,通过这些镜像站,我们可以快速、方便地获取所

从“专家”视角看:2024年软件测试行业的八大发展趋势!

随着技术的快速发展和数字化转型的深入推进,软件测试行业正面临着前所未有的变革。2024年,我们可以预见软件测试行业将呈现出几个重要的趋势将深刻影响软件测试的方式、工具和流程。它们将重塑软件测试的格局,提升软件质量,推动整个行业的进步,以下是具体的预判解读,供参考。 1. AI与机器学习的深度整合 在

【译】Visual Studio 17.10 发布了新版扩展管理器

从 Visual Studio 17.10 开始提供新的扩展管理器作为默认预览功能。我们已将基本功能简化为现代风格 UI,以帮助您发现新的扩展并管理已安装的扩展。