Postgresql

PostgreSQL - 大對象的部分轉儲(pg_largeobject 表)

  • December 7, 2021

背景:我們的網路應用程序就像一個協作平台,您可以在其中共享文件、約會、調查等。該網路應用程序的一個實例被劃分為社區,每個社區彼此獨立但共享同一個 PostgreSQL 數據庫。

目標:實際上我想做的是編寫一個 shell 腳本,以便分別對社區進行定期備份。這意味著我只需要選擇各種 Postgre 表中的部分數據並導出/轉儲社區數據。

障礙:我的大問題是 pg_largeobjects 表,用於儲存文件的 BLOB。該表使用 OID 作為 pk(順便說一下,我不喜歡這種東西)。表文件(包含文件元數據)具有對 pg_largeobject OID 的引用。

考慮的解決方案

    • 從文件表 WHERE community_id = something 中選擇所有 OID。
  • 之後,我可以使用函式從 pg_largeobjects 導出數據流,該[lo_export][1]函式給出在前一個操作中選擇的所有 OID:

> > int lo_export(PGconn *conn, Oid lobjId, const char *filename); > >

這種方法的問題是當我嘗試恢復 pg_largeobject 記錄時,我需要保持相同的 OID,否則關係將被破壞。我可以使用lo_import_with_oid允許定義所需 OID 的函式,但在大多數情況下,OID 已被原始數據佔用,因此導入將生成一個新的 OID,這將不滿足與其餘部分的關係數據庫。

  1. 我仍然不知道如何實現這一目標,但我嘗試解釋:
  • 在導出過程中,我可以選擇並保存某個社區的文件表記錄的所有 PK(我們稱之為 filesPKs)。
  • 然後我將執行[lo_export]pg_largeobjects
  • 在此期間,lo_import我可以忽略正在生成新 OID 的事實。但以某種方式,我會保存插入的這些新 OID 的列表。
  • 作為最後一步,我可以更新文件表中的所有行(使用 filesPKs 引用),以使它們指向新導入的 pg_largeobject 記錄。

在我看來,第二個過程非常困難,因為我仍然看不到如何更新文件行以指向正確的大對象。

  • 另一種選擇是最好的選擇,它是修改 pg_largeobject 表,以便有一個附加列,其中包含對 files 表的(靜態)引用。但是經過測試似乎是不可能的:

testdb=# alter table pg_largeobject 添加列 prova text; 錯誤:權限被拒絕:“pg_largeobject”是系統目錄

問題

  • 還有其他人遇到過這個問題嗎?
  • 我只是錯過了什麼,還是採取了錯誤的方法?
  • 是否存在另一種導出/轉儲 pg_largeobjects 記錄的方法,導出所有欄位,而不僅僅是數據流?

我設法解決了這個問題如下(第二個考慮的解決方案 - 重新審視):

一會兒循環,對於每個文件:

  • 選擇 file_id , file_version, oid 並將它們放入 3 個變數中
  • 執行一個$$ lo_export $$需要定義路徑+文件名的 pg_largeobjects。文件名將是 file_id 和 file_version 的串聯。
  • 在 lo_import 期間將生成新的 OID。但是使用上面定義的文件名,我可以執行最後一步:
  • 更新 files 表中的所有行,以使它們指向新導入的 pg_largeobject 記錄並保持關係一致性

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