記一次Postgres CPU爆滿故障


問題描述

公司項目測試環境調用某些接口的時候,服務器立即崩潰,並一定時間內無法提供服務。

問題排查

服務器配置不夠

第一反應是服務器需要升配啦,花錢解決一切!畢竟測試服務器配置確實不高,2CPU + 4Gib,能干啥?不過問題是今天突然發生的,而且說崩就崩。憑着嚴謹的態度,還是要刨根問底地找下問題。

查看服務器負載

  • free -m

內存占用並不大,忘記截圖了,反正看下來不是內存過高導致的崩潰

  • top

數據庫占用CPU過高

連接數過多

業務高峰活躍連接陡增,活躍的連接數是否比平時多很多

SELECT 
  COUNT(*) 
FROM 
  pg_stat_activity 
WHERE 
  STATE NOT LIKE '%idle';

查詢下來只有3個連接,所以不是連接數導致的CPU過高

慢SQL

如果活躍連接數的變化處於正常范圍,則可能是當時有性能很差的SQL被大量執行。

select 
  datname, 
  usename, 
  client_addr, 
  application_name, 
  state, 
  backend_start, 
  xact_start, 
  xact_stay, 
  query_start, 
  query_stay, 
  replace(
    query, 
    chr(10), 
    ' '
  ) as query 
from 
  (
    select 
      pgsa.datname as datname, 
      pgsa.usename as usename, 
      pgsa.client_addr client_addr, 
      pgsa.application_name as application_name, 
      pgsa.state as state, 
      pgsa.backend_start as backend_start, 
      pgsa.xact_start as xact_start, 
      extract(
        epoch 
        from 
          (now() - pgsa.xact_start)
      ) as xact_stay, 
      pgsa.query_start as query_start, 
      extract(
        epoch 
        from 
          (now() - pgsa.query_start)
      ) as query_stay, 
      pgsa.query as query 
    from 
      pg_stat_activity as pgsa 
    where 
      pgsa.state != 'idle' 
      and pgsa.state != 'idle in transaction' 
      and pgsa.state != 'idle in transaction (aborted)'
  ) idleconnections 
order by 
  query_stay desc 
limit 
  5;

可以看到,確實有一條慢SQL,而且屬於奇慢無比,執行了接近1分鍾還沒執行完畢,基本可以定位,是慢SQL導致的CPU占用陡增。

問題解決

對於上面的方法查出來的慢SQL,首先需要做的是Kill掉他們,使業務先恢復。

select pg_cancel_backend(pid) from pg_stat_activity where  query like '%<query text>%' and pid != pg_backend_pid();
select pg_terminate_backend(pid) from pg_stat_activity where  query like '%<query text>%' and pid != pg_backend_pid();

如果這些SQL確實是業務上必需的,則需要對他們做如下優化:

  1. 對查詢涉及的表,執行ANALYZE <table>VACUUM ANZLYZE <table>,更新表的統計信息,使查詢計划更准確。為避免對業務影響,最好在業務低峰執行。
  2. 執行explain <query text>explain (buffers true, analyze true, verbose true) <query text>命令,查看SQL的執行計划(前者不會實際執行SQL,后者會實際執行而且能得到詳細的執行信息),對其中的Table Scan涉及的表,建立索引。
  3. 重新編寫SQL,去除掉不必要的子查詢、改寫UNION ALL、使用JOIN CLAUSE固定連接順序等,都是進一步深度優化SQL的手段,這里不再深入說明。

總結

在查詢語句中,盡量減少不必要的子查詢,公司使用的ORM框架是Spring JPA,針對一些特別慢的HQL,可以采用直接執行SQL的方式來優化查詢效率。

    @Query(value = "select count(*) from example_table where example_id = :exampleId", nativeQuery = true)
    int exampleNativeQuery(@Param("exampleId") Long exampleId);

參考

PostgreSQL/PPAS CPU使用率高的原因及解決辦法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM