max复制关键帧到不同的文件_彭占元|如何排除PostgreSQL WAL 文件数量长期持续增加?...
點擊藍字
關注我們
作者簡介
彭占元
2018年8月加入去哪兒網,現負責公司 PostgreSQL/GreenPlum 運維工作,對數據庫日常運維和日常調優有大量優化實踐經驗。
1. 提出問題
最近遇到一個自己運維 DB 的開發同學反饋:"我們的業務量較小,但現在數據庫積累了大量的 WAL, 一個月的時間 pg_wal 目錄和歸檔的目錄均超過了80GB, 且 WAL 增長的速度較快,由于虛擬機的磁盤不大,幾乎把磁盤撐爆了,我應該怎么處理呢?可以先人工刪一下嗎?”
針對這個現象,我們需要分析如下幾個問題:
幾乎沒有業務為什么 WAL 還會增加且增加的還很快?
WAL 會一直增加直至把磁盤撐爆嗎?DBMS 有參數控制上限么?
WAL 文件為什么會保留那么多, DBMS 難道不會自動清理, 需要人工介入么?
2. 分析問題
因為 PostgreSQL 不同版本之間參數有差異,所以確認運行環境是排查問題的第一步。經確認, 出現這一現象的 DB 版本是 PostgreSQL 11,那么針對 pg_wal 目錄下文件數量和尺寸的問題,我們首先明確如下幾個相關參數的含義:
wal_segment_size:單個 WAL 文件的大小,默認為16MB,一般不做更改,且在 pg11 之前,只能在編譯 pg 時指定,很明顯這個參數的影響可以排除。
wal_keep_segments:這個參數配置的是 standby 復制所需的在 pg_wal 目錄中最少保留的 WAL 文件的數目,一般情況下,這大概就是 wal 尺寸范圍,如果這個參數配置為0,那么此時 WAL 文件的數量還取決于如下其他參數。
min_wal_size:這個是 WAL 文件保留的最小尺寸,當 WAL 的使用低于這個配置,那么 WAL 將會在 checkpoint 時候對 WAL 以 recycle 的形式處理,而不是直接 remove。當然這個參數也是有配置范圍限制的:min_wal_size 至少是 wal_segment_size 的2倍。
max_wal_size:這個參數指定是 checkpoint 和 checkpoint 之間產生的 WAL 最大量。當然這只是一個軟限制,在集群負載高或者一些其他異常情況下可能會超過這個值。結合 checkpoint_completion_target 參數, 當新產生的 wal 文件到達特定的數據量后便會觸發 checkpoint。
archive_timeout:如果 DB 實例寫入量很少,到達 archive_timeout 會觸發 WAL 文件的強制切換。因此如果 archive_timeout 如果太短就會產生很多新的 WAL,從而產生大量歸檔。
除了這些參數配置外,還有一些異常情況會造成 WAL 堆積:
如果開啟了歸檔,那么歸檔命令成功了,WAL 才會被 remove/recycle,所以這里需要注意,如果歸檔命令是失效的,那么 pg_wal 目錄會一直增長,不會自動刪除 WAL,此目錄會持續增長,進而有撐爆磁盤的風險。
在創建了復制槽后,如果通過復制槽不能正常消費掉,則會造成 WAL 堆積,導致主庫的 WAL 文件數量一直增加,pg_wal 目錄也會一直增長。
3. 解決問題
根據上述參數描述和分析,我們首先檢查 DB 實例的上述參數。
postgres=# select version(); version --------------------------------------------------------------------------------------------------------- PostgreSQL 11.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16), 64-bit postgres=# show wal_keep_segments ; wal_keep_segments------------------- 128(1 row) postgres=# show min_wal_size ; min_wal_size-------------- 80MB(1 row) postgres=# show max_wal_size ; max_wal_size-------------- 5GB(1 row) postgres=# show archive_timeout; archive_timeout----------------- 1min(1 row) postgres=# select * from pg_stat_get_archiver();-[ RECORD 1 ]------+------------------------------archived_count | 6053last_archived_wal | 00000001 00000017 000000A5last_archived_time | 2020-09-30 11:51:04.366339+08failed_count | 0last_failed_wal |last_failed_time |stats_reset | 2020-08-14 15:02:23.166376+08可見,wal_keep_segments 值為128,但 archive_timeout 設置較小,這就回答了“幾乎沒有業務,為什么 WAL 還會增加且增加的很快”這個問題。建議調大 archive_timeout 參數來降低 WAL 文件的強制切換頻率,WAL 產生過快的問題得以優化。
pg_wal 目錄的文件輕易不要人工處理,但歸檔目錄需要定期將歷史 WAL 備份走然后刪掉,在磁盤緊張的情況下可以先將歸檔這部分處理掉。
繼續觀察,由于 failed_count 是0, 且同時檢查 DB log 沒有任何異常信息,可以排除歸檔失敗導致的 pg_wal 目錄一直增加。
通過上述信息及分析可斷定 WAL 堆積不是由于 wal_keep_segments 參數配置過大或歸檔失敗導致,接下來我們重點分析下 pg_replication_slots。
postgres=#?select?*?from?pg_replication_slots?;-[ RECORD 1 ]-------+-----------slot_name | pgstandby1plugin |slot_type | physicaldatoid |database |temporary | factive | factive_pid |xmin |catalog_xmin |restart_lsn | 0/B000000confirmed_flush_lsn |首先這個復制槽的激活狀態"active = f",可以確定其不是被某些進程正在使用的此復制槽。
接下來我們查看 restart_lsn 對應的 WAL 文件名。
postgres=# select pg_walfile_name('0/B000000');-[ RECORD 1 ]---+-------------------------pg_walfile_name | 00000001000000000000000A從 pg_wal 目錄中可以看到,這個文件是最老的 WAL 文件,創建時間是 2020-08-14,
[postgres@dbhost /export/pgdata/pg_wal]$ ll 00000001000000000000000A-rw------- 1 postgres postgres 16777216 Aug 14 15:03 00000001000000000000000A所以從這里我們基本上可以判斷 WAL 保留這么多是物理槽占用導致的。
此外,我們繼續確認下當前 wal_lsn 和上面開始堆積的 lsn 差異是不是和現在的 pg_wal 尺寸吻合呢?
postgres=# select pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),'0/B000000')); pg_size_pretty---------------- 94 GB(1 row)?
這里的總尺寸也對上了!
問題原因找到了,那么接下來就可以對癥下藥。首先確認下這個復制槽是干什么用的,如果這個復制槽有用,那么把這些堆積的 WAL 消費掉就可以了,如果這個復制槽沒啥用,那么把可以直接 drop 掉這個物理復制槽。
postgres=# select pg_drop_replication_slot('pgstandby1'); pg_drop_replication_slot-------------------------- (1 row)正常情況下,數據庫在做 checkpoint 時或在數據庫重啟時會隨著 recovery 的 checkpoint 而自動 remove/recycle。那么接下來,我們選擇手動執行一個 checkpoint 或等待下一個系統自動的 checkpoint 后 pg_wal 目錄的尺寸就會降下來。
postgres=#?checkpoint;CHECKPOINTpostgres=# \q [postgres@dbhost /export/pgdata/pg_wal]$ du -sh2G .4. 結論
綜述,本案例情形已經明朗:
幾乎沒有業務的數據庫 WAL 量也會增加是因為周期性強制切換 WAL,如果想要 WAL 切換速度降低,我們可以適當調大 archive_timeout,比如從1min 增大為10min 甚至更長時間
DBMS 有參數控制 WAL 的增長幅度和總尺寸,但是很多都是軟限制,而非強制。出現異常的情況下,pg_wal 確實是會無限膨脹下去將磁盤撐爆,DBMS 無法自動處理,需要人工介入。
產生 WAL 堆積在排除參數配置且歸檔成功的情況下,是因為物理復制槽占用導致。可見在此極端情況下,WAL 文件確實會一直堆積,進而出現占滿磁盤的情況,導致 DB 實例異常 shutdown 而產生故障。
DBMS 正常情況下是可以對 WAL 進行自動 remove/recycle,如果出現 WAL 清理不掉的情況,且參數無可疑之處,多半是其他原因引起的,需要仔細分析原因,切忌“頭痛醫頭腳痛醫腳”。比如此例中是因為廢棄的物理復制槽導致,其實廢棄的邏輯復制槽亦可導致此問題。
監控是 DBA 的眼睛,為了防止這樣的意外發生,DBA 可以配置對 pg_wal 總尺寸大小進行監控, 同時也可以對 pg_replication_slots 的狀態進行監控,雙管齊下,防患于未然。
END
總結
以上是生活随笔為你收集整理的max复制关键帧到不同的文件_彭占元|如何排除PostgreSQL WAL 文件数量长期持续增加?...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c malloc 头文件_C语言提高篇_
- 下一篇: python3打包exe_[求助]入坑学