大多數(shù)人最初意識(shí)到這個(gè)問題,認(rèn)為他們需要監(jiān)控的問題,就是事務(wù) ID 回卷本身,但從技術(shù)上講,事務(wù) ID 的耗盡才是真正的問題。PostgreSQL 在技術(shù)上能夠很好地處理事務(wù) ID 的回卷。但是,如果達(dá)到回卷點(diǎn),事務(wù) ID 會(huì)即將用完,這才是為什么回卷本身會(huì)令人擔(dān)憂的原因。
以下查詢可以提供非常簡單的數(shù)據(jù),來指示問題的趨勢(shì)/警報(bào)。
WITH max_age AS ( SELECT 2000000000 as max_old_xid , setting AS autovacuum_freeze_max_age FROM pg_catalog.pg_settings WHERE name = 'autovacuum_freeze_max_age' ), per_database_stats AS ( SELECT datname , m.max_old_xid::int , m.autovacuum_freeze_max_age::int , age(d.datfrozenxid) AS oldest_current_xid FROM pg_catalog.pg_database d JOIN max_age m ON (true) WHERE d.datallowconn )SELECT max(oldest_current_xid) AS oldest_current_xid , max(ROUND(100*(oldest_current_xid/max_old_xid::float))) AS percent_towards_wraparound , max(ROUND(100*(oldest_current_xid/autovacuum_freeze_max_age::float))) AS percent_towards_emergency_autovacFROM per_database_stats;
percent_towards_wraparound 指標(biāo)是設(shè)置警報(bào)的真正關(guān)鍵指標(biāo)。由于它使用 age() 函數(shù)來確定事務(wù) ID 值,因此它會(huì)考慮它們是否真的處于耗盡點(diǎn),以查看回卷是否是一個(gè)真正的問題。如果達(dá)到耗盡,數(shù)據(jù)庫將被迫關(guān)閉,并可能導(dǎo)致不確定的停機(jī)時(shí)間,以進(jìn)行修復(fù)。此查詢中有一點(diǎn)緩沖,因?yàn)樗鼨z查的上限(確切地說是 20 億)小于導(dǎo)致耗盡的實(shí)際最大整數(shù)值。但它已經(jīng)足夠接近了,應(yīng)該立即對(duì)達(dá)到 100% 的警報(bào)采取行動(dòng)。
percent_towards_emergency_autovac 指標(biāo)是我們建議監(jiān)控的一個(gè)附加值,特別是對(duì)于以前從未監(jiān)控過此指標(biāo)的系統(tǒng)(請(qǐng)參閱下面有關(guān)凍結(jié)的近期好處的說明,了解何時(shí)可以調(diào)低該警報(bào)優(yōu)先級(jí)或移除它)。它將監(jiān)視數(shù)據(jù)庫中達(dá)到 autovacuum_freeze_max_age 的最高事務(wù) ID 值。
這是一個(gè)用戶可調(diào)的值,默認(rèn)值為 2 億,當(dāng)任何表的最高事務(wù) ID 值達(dá)到該值時(shí),在該表上會(huì)啟動(dòng)一次更高優(yōu)先級(jí)的自動(dòng)清理。您可以識(shí)別出這個(gè)特殊的清理會(huì)話,因?yàn)樵?pg_stat_activity 中,它會(huì)被標(biāo)記為 (to prevent wraparound)。從某種意義上說,它的優(yōu)先級(jí)更高,即使禁用了自動(dòng)清理,它也會(huì)運(yùn)行,如果手動(dòng)取消該清理,它幾乎會(huì)立即再次重新啟動(dòng)。它還需要一些不同的內(nèi)部低級(jí)鎖,因此根據(jù)它們?cè)诰o急清理期間的鎖定方式,可能會(huì)在這些表上引起稍高的爭用。
如果您確實(shí)遇到爭用/鎖定問題,并且可以確認(rèn)問題來源于緊急清理,那么取消它以完成其他事務(wù)也是完全安全的。請(qǐng)注意,它會(huì)繼續(xù)重新啟動(dòng),直到能夠成功完成回卷式清理或運(yùn)行了一次手動(dòng)清理。
對(duì)于每秒事務(wù)數(shù)很高的數(shù)據(jù)庫,想要避免緊急清理期的頻繁出現(xiàn),增加 autovacuum_freeze_max_age 可能是有益的。增加此值的主要問題是,它可能會(huì)增加數(shù)據(jù)目錄下 pg_xact 和 pg_commit_ts 文件夾中的存儲(chǔ)空間。同樣,請(qǐng)閱讀上面鏈接中的日常清理文檔,了解調(diào)整此設(shè)置時(shí)的這些存儲(chǔ)要求。一般可以將此值設(shè)置為 10 億,不會(huì)有太大問題,但前提是需要確定有在監(jiān)控回卷并且磁盤空間足夠。
要使最高事務(wù) ID 的 age 值回落,最簡單(但不一定是最快)的方法是,強(qiáng)制對(duì)整個(gè)數(shù)據(jù)庫集群進(jìn)行一次清理。要實(shí)現(xiàn)這種集群范圍的清理,最好方法是用 PostgreSQL 附帶的 vacuumdb 二進(jìn)制實(shí)用程序。
vacuumdb --all --freeze --jobs=2 --echo --analyze
--all 選項(xiàng)可確保對(duì)所有數(shù)據(jù)庫都進(jìn)行清理,因?yàn)槭聞?wù) ID 是一個(gè)全局值。--freeze 選項(xiàng)可確保運(yùn)行更激進(jìn)的清理,以確保在該表中凍結(jié)盡可能多的元組(有關(guān)凍結(jié)的詳細(xì)信息,請(qǐng)參閱日常清理)。
--jobs=2 允許并行運(yùn)行多個(gè)清理。這應(yīng)該設(shè)置在系統(tǒng)處理能力的范圍內(nèi),以加快速度,但要小心設(shè)置得太高,因?yàn)樗鼤?huì)導(dǎo)致額外的 IO 和更快地生成 WAL(增加磁盤使用率)。--echo 只是提供一些很小的反饋,以讓您可以看到一些進(jìn)度。--analyze
在這里要提到的 --freeze 選項(xiàng)的另一個(gè)好處是,在未來的清理操作中,可以大大減少 IO 和 WAL 的產(chǎn)生。PostgreSQL 9.6 引入了一項(xiàng)功能,如果頁面中的所有元組都已標(biāo)記為凍結(jié),則 vacuum 能夠跳過該頁面。PostgreSQL 11 在索引方面對(duì)此進(jìn)行了進(jìn)一步改進(jìn)。
因此,如果您有很多舊表不再被寫入,那么當(dāng)它們因任何原因需要 vacuum 時(shí),這是一個(gè)成本低得多的操作。這也讓 percent_towards_emergency_autovac 警報(bào)不那么令人擔(dān)憂,因?yàn)樗粫?huì)產(chǎn)生太多意外的突發(fā)活動(dòng)。因此,一旦你把事情調(diào)整好了,你可以把這個(gè)警報(bào)看作是低優(yōu)先級(jí)的警告,甚至可以刪除它,只用擔(dān)心對(duì)回卷本身的監(jiān)控。
本文鏈接:http://www.tebozhan.com/showinfo-26-88733-0.htmlPostgreSQL 的事務(wù) ID 回卷,應(yīng)對(duì)措施也很簡單
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com
上一篇: 從零開始搭建 Kafka 集群