RDS for PostgreSQL CPU过载定位及处理建议
本章节的所有SQL操作都使用root用户执行。
场景介绍
CPU过载的典型表现为数据库实例的CPU使用率在短时间内(几十秒到几分钟)从正常水平迅速飙升至100%,导致查询响应延迟、连接超时、服务不可用。
CPU使用率指标说明
系统CPU使用率:指的是整个系统CPU运行时间占总CPU时间的百分比。
CPU使用率分别有用户态CPU时间占比和内核态CPU时间占比:
- 用户态CPU时间占比:是用户程序运行时的状态。
- 内核态CPU时间占比:是操作系统的管理程序运行时的状态,包含系统调用,内核线程和中断。
可能原因
CPU过载的原因排查思路如图1。
- 活跃连接数陡增
活跃连接数陡增会有两个比较典型的现象:内核态CPU时间占比>20%,活跃连接数会有陡增的情况,可以结合起来一起看。
- ECS资源争抢(非独享型实例)
在内核态CPU时间占比>20%的场景中,还有一种比较罕见的情况:ECS资源争抢,这种情况发生在非独享型(包括:通用型、通用增强型等)实例中。
通常情况下,RDS for PostgreSQL实例上的内核态CPU都是低于10%的,当内核态CPU时间占比>10%以上就要警惕是否是由ECS资源争抢导致的CPU爆满,可以提交工单确认是否发生资源争抢。
- 慢SQL被大量执行
华为云RDS for PostgreSQL数据库有慢SQL日志,可以通过这个日志,定位到当时比较耗时的SQL来进一步做分析。但通常问题发生时,整个系统都处于停滞状态,所有SQL都慢下来,当时记录的慢SQL可能非常多,并不容易找到目标。
这里推荐几种追查慢SQL的方法,除了慢SQL以外,还有一些简单执行时间很短的SQL,在某些情况下(例如:在事务中循环执行、大量的并发执行)也会导致CPU消耗的陡增。
追查慢SQL方法如下:
- 通过pg_stat_statements插件定位导致CPU消耗增高的SQL,详细使用请参考使用pg_stat_statements插件。
- 通过pg_stat_activity视图查看当前长时间执行的SQL。
使用root用户执行如下SQL获取可能造成CPU过高的SQL:
SELECT *, (now() - backend_start) AS proc_duration, (now() - xact_start) AS xact_duration, (now() - query_start) AS query_duration, (now() - state_change) AS state_duration FROM pg_stat_activity WHERE pid<>pg_backend_pid() ORDER BY state_duration DESC limit 10;
- 通过查询pg_stat_user_tables,排查数据库中存在的大量的全表扫描的表以及对应的SQL。
select * from pg_stat_user_tables order by seq_tup_read desc, seq_scan desc limit 10;
- 结合pg_stat_statements或者pg_stat_activity,排查是否存在对应的慢SQL。
前提需要安装pg_stat_statements插件。
使用root用户执行如下SQL,结合pg_stat_statements排查慢SQL:
select * from pg_stat_statements where query like '%tablename%' order by shared_blks_hit + shared_blks_read desc;
使用root用户执行如下SQL,结合pg_stat_activity排查慢SQL:
select *, (now() - backend_start) AS proc_duration, (now() - xact_start) AS xact_duration, (now() - query_start) AS query_duration, (now() - state_change) AS state_duration from pg_stat_activity where pid<>pg_backend_pid() and query like '%tablename%' ORDER BY state_duration DESC;
这些慢SQL通常是由于缺少查询对应的索引,导致过多的buffer读,从而消耗大量CPU。
对业务的影响
- 查询响应延迟:SQL执行时间大幅增加,正常秒级查询可能变为分钟级。
- 吞吐量下降:数据库处理请求的能力降低,TPS/QPS显著减少。
- 连接超时:客户端连接可能因等待CPU资源而超时断开。
- 主从复制延迟:备库或只读实例同步滞后,数据一致性受影响。
- 连接池耗尽:应用端连接池等待时间增长,甚至耗尽导致业务失败。
处理建议
出现过载异常前的建议:
- 监控告警:分别配置CPU使用率 > 70% 时触发预警,以及CPU使用率 > 85% 时触发告警的规则,详见设置告警规则。
- 慢查询优化:定期分析慢查询日志,使用EXPLAIN ANALYZE优化执行计划。
- 索引优化:确保高频查询字段有合适索引,避免全表扫描。
- 实例规格升级:根据业务增长预期,提前升级CPU规格。
- 连接池管理:合理设置max_connections,避免瞬时并发冲击。
过载异常中的建议:
- 活跃连接数陡增
从业务侧确认陡增活跃连接数是否是业务所需,若为业务所需建议通过提高实例规格来解决问题,否则从业务上优化活跃连接数陡增问题,或者kill不需要的会话,降低实例CPU消耗,详见管理实时会话。
kill会话操作可能会导致业务断连,建议业务有重连机制,请谨慎操作。
过载异常后的复盘优化:
- SQL层面优化
- 建立慢查询治理机制,针对业务中慢SQL进行整改。
- 使用 EXPLAIN ANALYZE 优化执行计划:避免全表扫描、顺序扫描,确保关联字段有索引。
- 避免使用SELECT *:只查询需要的字段,减少数据传输。
- 批量操作优化:大批量INSERT/UPDATE/DELETE操作改为分批执行。
- 架构层面优化
- 连接池优化:合理限制最大连接数。
- 只读实例弹性扩展:配置只读实例自动弹性伸缩,应对读流量峰值。
- 容量规划


