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