Postgresql
PostgreSQL - 大對象的部分轉儲(pg_largeobject 表)
背景:我們的網路應用程序就像一個協作平台,您可以在其中共享文件、約會、調查等。該網路應用程序的一個實例被劃分為社區,每個社區彼此獨立但共享同一個 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,這將不滿足與其餘部分的關係數據庫。
- 我仍然不知道如何實現這一目標,但我嘗試解釋:
- 在導出過程中,我可以選擇並保存某個社區的文件表記錄的所有 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 記錄並保持關係一致性