PostgreSQL VACUUM 沒有效果(無法清理死元組)的原因


眾所周知,在PostgreSQL里面使用VACUUM FULL來回收dead tuples空間並將其返回給操作系統。但是我執行VACUUM FULL卻沒有任何效果,是數據庫版本出現了bug?當然不是!
經排查原來是Physical Replication Slot導致(具體解釋見http://mysql.taobao.org/monthly/2015/02/03/)。將hot_standby_feedback設為on時,從庫關閉,主庫的xmin不再改變,主庫的vaccum操作停滯,造成主庫被頻繁更新的表大小暴增。

為什么VACUUM不清理死元組

VACUUM只能刪除不再需要的那些行版本(也稱為“元組”)。如果刪除事務的事務 ID(存儲在xmax中)早於 PostgreSQL 數據庫(或共享表的整個集群)中仍處於活動狀態的最舊事務,則無法清除元組

在 PostgreSQL 集群中,有三件事可以阻止這個VACUUM回收死元組:

  1. 長時間運行的事務:

    可以通過以下查詢找到長時間運行的事務及其xmin值:

    SELECT pid, datname, usename, state, backend_xmin
    FROM pg_stat_activity
    WHERE backend_xmin IS NOT NULL
    ORDER BY age(backend_xmin) DESC;

    可以使用該pg_terminate_backend()函數來終止阻止您的VACUUM.

  2. 廢棄的Replication Slot:

    復制槽是一種數據結構,保持從主庫丟棄但仍需要由備用服務器趕上主要信息PostgreSQL服務器的數據。

    如果復制延遲或備用服務器關閉,復制槽將阻止VACUUM刪除舊行。

    可以使用此查詢找到所有復制槽及其xmin值:

    SELECT slot_name, slot_type, database, xmin
    FROM pg_replication_slots
    ORDER BY age(xmin) DESC;

    使用該pg_drop_replication_slot()函數刪除不再需要的復制槽。

    注意:如果hot_standby_feedback = on對於邏輯復制存在類似的危險(無法回收元組),但只有系統目錄受到影響。catalog_xmin在這種情況下檢查列

  3. 孤立的准備運行的事務:

    兩階段提交期間,分布式事務首先用PREPARE語句准備,然后用COMMIT PREPARED語句提交

    一旦一個事務准備好,它就會一直“等待”直到它被提交或中止。它甚至必須在服務器重啟后還需要保留下來!通常,事務不會長時間保持准備狀態,但有時會出錯,必須由管理員手動刪除准備好的事務。

    可以xmin使用以下查詢找到所有准備好的交易及其價值:

    SELECT gid, prepared, owner, database, transaction AS xmin
    FROM pg_prepared_xacts
    ORDER BY age(transaction) DESC;

    使用ROLLBACK PREPAREDSQL 語句刪除准備好的事務。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM