往期分享
RDS MySQL 小版本更新最佳實踐 RDS MySQL 執行個體空間問題 RDS MySQL 記憶體使用問題 RDS MySQL 活躍線程數高問題 RDS MySQL 慢SQL問題 RDS MySQL 執行個體IO高問題IO基本概念
- IO,就是對磁盤進行讀寫的動作。
- IO延時,一個IO操作的執行時間。
- 邏輯IO,由應用程式發給檔案系統的IO。
- 實體IO,由檔案系統發給磁盤的IO。
- 順序IO,順序的從磁盤進行讀寫動作。
- 随機IO,随機的通路磁盤進行讀寫操作。
- 同步寫,需要等資料完全寫入磁盤進行傳回。
- 異步寫,無需等待資料寫入磁盤進行傳回,釋放CPU資源。
IO高的常見原因
SQL掃描行高
檢視資源監控的資料盤IOPS

可以發現基本都是讀占用的,一般用戶端SQL通路的資料都是從資料庫共享緩沖區進行傳回,如果資料未在共享緩沖區命中就會需要從磁盤中進行讀取,讀的IOPS比較高,說明大量的從磁盤讀取資料到資料庫共享緩沖區中,可能存在SQL掃描行較高的情況。
檢視引擎監控
發現全表掃描行明顯增加,說明用戶端讀取了大量的資料。
檢視性能洞察
可以找到對應的問題SQL,可以對問題SQL進行索引優化或者增加規格承擔更高的負載。
導入資料
從圖中可以看出有大量的寫入IOPS,懷疑存在大量的資料導入動作。
檢視das中的性能洞察可以發現是由該操作導緻的IOPS升高
盡量避免高峰期的資料導入動作。
Vacuum操作
vacuum指的是PostgreSQL需要對垃圾資料進行清理動作,一般update和delete過程,資料表會産生垃圾資料造成膨脹,需要及時通過vacuum進行清理回收空間。
此時可以看到IOPS中讀寫都占用了較多的資源。
檢視引擎監控操作行數
此時發現操作行數沒有明顯增加,此時可以懷疑是vacuum或者CheckPoint引起的IOPS升高,通過查詢pg_stat_progress_vacuum可以檢視目前正在運作vacuum的動作及vacuum的進度。可以确定是由vacuum引起的IOPS升高。
postgres=# select * from pg_stat_progress_vacuum ;
-[ RECORD 1 ]------+--------------
pid | 109229
datid | 13593
datname | postgres
relid | 40435
phase | scanning heap
heap_blks_total | 943453
heap_blks_scanned | 937101
heap_blks_vacuumed | 0
index_vacuum_count | 0
max_dead_tuples | 291
num_dead_tuples | 0
通過pg_stat_user_tables也可以檢視曆史vacuum的情況
postgres=# select * from pg_stat_user_tables where relname ='t_all';
-[ RECORD 1 ]-------+------------------------------
relid | 40435
schemaname | public
relname | t_all
seq_scan | 4547
seq_tup_read | 35959634448
idx_scan |
idx_tup_fetch |
n_tup_ins | 91514896
n_tup_upd | 0
n_tup_del | 0
n_tup_hot_upd | 0
n_live_tup | 91514896
n_dead_tup | 0
n_mod_since_analyze | 0
last_vacuum | 2020-11-20 14:25:19.077927+08
last_autovacuum |
last_analyze |
last_autoanalyze | 2020-11-20 11:59:34.641906+08
vacuum_count | 1
autovacuum_count | 0
analyze_count | 0
autoanalyze_count | 5
對于vacuum引起的IO升高可以通過調整vacuum相關參數進行降低vacuum對IO産生的影響。
autovacuum_vacuum_cost_delay指的是vacuum動作代價達到autovacuum_vacuum_cost_limit時vacuum程序休息的時間機關是ms。autovacuum_vacuum_cost_limit指的是vacuum程序代價評估的門檻值。通過這兩個參數調整可以很大程度降低vacuum操作對于生成環境IO的影響,同時也需要考慮vacuum回收速度慢也會導緻表膨脹的更加嚴重。
CheckPoint
CheckPoint指的是将資料庫共享緩沖區的髒頁進行寫入到磁盤的操作,一般該行為由四種條件觸發
-
- 定時觸發,通過checkpoint_timeout參數定時将将資料庫共享緩沖區的髒頁進行寫入到磁盤,此行為為異步寫,資料分多次小批量寫入磁盤,對IO影響小。
- wal日志寫入量達到max_wal_size觸發,wal日志是循環使用的,當日志量達到max_wal_size,會觸發積極的CheckPoint,此行為為同步寫,會全速進行資料寫入動作,對IO影響大。
- 手動CheckPoint,此行為為同步寫,會全速進行資料寫入動作,對IO影響大。
- 重新開機執行個體,此行為為同步寫,會全速進行資料寫入動作,對IO影響大。
目前對于這種情況可以通過查詢pg_stat_bgwriter分析,checkpoints_timed指的是定時觸發的次數,checkpoints_req指的是手動觸發以及wal日志寫入量達到max_wal_size觸發,如果checkpoints_req高需要關注是否有大批量導入的情況,可以控制批量導入的大小,最好調整為小批量,多批次導入。
postgres=# select * from pg_stat_bgwriter ;
-[ RECORD 1 ]---------+------------------------------
checkpoints_timed | 8271
checkpoints_req | 160
checkpoint_write_time | 9109283
checkpoint_sync_time | 22878
buffers_checkpoint | 1228674
buffers_clean | 829714
maxwritten_clean | 293
buffers_backend | 3731358
buffers_backend_fsync | 0
buffers_alloc | 2290169
stats_reset | 2020-06-28 15:32:00.021466+08