MogDB/openGauss 故障排查流程
前提
如果有反饋說資料庫響應慢或者壓測過程中資料庫有報錯,第一步先收集資料庫伺服器資源使用情況,這一步是處理所有故障的前提。
--負載
top 命令
htop 命令
--cpu
lscpu 命令
--記憶體大小
free -g
--磁碟大小
df-Th
--磁碟使用跟蹤
nohup iostat -xmt 1 > iostat.log 2>&1 &
--網路延時
應用程式與資料庫之間的網路延時,叢集內主庫與同步備庫之間的網路延時
nohup ping 目標ip | awk '{ print $0"\t" strftime("%Y-%m-%d %H:%M:%S",systime())}' > ping.log 2>&1 &
*模擬網路延時小知識*
模擬同城機房網路延遲在0.7ms ~ 0.9ms
新增網路延遲模擬:tc qdisc add dev enp23s0f1(網路卡) root netem delay 0.8ms 0.1ms
刪除網路延時模擬:tc qdisc dev dev enp23s0f1(網路卡) root netem delay 0.8ms 0.1ms
常見問題
xlog 目錄磁碟空間不足
xlog 日誌目錄滿的原因有以下幾個
1、叢集內有當機的備節點,或者主備節點之間的網路不通
2、無效的複製槽未及時清理
3、開啟歸檔,但歸檔失敗
4、xlog 保留數量過多
備節點故障
透過網路及資料庫日誌資訊,判斷節點故障原因,並儘快恢復主備節點之間的複製關係,當故障無法快速解決時,建議修改資料庫引數來改變主庫 xlog 保留大小
enable_xlog_prune = on
max_size_for_xlog_prune:預設是2T,建議修改值為104857600 (100GB),或根據磁碟空間自行調整
無效複製槽
檢視是否存在無效的複製槽導致 xlog 清理不及時,需要將延時最大的複製槽刪除
--檢視複製槽
select slot_name,coalesce(plugin,'_') as plugin,
slot_type,datoid,coalesce(database,'_') as database,
active,coalesce(xmin,'_') as xmin,
pg_size_pretty(pg_xlog_location_diff(CASE WHEN pg_is_in_recovery() THEN pg_last_xlog_receive_location() ELSE pg_current_xlog_location() END , restart_lsn)) AS retained_bytes
from pg_replication_slots;
--清理複製槽
select pg_drop_replication_slot('slot_name');
歸檔失效
先檢查歸檔目錄是否有歸檔日誌,如果沒有,需要檢視資料庫日誌歸檔失效的原因。
xlog 引數不合理
檢查資料庫 xlog 保留引數值是否合理: wal_keep_segments
CPU 使用率高
除了資料庫 BUG、其他程式耗 cpu 高影響資料庫外,絕大部分原因是 SQL 執行慢且併發量大引起
1、當前正在執行的SQL彙總
select query,count(*) from pg_stat_activity group by query order by 2 desc limit 5;
2、檢視sql的執行計劃
explain (analyze,costs,buffers,timing) QUERY
3、sql涉及的表是否有表膨脹、索引失效或缺失或重複 的情況,這步可以處理80%的慢sql
--表結構
\d+ 表名
--表及索引佔空間大小
SELECT CURRENT_CATALOG AS datname,nsp.nspname,rel.relname,
pg_size_pretty(pg_total_relation_size(rel.oid)) AS totalsize,
pg_size_pretty(pg_relation_size(rel.oid)) AS relsize,
pg_size_pretty(pg_indexes_size(rel.oid)) AS indexsize,
pg_size_pretty(pg_total_relation_size(reltoastrelid)) AS toastsize
FROM pg_namespace nsp
JOIN pg_class rel ON nsp.oid = rel.relnamespace
WHERE nspname NOT IN ('pg_catalog', 'information_schema') AND rel.relkind = 'r'
order by pg_total_relation_size(rel.oid) desc
limit 20;
--表膨脹
select schemaname,relname,n_live_tup,n_dead_tup,
round((n_dead_tup::numeric/(case (n_dead_tup+n_live_tup) when 0 then 1 else (n_dead_tup+n_live_tup) end ) *100),2) as dead_rate
from pg_stat_user_tables
where n_live_tup > 0 and (n_dead_tup::numeric/(n_dead_tup+n_live_tup))>0
order by 5 desc limit 50;
--索引使用率
select schemaname||'.'||relname tablename,schemaname||'.'||indexrelname indexname,idx_scan,idx_tup_read,idx_tup_fetch from pg_stat_user_indexes;
--重複索引
SELECT pg_size_pretty(SUM(pg_relation_size(idx))::BIGINT) AS SIZE,
(array_agg(idx))[1] AS idx1, (array_agg(idx))[2] AS idx2,
(array_agg(idx))[3] AS idx3, (array_agg(idx))[4] AS idx4
FROM (
SELECT indexrelid::regclass AS idx, (indrelid::text ||E'\n'|| indclass::text ||E'\n'|| indkey::text ||E'\n'||COALESCE(indexprs::text,'')||E'\n' || COALESCE(indpred::text,'')) AS KEY
FROM pg_index) sub
GROUP BY KEY HAVING COUNT(*)>1
ORDER BY SUM(pg_relation_size(idx)) DESC;
4、根據執行計劃判斷sql是否需要改寫
記憶體不足
1、檢視伺服器實體記憶體整體使用情況。
2、檢查資料庫記憶體引數設定是否合理:
max_process_memory 建議設定實體記憶體 80%
shared_buffers 建議設定為實體記憶體的 40%
資料庫記憶體使用分佈
檢視整體記憶體使用情況,當 dynamic_used_memory 與 max_dynamic_memory 的值接近時說明動態記憶體可能不足,如果 dynamic_peak_memory 超過了 max_dynamic_memory,說明曾經發生過 oom
select * from gs_total_memory_detail;
連線過多耗盡記憶體
主要排除是連線數過多導致記憶體不足的場景
檢視連線數分佈
select state,count(*) from pg_stat_activity group by state;
各狀態連線佔用總記憶體情況
select state,pg_size_pretty(sum(totalsize))
from gs_session_memory_detail m,pg_stat_activity a
where substring_inner(sessid,position('.' in sessid)+1)=a.sessionid
group by state;
單會話佔用記憶體排序
select sessid,pg_size_pretty(sum(totalsize)),pg_size_pretty(sum(freesize)) from gs_session_memory_detail group by sessid order by sum(totalsize) desc limit 10;
快取機制
會話的快取機制不合理,也會導致記憶體無法快速釋放,可能與引數 local_syscache_threshold 有關係。
記憶體上下文使用記憶體分佈
select contextname,pg_size_pretty(sum(totalsize)),pg_size_pretty(sum(freesize)) from gs_session_memory_detail group by contextname order by sum(totalsize) desc limit 10;
總結
動態記憶體高一般有以下幾個原因:
1、連線數過多會導致動態記憶體耗盡,
如果是 idle 連線多,可能是開發端長連線保留數量不合理;
如果是 active 連線多,可能是硬體記憶體不足,需要擴記憶體。
2、單個會話佔用記憶體多,需要根據 sql 去分析佔用記憶體情況