Postgresql

postgresql pg_dump 記憶體不足

  • December 29, 2019

是否可以以某種方式限制 pg_dump 的資源使用?

問題是,整個 DBase 是 775GB,我有兩個非常大的表:

pg_largeobject 表為 – 390GB

pg_largeobject statistics:
Index scans              778313505
Index tuples fetched    1079812292
Tuples inserted          201022148
Table size                  395 GB
Indexes size               6900 MB

hive.lob_messages – 265GB。

Index scans             194377937
Index tuples fetched    183894199
Tuples inserted          16902844
Table size  8127 MB
Toast table size     272573947904
Indexes size              3090 MB

在所有情況下,我都在執行這個 pg_dump 命令:

pg_dump -U postgres -d hive -Fc -v -f /nfs/hive_dump_10/hive_full_20191016_1945.dmp 2> /nfs/hive_dump_10/hive_full_20191016_1945.log

當我嘗試執行 pg_dump 來轉儲所有數據時,它會被“記憶體不足”殺死。我的 Postgre SQL 伺服器有 20gb 的 RAM,當我啟動 pg_dump 時,它會在大約 30 分鐘後終止。記憶體不足的說法。

帶有 20GB rams 和 pg_dump 的 DB 被此 *.log 行殺死:

pg_dump: reading large objects

核心日誌:

Oct 15 09:00:18 hive-psql kernel: [21504626.583951] Out of memory: Kill process 30663 (pg_dump) score 750 or sacrifice child
Oct 15 09:00:18 hive-psql kernel: [21504626.584000] Killed process 30663 (pg_dump) total-vm:19151692kB, anon-rss:16873728kB, file-rss:0kB, shmem-rss:0kB

這是 ZABBIX 監控工具,顯示了我 3 次嘗試使用 20GB 記憶體的 pg 轉儲: 在此處輸入圖像描述

所以為了解決這個問題,我給了我所有的資源,額外的 +20 GB 記憶體(總共 40 GB),它在大約 3 小時後被這個 *.log 行殺死:

pg_dump: dumping contents of table "hive.lob_messages"

kern.log 說:

Oct 16 23:19:01 hive-psql kernel: [15614.408113] Out of memory: Kill process 2693 (pg_dump) score 840 or sacrifice child
Oct 16 23:19:01 hive-psql kernel: [15614.408169] Killed process 2693 (pg_dump) total-vm:38363104kB, anon-rss:34020140kB, file-rss:24kB, shmem-rss:0kB

再次ZABBIX視窗,總共40GB: 在此處輸入圖像描述

我沒有更多的資源。那麼我的選擇是什麼?我的數據庫每天都在增長,謝謝。我認為額外的 20GB 就足夠了,60GB 的記憶體就足夠了。但這是好的情況嗎?當我的數據庫變得像〜2TB大小等時該怎麼辦……

其他問題,我的 hive.lob_messages 表還好嗎?表大小和吐司表大小不同。

該圖顯示的是 pg_dump 可能從 19:45 開始,並且在 20:00 之前具有正常的記憶體消耗。在 20:00,似乎突然分配了大約 30 GB,直到 23:15 才釋放了多少,這可能是記憶體不足的情況發生。

從評論中,核心說:

hive-psql kernel: [15614.408169] Killed process 2693 (pg_dump) total-vm:38363104kB, anon-rss:34020140kB, file-rss:24kB, shmem-rss:0kB

大約 36GB的anon-rsspg_dump 表明確實是 pg_dump 過度分配。需要那麼多記憶體的 pg_dump 有問題。

您的數據庫肯定有很多大對象,其中一些可能非常大(每個對象的理論最大值為 2TB),但 pg_dump 通過以下方式處理大對象:

  • 打開一個游標SELECT oid FROM pg_largeobject_metadata ORDER BY 1並按 1000 個條目的塊讀取它:這永遠不會爆炸。
  • 對於每個大對象,循環 lo_read 以將內容提取到 16384 字節的緩衝區中:這永遠不會爆炸。

表本身重 390 GB 的事實不應成為 pg_dump 進行大分配的理由。

但是,第一次 pg_dump 在“檢索大對象”時被殺死

假設 pg_dump 顯示這個-v選項(順便說一下,你沒有提到傳遞了哪些選項),它應該顯示*“讀取大對象”*。

Postgres pg_dump 犧牲了記憶體分配檢查來加快備份過程。應該重寫 pg_dump 以考慮記憶體不足的問題。我所做的是讓 pg_dump 備份非 blob 欄位,然後我編寫了一個程序來分別備份 blob 欄位。我也必須編寫一個恢復程序。

引用自:https://dba.stackexchange.com/questions/251317