大數(shù)據(jù)“復(fù)活”記
838
2025-04-04
vacuum的功能
回收空間
數(shù)據(jù)庫總是不斷地在執(zhí)行刪除,更新等操作。良好的空間管理非常重要,能夠?qū)π阅軒泶蠓岣摺?/p>
執(zhí)行delete操作后,表中的記錄只是被標(biāo)示為刪除狀態(tài),并沒有釋放空間,在以后的update或insert操作中該部分的空間是不能夠被重用的。
在數(shù)據(jù)庫中用于維護(hù)數(shù)據(jù)庫磁盤空間的工具是VACUUM,其重要的作用是刪除那些已經(jīng)標(biāo)示為刪除的數(shù)據(jù)并釋放空間。經(jīng)過vacuum清理后,空間才能得到釋放。
VACUUM回收已刪除元組占據(jù)的存儲空間。在一般的數(shù)據(jù)庫操作里,那些已經(jīng)DELETE的元組或者被UPDATE過后過時(shí)的元組是沒有從它們所屬的表中物理刪除的;在完成VACUUM之前它們?nèi)匀淮嬖凇R虼宋覀冇斜仨氈芷诘剡\(yùn)行VACUUM,特別是在常更新的表上。
凍結(jié)tuple的xid
在每條記錄(tuple)的header中,存放xmin,xmax信息(增刪改事務(wù)ID)。transactionID的最大值為2的32次,即無符整形來表示。當(dāng)transactionID超過此最大值后,會循環(huán)使用。
這會帶來一個(gè)問題:就是最新事務(wù)的transactionID會小于老事務(wù)的transactionID。如果這種情況發(fā)生后,就沒有辦法按transactionID來區(qū)分事務(wù)的先后,也沒有辦法實(shí)現(xiàn)MVCC了。
因此用vacuum后臺進(jìn)程,按一定的周期和算法觸發(fā)vacuum動作,將過老的tuple的header中的事務(wù)ID進(jìn)行凍結(jié)。凍結(jié)事務(wù)ID,即將事務(wù)ID設(shè)置為“2”(“0”表示無效事務(wù)ID;“1”表示bootstrap,即初始化;“3”表示最小的事務(wù)ID)。被凍結(jié)的事務(wù)ID比任何事務(wù)都要老。這樣就不會出現(xiàn)上面的這種情況了。
更新visibility map
在數(shù)據(jù)庫中,有一個(gè)visibility map用來標(biāo)記那些page中是沒有dead tuple的。這有兩個(gè)好處,一是當(dāng)vacuum進(jìn)行scan時(shí),直接可以跳過這些page。二是進(jìn)行index-only scan時(shí),可以先檢查下visibility map。這樣減少fetch tuple時(shí)的可見性判斷,從而減少IO操作,提高性能。另外visibility map相對整個(gè)relation,還是小很多,可以cache到內(nèi)存中。
vacuum full與vacuum的區(qū)別
1.vacuum只是將刪除狀態(tài)的空間釋放掉,轉(zhuǎn)換到能夠重新使用的狀態(tài),但是對于系統(tǒng)來說該數(shù)據(jù)塊的空閑空間并沒有反應(yīng)到系統(tǒng)的元數(shù)據(jù)中,并不進(jìn)行空間合并。
而vacuum full實(shí)質(zhì)上是重建了整個(gè)表,以達(dá)到空間合并的效果。
2.vacuum執(zhí)行過程中對表加4級鎖,不會影響表的增刪改查,而vacuum full對表加8級鎖,執(zhí)行過程中表無法訪問。
3.vacuum對列存表無效
vacuum full的執(zhí)行流程
建臨時(shí)表
數(shù)據(jù)庫會新建一個(gè)臨時(shí)表,臨時(shí)表繼承老表所有屬性。
這個(gè)階段會對pg_class申請“RowExclusiveLock”鎖,因?yàn)樾枰迦胗涗洝?/p>
拷貝數(shù)據(jù)
將原來的數(shù)據(jù)copy到temp表中。
對臨時(shí)表,老表以及索引都以“AccessExclusiveLock”模式打開。
另外對于toast,只是lock,不打開。
在這個(gè)過程中完成Dead Tuple的清理。
表交換
新表將老表替換掉。會對pg_class再次申請“RowExclusiveLock”鎖。
重建索引
是在交換之后完成的,重建索引時(shí),會更新一些統(tǒng)計(jì)信息。對表申請“ShareLock”鎖。
刪除臨時(shí)表
索引重建完成后,將帶有老物理文件的新臨時(shí)表進(jìn)行刪除。
vacuum full執(zhí)行慢的常見場景
1. 存在鎖爭搶
在cn上執(zhí)行select * from pg_stat_activity where query like '%vacuum%';找到vacuum full的pid
查看該線程的等待狀態(tài),如果等待狀態(tài)是acquire lock,說明存在鎖等待
select * from pg_thread_wait_status where tid = 139878309295872;
在pg_locks中查詢vacuum full在等哪個(gè)鎖
select * from pg_locks where pid = 139878309295872 and granted = 'f';
查看持有該鎖的線程
select * from pg_locks where relation = 544793 and granted = 't';
查看該線程對應(yīng)的語句
select query from pg_stat_activity where pid = 139877539612416;
根據(jù)語句判斷是否可以殺掉該語句繼續(xù)做vacuum full,或者另外找時(shí)間窗做vacuum full
2. 存在IO/網(wǎng)絡(luò)問題導(dǎo)致事務(wù)無法提交
執(zhí)行一個(gè)簡單的create table語句,如果create table語句執(zhí)行也很慢,說明存在IO/網(wǎng)絡(luò)問題,進(jìn)一步排查IO和網(wǎng)絡(luò)
3. 系統(tǒng)表過大導(dǎo)致vacuum full慢
vacuum full任意一張表時(shí),都會掃描pg_class、pg_partition、pg_proc三張系統(tǒng)表,當(dāng)這三個(gè)系統(tǒng)表過大時(shí),也會導(dǎo)致vacuum full較慢
可以在排除IO/網(wǎng)絡(luò)問題(即create table語句不慢)后,對空表做vacuum full,觀察執(zhí)行速度,如果空表做vacuum full也比較慢,則說明就是這三張系統(tǒng)表較大導(dǎo)致vacuum full任意表都慢
4. 排除以上場景之后,可以查看表定義中是否使用了PCK
當(dāng)存在PCK時(shí),表做vacuum full時(shí)會進(jìn)行全排序,此時(shí)如果表較大或psort_work_mem設(shè)置較小,就會導(dǎo)致PCK排序時(shí)產(chǎn)生下盤,進(jìn)行外排,效率急劇下降。
可以通過調(diào)大psort_work_mem進(jìn)行規(guī)避
EI企業(yè)智能 數(shù)據(jù)倉庫服務(wù) GaussDB(DWS) Gauss AP
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。