记一次TelePG数据库年龄过大导致服务中断事件的处置案例
背景介绍
某日中午,接到驻场同事的求助电话,某个TelePG数据库服务出现异常,UPDATE、INSERT等语句执行失败,但SELECT查询正常,系统无法正常使用。检查数据库日志,数据库告警:为避免回卷(wraparound)导致数据库丢失,需要进入单用户模式执行vacuum操作。
根据提示信息,现场同事已经尝试对业务表进行了vacuume操作,但仍有少量表的年龄未下降,数据库未能恢复正常。该数据库目前为预生产用途,未正式承载生产业务,但项目组希望能够尽快恢复使用。
二线技术团队迅速介入处置,对可能影响数据库年龄的各项因素进行检查,进入单用户模式,手工执行vacuum freeze命令对相关表进行清理,移除死元组(dead tuple),冻结事务标识(TXID),最终表年龄下降到合理值,数据库服务恢复正常。
原因分析
本次事件发生在一套一主一从架构的TelePG数据库上。通过分析数据库日志,可以判断是数据库TXID耗尽引起的服务异常。导致这种问题的原因多种多样,大量的写入操作、长时间运行的事务、硬盘坏块、不合理的参数配置等等,都有可能导致数据库年龄快速增长,最终造成数据库停止服务。
处理过程
本次事件涉及的TelePG数据库尚未承载生产业务,但用户希望系统能够尽快恢复正常。因此,我们结合数据库日志信息,对可能导致库年龄异常增长的因素优先展开排查,以下是排查过程:
1、检查数据库年龄
某数据库的年龄已经超过21亿。
2、找出年龄过大的表
部分业务数据表的年龄已经接近、超过21亿。
3、检查是否存在预处理事务
本次案例没有未提交的预处理事务,若存在,则应当提交或回滚预处理事务。
4、检查是否存在长时间运行的事务
部分后台进程的运行时间超过40分钟。可通过pg_terminate_backend()强制中止这些长事务。
5、检查是否存在异常的复制槽
本案例不存在异常的复制槽,若存在,可通过pg_drop_replication_slot()删除。
为了使数据库尽快恢复使用,在征得用户同意后,我们关闭从库,主库进入单用户模式进行清理操作,以下是操作过程。
6、主库进入单用户模式
7、再次确认准备执行清理的表
8、执行vacuum freeze命令
vacuum freeze命令会以迫切模式(eager mode)执行,强制冻结指定表中的所有事务标识,该操作通常会扫描指定表的大量页面(page),产生大量IO操作。本次案例清理一张业务表用时10分钟左右。
重复上述步骤,清理其它年龄过大的表。
9、退出单用户模式,检查表年龄
检查vacuum freeze后表年龄的大小,相关表的年龄已经降为0。
数据库使用人员反馈数据库读写已经恢复正常。
10、备份数据库等后续操作
总结复盘
回顾本次事件,连续几日,项目组陆续向预生产数据库导入业务数据,与此同时,数据库恰巧存在长事务,导致自动执行的autovacuum以及人工发起的vacuum作业无法达到预期的清理效果,最早的TXID无法得到回收,而持续导入的数据使得表年龄不断增长,最终表的年龄超过了21亿,导致数据库拒绝写入。
思考与启示
本次事件源于TelePG数据库表年龄超限(21亿)导致的数据库拒绝写入异常。从中我们可以看出,在数据库运行过程中,必须高度重视数据库的健康状况,强化对关键指标的监控和预警机制,及早发现问题、迅速采取措施,主动化解潜在风险。
专家点评
在这个案例中,一线技术人员发现了数据库存在异常,在采取措施未果的情况下,请求二线技术专家介入。二线技术人员迅速定位并排查了可能导致异常的其他数据库指标,在与数据库用户沟通后果断采取措施解决问题。本次事件,是一则比较典型的数据库异常解决案例,对于处置TelePG数据库异常问题、数据库系统的保障工作具有较大的参考价值。