postgresql pg_dump 記憶體不足
是否可以以某種方式限制 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
我沒有更多的資源。那麼我的選擇是什麼?我的數據庫每天都在增長,謝謝。我認為額外的 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-rss
pg_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 欄位。我也必須編寫一個恢復程序。