PostgreSQL在線將普通表轉(zhuǎn)換為分區(qū)表插件之pg_rewrite
點(diǎn)擊上方“IT那活兒”公眾號(hào),關(guān)注后了解更多內(nèi)容,不管IT什么活兒,干就完了?。?!說到分區(qū),我們首先想到的是表為啥要分區(qū),分區(qū)有什么好處?當(dāng)前版本并不能對(duì)單表或者單個(gè)分區(qū)并行進(jìn)行垃圾回收,包括單表的freeze也只能是單進(jìn)程進(jìn)行凍結(jié)和回收。但是對(duì)于多表或者多個(gè)分區(qū)就可以并行執(zhí)行上述操作,所以在單表數(shù)據(jù)量過大會(huì)發(fā)生什么?
- 1. 當(dāng)進(jìn)行autovacuum垃圾回收時(shí),如果該表的DML操作非常頻繁的話,可能導(dǎo)致垃圾回收不過來,進(jìn)而導(dǎo)致表迅速膨脹,占用過多的空間從而導(dǎo)致故障。
- 2. 單表過大會(huì)導(dǎo)致單表的freeze時(shí)間過長(zhǎng),可能會(huì)導(dǎo)致xid耗盡,此時(shí)就只能停庫操作降低年齡之后才能正常運(yùn)行。在PG 9.6以前的版本,大表的freeze帶來的IOPS影響較大,體現(xiàn)在數(shù)據(jù)文件讀寫、WAL日志大量產(chǎn)生。但9.6及以后版本freeze有大幅改進(jìn),并不會(huì)產(chǎn)生大量的WAL日志了。
- 3. 表沒分區(qū)的話,當(dāng)要清理歷史數(shù)據(jù)時(shí)就只能delete了,大批量的delete會(huì)產(chǎn)生大量的wal日志,從而導(dǎo)致從庫延遲。并且大批量數(shù)據(jù)的delete事務(wù)時(shí)間過長(zhǎng),可能會(huì)導(dǎo)致表膨脹發(fā)生。如果大表分區(qū)了,我們可以通過drop歷史分區(qū)或者truncate歷史分區(qū)的方式清理歷史數(shù)據(jù),不用擔(dān)心大量wal日志的產(chǎn)生,而且執(zhí)行時(shí)間很快。
- 4. 單表的只能位于單個(gè)表空間,對(duì)應(yīng)到單個(gè)目錄,并不能像分區(qū)表那樣將各個(gè)分區(qū)放到不同的表空間,不同的目錄上去。這樣就可能導(dǎo)致某個(gè)目錄對(duì)應(yīng)的盤IO很繁忙,但其他目錄就很空閑的情況。IO不能分散從而導(dǎo)致性能問題的發(fā)生。
單表的邏輯備份恢復(fù)無法并行執(zhí)行,數(shù)據(jù)全量同步時(shí)會(huì)很慢,并且異常中斷后又需要重新開始這個(gè)大表的同步。
當(dāng)然,pg_rewrite使用是有限制的:
- 分區(qū)表建議約束和非分區(qū)表保持一致, 例如not null,default value 等約束。
pg_rewrite是開源的,需要pg 13或更高版本才能安裝。https://github.com/cybertec-postgresql/pg_rewrite1. 設(shè)置PG_CONFIG環(huán)境變量,安裝時(shí),我們必須確保路徑中的pg_config 版本正確。3. 修改postgresql.conf 參數(shù)文件并重啟生效。wal_level = logical
max_replication_slots = 1 #或者在當(dāng)前值上加1。
shared_preload_libraries = pg_rewrite #將pg_rewrite添加到現(xiàn)有庫中
4. 使用超級(jí)用戶創(chuàng)建擴(kuò)展 pg_rewrite,目前該擴(kuò)展只包含一個(gè)函數(shù)partition_table()。它可以將非分區(qū)表轉(zhuǎn)換為分區(qū)表。1. 創(chuàng)建普通表及結(jié)構(gòu)相同的分區(qū)表2. 普通表插入測(cè)試數(shù)據(jù)3. 運(yùn)行 partition_table() 函數(shù)將普通表的數(shù)據(jù)復(fù)制至分區(qū)表,并將普通表的表名修改成自定義表名用于備份。并將分表區(qū)的表名修改成與原普通表一致的表名。
1. rewrite.check_constraints在開始復(fù)制數(shù)據(jù)之前,它會(huì)檢查目標(biāo)表是否與源表具有相同的約束,如果發(fā)現(xiàn)差異則拋出錯(cuò)誤。如果目標(biāo)表上缺少約束,一旦處理完成,違反源表約束的數(shù)據(jù)將被允許出現(xiàn)在目標(biāo)表中。甚至對(duì)目標(biāo)表的額外約束也是一個(gè)問題,因?yàn)閿U(kuò)展只假設(shè)它復(fù)制的所有數(shù)據(jù)確實(shí)滿足源表上的約束,但是它不會(huì)根據(jù)目標(biāo)表上的額外約束來驗(yàn)證它們。默認(rèn)值是true,通過將 rewrite.check_constraints 設(shè)置為 false,用戶可以關(guān)閉約束檢查。但是不建議這么做,最好是提前檢查目標(biāo)表與源表的結(jié)構(gòu)是否一致。2. rewrite.max_xlock_time盡管大多數(shù)時(shí)候正在處理的表可用于其他事務(wù)的讀寫操作,但需要排他鎖來完成處理。如果過多地阻止對(duì)表的訪問,請(qǐng)考慮設(shè)置“rewrite.max_xlock_time”參數(shù)。set rewrite.max_xlock_time to 100;
表示排他鎖的持有時(shí)間不應(yīng)超過 0.1 秒(100 毫秒)。如果最后階段需要更多時(shí)間,則特定函數(shù)會(huì)釋放排他鎖,處理中間其他事務(wù)提交的更改并再次嘗試最后階段。多次超過鎖定時(shí)間會(huì)報(bào)錯(cuò)。如果發(fā)生這種情況,您應(yīng)該增加設(shè)置或稍后在寫入活動(dòng)較低時(shí)嘗試處理有問題的表。默認(rèn)值為 0,這意味著最后階段可以根據(jù)需要花費(fèi)盡可能多的時(shí)間。本文作者:魏 斌(上海新炬王翦團(tuán)隊(duì))
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/129240.html