更新时间:2026-08-06 GMT+08:00
分享

RDS for PostgreSQL CPU过载定位及处理建议

本章节的所有SQL操作都使用root用户执行。

场景介绍

CPU过载的典型表现为数据库实例的CPU使用率在短时间内(几十秒到几分钟)从正常水平迅速飙升至100%,导致查询响应延迟、连接超时、服务不可用。

CPU使用率指标说明

系统CPU使用率:指的是整个系统CPU运行时间占总CPU时间的百分比。

CPU使用率分别有用户态CPU时间占比和内核态CPU时间占比:

  • 用户态CPU时间占比:是用户程序运行时的状态。
  • 内核态CPU时间占比:是操作系统的管理程序运行时的状态,包含系统调用,内核线程和中断。

可能原因

CPU过载的原因排查思路如图1

图1 排查思路
  • 活跃连接数陡增

    活跃连接数陡增会有两个比较典型的现象:内核态CPU时间占比>20%,活跃连接数会有陡增的情况,可以结合起来一起看。

    • 查看内核态CPU时间占比

      通过管理控制台中的监控平台中内核态CPU时间占比监控项进行查看,选择近1小时查看当前的内核态CPU时间占比。

      图2 查看内核态CPU时间占比

      若内核态CPU时间占比高于​20%​,此时说明可能存在大量的系统调用或者中断,通常对应的是系统中存在大量正在工作的进程。

      当活跃连接数超出了实例规格的承受能力,系统不停地切换CPU中运行的进程,而内核程序切换CPU让其在不同的地址空间上操作,导致内核态CPU时间占比升高。

    • 查看活跃连接数

      通过管理控制台中的监控平台中的活跃连接数监控项进行查看,选择近24小时或近7天查看最近一段时间的活跃连接数的情况,确认是否存在陡增现象以及陡增时间点。

      图3 查看活跃连接数

      正常情况下,合理的活跃会话数量应当是当前CPU核数的2倍,此时的CPU使用效率最高。

  • 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方法如下:

    1. 通过pg_stat_statements插件定位导致CPU消耗增高的SQL,详细使用请参考使用pg_stat_statements插件
    2. 通过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;
    3. 通过查询pg_stat_user_tables,排查数据库中存在的大量的全表扫描的表以及对应的SQL。

      使用root用户执行如下SQL获取存在大量全表扫描的表:

      select * from pg_stat_user_tables order by seq_tup_read desc, seq_scan desc limit 10;
    4. 结合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会话操作可能会导致业务断连,建议业务有重连机制,请谨慎操作。

  • ECS资源争抢(非独享型实例)

    如果确认是ECS资源争抢,建议转为独享型实例。

  • 慢SQL被大量执行

    定位到导致CPU消耗增加的SQL,对SQL进行优化。

过载异常后的复盘优化:

  • SQL层面优化
    • 建立慢查询治理机制,针对业务中慢SQL进行整改。
    • 使用 EXPLAIN ANALYZE 优化执行计划:避免全表扫描、顺序扫描,确保关联字段有索引。
    • 避免使用SELECT *:只查询需要的字段,减少数据传输。
    • 批量操作优化:大批量INSERT/UPDATE/DELETE操作改为分批执行。
  • 架构层面优化
    • 连接池优化:合理限制最大连接数。
    • 只读实例弹性扩展:配置只读实例自动弹性伸缩,应对读流量峰值。
  • 容量规划
    • 实例规格升级:根据业务增长,评估是否需要升级CPU规格
    • 至少预留30%余量:日常CPU使用率控制在50%~60%,峰值不超过70%。
    • 长期监控趋势:分析过去3~6个月的CPU使用趋势,提前规划扩容CPU

相关文档