总结 by gemini
1. 故障背景
平台环境: 腾讯云 TDSQL-C (云原生数据库)
现象描述: 监控报警显示,MySQL Undo Log 空间在一周内从 300GB 异常增长至 1.3TB,导致磁盘空间占用持续上升。
初步排查: 数据库中没有明显的长事务(Active Transaction),最长的活跃会话仅 5000 多秒(且为 Binlog Dump 线程),常规业务写入耗时偶有超过 1 秒。
2. 排查过程
2.1 常规嫌疑排除
首先按照标准流程排查导致 Undo Log 无法回收的常见原因:
长事务检测: 查询
information_schema.INNODB_TRX,未发现trx_started较早的事务。活跃事务都在 1 秒以内。Sleep 事务检测: 检查是否有程序开启事务后未提交并断开连接(僵尸会话),结果无异常。
XA 事务检测: 执行
XA RECOVER,检查是否有残留的分布式事务(Prepared 状态),结果为空。
2.2 锁定核心指标
排除了“事务阻塞”后,问题指向了“清理速度跟不上生成速度”。执行 SHOW ENGINE INNODB STATUS\G 发现惊人数据:
SQL
------------
TRANSACTIONS
------------
History list length 600,812,666 <-- 积压达 6 亿
分析: 正常系统该值应在几十万级别。6 亿的积压意味着 Purge 系统已经严重滞后。
2.3 瓶颈定位
进一步分析服务器资源负载情况:
Purge 配置:
innodb_purge_threads已开启至最大值 32,但依然无法消化积压。CPU 负载: 扩容前 CPU 使用率长期维持在 70%-90% 的高位,说明计算资源紧张,后台 Purge 线程与前台业务线程存在资源争抢。
内存负载: Buffer Pool 内存占用高,且物理读(Reads/s)数值较大,表明在处理大量历史数据清理时,内存缓存不足以支撑,导致频繁回源读盘。
结论:
这是一起典型的**“小马拉大车”**案例。业务写入压力较大,叠加 6 亿的历史积压清理需求,导致原有的实例规格(CPU 计算能力和内存缓存能力)已达到瓶颈,Purge 线程无法获得足够的资源来追赶进度。
3. 解决方案
资源瓶颈明显,决定申请维护窗口进行垂直扩容。
3.1 垂直扩容
规格变更: 16核 96GB $\to$ 24核 144GB。
目的:
增加内存: 144GB 内存提供更大的 Buffer Pool,大幅提高数据页缓存命中率,减少 Purge 过程中的物理 IO 读取耗时。
增加 CPU: 更多核心缓解了后台 Purge 线程与业务线程的资源争夺,让清理工作能全速运行。
3.2 数据库参数修改
innodb_purge_threads: 4 -> 8
innodb_purge_batch_size: 300 -> 5000
innodb_read_io_threads: 4 -> 12
4. 优化效果
扩容完成后,效果立竿见影:
Undo Log 积压缓解:
History list length立即停止增长并转为下降趋势(6.02亿 $\to$ 6.01亿 $\to$ 5.99亿),说明 Purge 速度终于超过了生成速度。资源负载降低: 在业务量不变的情况下,CPU 使用率从扩容前的 70%-90% 显著下降至 50%-60%,系统运行更加从容。
吞吐量表现: 写 IOPS 小幅上升(7000 $\to$ 8000),侧面反映出 Purge 效率提升后,清理产生的脏页刷盘更加活跃。
5. 总结
对于 MySQL Undo Log 积压问题,在排除了长事务这一最常见原因后,应当重点关注 History List Length 这一关键指标。
当该指标达到亿级且持续增长时,往往意味着数据库的“消化能力”(Purge)已经落后于“进食能力”(写入)。在本案例中,通过垂直扩容(增加 CPU 和内存),用硬件资源换取了处理效率,成功化解了存储空间持续爆炸的风险。