pg_dump是一個用于備份PostgreSQL 數據庫的工具。它甚至可以在數據庫正在使用的時候進行完整一致的備份。pg_dump并不阻塞其它用戶對數據庫的訪問(讀或者寫)。
轉儲格式可以是一個腳本或者歸檔文件。腳本轉儲的格式是純文本,它包含許多 SQL 命令,這些 SQL 命令可以用于重建該數據庫并將之恢復到保存成腳本的時候的狀態。使用psql從這樣的腳本中恢復。甚至可以用于在其它機器甚至是其它硬件體系的機器上重建該數據庫,通過對腳本進行一些修改,甚至可以在其它 SQL 數據庫產品上重建該數據庫。
歸檔文件格式必須和pg_restore一起使用重建數據庫。它們允許pg_restore對恢復什么東西進行選擇,或者甚至是在恢復之前對需要恢復的條目進行重新排序。歸檔文件也是設計成可以跨平臺移植的。
如果一種候選文件格式和pg_restore結合,那么pg_dump就能提供一種靈活的歸檔和傳輸機制。 pg_dump可以用于備份整個數據庫,然后就可以使用 pg_restore檢查這個歸檔和/或選擇要恢復的數據庫部分。最靈活的輸出文件格式是"custom"(自定義)格式(-Fc)和 "directory"(目錄)格式(-Fd)。它們允許對歸檔元素進行選取和重新排列,支持并行恢復并且缺省時是壓縮的。 "directory"格式是唯一支持并行轉儲的格式。
pg_dump [connection-option...][option...] [dbname]
dbname
將要轉儲的數據庫名。如果沒有聲明這個參數,那么使用環境變量PGDATABASE。如果那個環境變量也沒聲明,那么使用發起連接的用戶名。
-a/--data-only
只輸出數據,不輸出模式(數據定義)。轉儲表數據、大對象和序列值。
-b/--blobs
在轉儲中包含大對象。除非指定了--schema, --table, --schema-only開關,否則這是默認行為。因此-b 開關僅用于在選擇性轉儲的時候添加大對象。
-c/--clean
輸出命令在輸出創建數據庫命令之前先清理(drop)該數據庫對象。(如果任何對象在目標數據庫中不存在,則轉儲可能生成一些無害的錯誤消息。)
-C/--create
以一條創建該數據庫本身并且與這個數據庫連接命令開頭進行輸出。如果是這種形式的腳本,那么你在運行腳本之前和目的安裝中的哪個數據庫連接就不重要了。如果也聲明了 --clean,那么腳本在重新連接到數據庫之前刪除并重新創建目標數據庫。
-E encoding /--encoding=encoding
以指定的字符集編碼創建轉儲。缺省時,轉儲是按照數據庫編碼創建的。另外一個獲取同樣結果的方法是將PGCLIENTENCODING環境變量設置為期望的轉儲編碼。
-f file /--file=file
輸出文件名。文件基礎輸出格式時可以省略這個參數,這種情況下使用標準輸出。但是,在聲明目標目錄而不是文件時必須給出目錄輸出格式。在這種情況下,目錄通過pg_dump創建并且必須之前不存在。
-F format/--format=format
選擇輸出的格式。format可以是下列之一:
pplain
純文本SQL腳本文件(缺省)。
ccustom
適合輸入到pg_restore里的自定義格式歸檔。加上目錄輸出格式,這是最靈活的格式,它允許在轉儲期間對已歸檔的條目進行手動選擇和重新排列。這個格式缺省的時候是壓縮的。
ddirectory
適合輸入到pg_restore里的目錄格式歸檔。這將創建一個目錄,該目錄包含一個為每個被轉儲的表和二進制大對象的文件,加上一個號稱目錄的文件,該文件以pg_restore可讀的機器可讀格式描述轉儲的對象。目錄格式歸檔可以用標準Unix工具操作;例如,在非壓縮歸檔中的文件可以用 gzip工具壓縮。這個格式缺省的時候是壓縮的,并且也支持并行轉儲。
ttar
適合輸入到pg_restore里的tar歸檔文件。 tar格式兼容目錄格式;提取tar格式歸檔產生一個有效的目錄格式歸檔。不過, tar格式不支持壓縮并且限制單獨的表為8 GB。還有,表數據條目的相關順序在轉儲期間不能更改。
-j njobs /--jobs=njobs
通過同時轉儲njobs表并行運行轉儲。該選項減少了轉儲的時間,但是也增加了數據庫服務器的負載。可以只將這個選項用于目錄輸出格式,因為這是多進程可以同時寫它們的數據的唯一的輸出格式。
pg_dump將打開njobs + 1個到數據庫的連接,所以使用時需要根據max_connections值進行設置,不能大于該值。
-n schema / --schema=schema
只轉儲匹配schema的模式內容,包括模式本身以及其中包含的對象。如果沒有聲明這個選項,所有目標數據庫中的非系統模式都會被轉儲出來。可以使用多個-n選項指定多個模式。同樣,schema參數將按照psql 的/d命令的規則被解釋為匹配模式,因此可以使用通配符匹配多個模式。在使用通配符的時候,最好用引號進行界定,以防止 shell 將通配符進行擴展。
-N schema /--exclude-schema=schema
不轉儲任何匹配schema的模式內容。模式匹配規則與-n完全相同。可以指定多個-N以排除多種匹配的模式。
如果同時指定了-n和-N,那么將只轉儲匹配-n 但不匹配-N的模式。如果出現-N但是不出現-n,那么匹配-N的模式將不會被轉儲。
-o /--oids
作為數據的一部分,為每個表都輸出對象標識(OIDs)。如果你的應用需要OID字段的話(比如在外鍵約束中用到),那么使用這個選項。否則,不應該使用這個選項。
-O /--no-owner
不把對象的所有權設置為對應源數據庫。pg_dump默認發出 ALTER OWNER或SET session AUTHORIZATION 語句以設置創建的數據庫對象的所有權。如果這些腳本將來沒有被超級用戶 (或者擁有腳本中全部對象的用戶)運行的話將會失敗。-O 選項就是為了讓該腳本可以被任何用戶恢復并且將腳本中對象的所有權賦予該選項指定的用戶。
-s/--schema-only
只輸出對象定義(模式),不輸出數據。
-S username/--superuser=username
指定關閉觸發器時需要用到的超級用戶名。它只有使用了--disable-triggers 的時候才有影響。一般情況下最好不要輸入這個參數,而是用超級用戶啟動生成的腳本。
-t table/--table=table
只轉儲出匹配table的表(或視圖、序列、外表)。可以使用多個-t選項匹配多個表。同樣,table 參數將按照psql的/d命令的規則被解釋為匹配模式,因此可以使用通配符匹配多個模式。在使用通配符的時候,最好用引號進行界定,以防止 shell 將通配符進行擴展。
使用了-t之后,-n和-N選項就失效了。因為被-t 選中的表將無視-n和-N選項而被轉儲,同時除了表之外的其他對象不會被轉儲。
-T table/--exclude-table=table
不要轉儲任何匹配table模式的表。模式匹配規則與-t完全相同。可以指定多個-T以排除多種匹配的表。
如果同時指定了-t和-T,那么將只轉儲匹配-t 但不匹配-T的表。如果出現-T但是不出現-t,那么匹配 -T的表將不會被轉儲。
-v/--verbose
指定冗余模式。這樣將令pg_dump 輸出詳細的對象評注以及轉儲文件的啟停時間和進度信息到標準錯誤上。
-V/--version
顯示pg_dump版本
-x/--no-PRivileges --no-acl
禁止轉儲訪問權限(grant/revoke 命令)。
-Z 0..9--compress=0..9
指定要使用的壓縮級別。0表示不壓縮。對于自定義歸檔格式,指定單個表數據段的壓縮,并且缺省是中等水平的壓縮。對于純文本輸出,設置非零壓縮級別會壓縮整個輸出文件,就像通過gzip反饋回來一樣;但是缺省是不壓縮的。 tar歸檔模式當前不支持壓縮。
--binary-upgrade
此選項用于在線升級工具。不建議也不支持用于其他目的。該選項的行為可能會在將來的版本中改變。
--column-inserts--attribute-inserts
把數據轉儲為帶有明確字段名的INSERT命令 (INSERTINTO table (column, ...) VALUES ...)。這樣會導致恢復非常緩慢,它主要用于制作那種可以用于其它非 PostgreSQL數據庫的轉儲。由于這個選項為每條記錄都生成一條命令,因此如果其中某一行命令出錯,那么將僅有該行數據丟失,而不是整個表的數據丟失。
--disable-dollar-quoting
這個選項關閉使用美元符界定函數體。強制它們用 SQL 標準的字符串語法的引號包圍。
--disable-triggers
這個選項只是和創建僅有數據的轉儲相關。它告訴pg_dump 包含在恢復數據時臨時關閉目標表上觸發器的命令。如果在表上有參照完整性檢查或者其它觸發器,而恢復數據的時候不想重載他們,那么就應該使用這個選項。
--exclude-table-data=table
不要轉儲任何匹配table模式的表。模式匹配規則與-t完全相同。可以給出多個--exclude-table-data 以排除多個匹配的表。當你需要指定表的定義時該選項是有用的,即使你不需要表里面的數據。
--inserts
將數據輸出為的INSERT命令(而不是COPY)。這樣會導致恢復非常緩慢。這個選項主要用于制作那種可以用于其它非PostgreSQL數據庫的轉儲。
--lock-wait-timeout=timeout
在轉儲開始的時候不要等待請求一個共享表鎖。相反,如果無法在指定的 timeout內鎖住表則失敗。 timeout可以用任意SET statement_timeout接受的格式聲明
--no-security-labels
不轉儲安全標簽。
--no-synchronized-snapshots
該選項允許在9.2以前的服務器上運行pg_dump -j,參閱-j 參數的文檔獲取更多信息。
--no-tablespaces
忽略表空間
--no-unlogged-table-data
不要轉儲未記錄表的內容。該選項對于表定義(模式)是否轉儲沒有影響;它只阻止轉儲表的數據。當從備用服務器轉儲時,未記錄表中的數據總是排除。
--quote-all-identifiers
強制給所有標識符加上引號。這在轉儲一個數據庫到一個可能引入了額外關鍵字的新版本中時可能是有用的。
--section=sectionname
只轉儲命名的章節。該章節名可以是pre-data, data, 或post-data。可以多次聲明這個選項以選擇多個章節。缺省是轉儲所有章節。
數據章節包含實際的表數據、大對象內容和序列值。原始數據項包含索引、觸發器、規則和約束(除了驗證檢查約束)的定義。之前的數據項包含所有其他數據定義項。
--serializable-deferrable
為轉儲使用一個可串行化的事務,以保證使用的快照和稍后的數據庫狀態一致;做這些是通過等待事務流中的一個點,該點沒有異常會出現,所以不會有轉儲失敗或導致其他事務 serialization_failure而回滾的風險。獲取關于事務隔離和并發控制的更多信息。
--use-set-session-authorization
輸出符合 SQL 標準的SET SESSIONAUTHORIZATION命令而不是ALTER OWNER 命令來確定對象所有權。這樣令轉儲更加符合標準,但是如果轉儲文件中的對象的歷史有些問題,那么可能不能正確恢復。并且,使用SET SESSION AUTHORIZATION 的轉儲需要數據庫超級用戶的權限才能轉儲成功,而ALTER OWNER需要的權限則低得多。
-?--help
顯示關于pg_dump命令行參數的幫助。
控制數據庫的連接參數:
-d dbname--dbname=dbname
聲明要連接的數據庫名稱。相當于在命令行中聲明dbname 作為第一個非選項參數。
-h host--host=host
指定運行服務器的主機名。如果數值以斜杠開頭,則被用作到 Unix 域套接字的路徑。缺省從PGhost環境變量中獲取(如果設置了的話),否則,嘗試一個 Unix 域套接字連接。
-p port--port=port
指定服務器正在偵聽的 TCP 端口或本地 Unix 域套接字文件的擴展(描述符)。缺省使用PGPORT環境變量(如果設置了的話),否則,編譯時的缺省值。
-U username--username=username
連接的用戶名。
-w--no-passWord
從不發出密碼提示問題。如果服務器要求密碼認證并且密碼不可用于其他意思如 .pgpass文件,則連接嘗試將會失敗。該選項在批量工作和不存在用戶輸入密碼的腳本中很有幫助。
-W--password
數據庫連接時需要密碼
--role=rolename
指定創建轉儲的角色名。這個選項導致連接到數據庫之后pg_dump 發出一個SET ROLErolename命令。當認證的用戶(通過-U指定)缺乏pg_dump所需的權限時是很有用的,可以轉變成有所需權限的角色。一些安裝有反對作為超級用戶直接登錄的政策,使用這個選項允許轉儲不違反該政策。環境變量
在參數為設置時,獲取環境變量值
PGDATABASEPGHOSTPGOPTIONSPGPORTPGUSER
用例
將mydb數據庫轉儲到一個 SQL 腳本文件:
$ pg_dump mydb > db.sql |
將上述腳本導入一個(新建的)數據庫newdb:
$ psql -d newdb -f db.sql |
將數據庫轉儲為自定義格式的歸檔文件
$ pg_dump -Fc mydb > db.dump |
將數據庫轉儲為目錄格式歸檔:
$ pg_dump -Fd mydb -f dumpdir |
將數據庫轉儲為目錄格式歸檔,并行5個worker工作:
$ pg_dump -Fd mydb -j 5 -f dumpdir |
將歸檔文件導入一個(新建的)數據庫newdb:
$ pg_restore -d newdb db.dump |
轉儲一個名為mytab的表:
$ pg_dump -t mytab mydb > db.sql |
轉儲detroit模式中所有以emp開頭的表,但是不包括employee_log表:
$ pg_dump -t 'detroit.emp*' -T detroit.employee_log mydb > db.sql |
轉儲所有以east或west開頭并以gsm結尾的模式,但是不包括名字中含有test模式:
$ pg_dump -n 'east*gsm' -n 'west*gsm' -N '*test*' mydb > db.sql |
同上,不過這一次使用正則表達式的方法:
$ pg_dump -n '(east|west)*gsm' -N '*test*' mydb > db.sql |
轉儲所有數據庫對象,但是不包括名字以ts_開頭的表:
$ pg_dump -T 'ts_*' mydb > db.sql |
在-t等選項中指定大寫字母或大小寫混合的名字必須用雙引號界定,否則將被自動轉換為小寫。但是因為雙引號在 shell 中有特殊含義,所以必須將雙引號再放進單引號中。這樣一來,要轉儲一個大小寫混合的表名,你就需要像下面這樣:
$ pg_dump -t "/"MixedCaseName/"" mydb > mytab.sql |

1 –a(只備份數據) 與 –s (只備份模式) 沖突
2 -a(只備份數據) 與 –c (刪除對象) 沖突
3 –inserts(insert 模式)與 –o(備份oid)沖突
4 --if-exists 與 –c 需同時存在
5 -j大于1時–F 為不能為d
文件格式定義:
typedefenum _archiveFormat
{
archUnknown = 0,
archCustom = 1,
archTar = 3,
archNull = 4,
archDirectory = 5
}ArchiveFormat;
通過枚舉定義文件格式類型,分別對應4中不同的文件格式,分別對應4種不同的處理類型,處理過程參考pg_backup_custom.c,pg_backup_directory.c,pg_backup_null.c,pg_backup_tar.c。
文件讀取模式定義:
typedefenum _archiveMode
{
archModeAppend,
archModeWrite,
archModeRead
}ArchiveMode;
通過枚舉定義文件讀寫方式 分別為追加,寫,讀 三中模式。
根據參數-F、--format 初始化輸出文件格式和模式
1 –F ,--format = a/append
文件格式:archNull 讀取模式:archModeAppend
2 –F ,--format = c/custom
文件格式:archCustom 讀取模式:archModeWrite
3 –F ,--format = d/directory
文件格式:archDirectory 讀取模式:archModeWrite
4 –F ,--format = p/plain
文件格式:archNull 讀取模式:archModeWrite
5 –F ,--format = t/tar
文件格式:archTar 讀取模式:archModeWrite
Archive結構
typedefstruct Archive
{
DumpOptions *dopt; /* 備份參數 */
RestoreOptions *ropt; /* 恢復參數*/
int verbose;
char *remoteVersionStr; /* 備份的數據庫版本 str類型*/
int remoteVersion; /* 備份的數據庫版本 int類型 */
bool isStandby; /*是否在進行熱備份 */
int minRemoteVersion; /* 兼容最低的數據庫版本 */
int maxRemoteVersion;
int numWorkers; /* 并發個數 */
char *sync_snapshot_id; /*異步快照id
* Operation */
/* info needed for string escaping */
int encoding; /* libpq code for client_encoding */
bool std_strings; /* standard_conforming_strings */
char *use_role; /* Issue SET ROLE to this */
/* error handling */
bool exit_on_error; /* whether to exit on SQL errors... */
int n_errors; /* number of errors (if no die) */
/* The rest is private */
}Archive;
ArchiveHandle結構:
struct_archiveHandle
{
Archive public; /* Public part of archive */
int version; /* Version of file */
char *archiveRemoteVersion; /* When reading an archive, the
* version of the dumped DB */
char *archiveDumpVersion; /* When reading an archive, the
* version of the dumper */
int debugLevel; /* Used for logging (currently onlyby
* --verbose) */
size_t intSize; /* Size of an integer in the archive*/
size_t offSize; /* Size of a file offset in thearchive -
* Added V1.7 */
ArchiveFormat format; /* Archive format */
sqlparseInfo sqlparse; /* state for parsing INSERT data */
time_t createDate; /* Date archive created */
/*
*Fields used when discovering header. A format can always get the
*previous read bytes from here...
*/
int readHeader; /* Used if file header has been readalready */
char *lookahead; /*Buffer used when reading header to discover
* format */
size_t lookaheadSize; /* Size of allocated buffer */
size_t lookaheadLen; /* Length of data in lookahead */
pgoff_t lookaheadPos; /* Current read position in lookahead buffer */
ArchiveEntryPtr ArchiveEntryPtr; /* Called for each metadata object */
StartDataPtr StartDataPtr; /* Called when table data is about to be
* dumped */
WriteDataPtr WriteDataPtr; /* Called to send some table data to the
* archive */
EndDataPtr EndDataPtr; /* Called when table data dump isfinished */
WriteBytePtr WriteBytePtr; /* Write a byte to output */
ReadBytePtr ReadBytePtr; /* Read a byte from an archive */
WriteBufPtr WriteBufPtr; /* Write a buffer of output to the archive*/
ReadBufPtr ReadBufPtr; /* Read a buffer of input from thearchive */
ClosePtr ClosePtr; /* Close the archive */
ReopenPtr ReopenPtr; /* Reopen the archive */
WriteExtraTocPtr WriteExtraTocPtr; /* Write extra TOC entry data
* associated with the current archive
* format */
ReadExtraTocPtr ReadExtraTocPtr; /* Read extr info associated with
* archie format */
PrintExtraTocPtr PrintExtraTocPtr; /* Extra TOC info for format */
PrintTocDataPtr PrintTocDataPtr;
StartBlobsPtr StartBlobsPtr;
EndBlobsPtr EndBlobsPtr;
StartBlobPtr StartBlobPtr;
EndBlobPtr EndBlobPtr;
SetupWorkerPtr SetupWorkerPtr;
WorkerJobDumPPTr WorkerJobDumpPtr;
WorkerJobRestorePtr WorkerJobRestorePtr;
ClonePtr ClonePtr; /* Clone format-specific fields */
DeClonePtr DeClonePtr; /* Clean up cloned fields */
CustomOutPtr CustomOutPtr; /* Alternative script output routine */
/* Stuff for direct DB connection */
char *archdbname; /*DB name *read* from archive */
trivalue promptPassword;
char *savedPassword; /* password for ropt->username, if known */
char *use_role;
PGconn *connection;
/* If connCancel isn't NULL, SIGINThandler will send a cancel */
PGcancel *volatile connCancel;
int connectToDB; /* Flag to indicate if direct DB connection is
* required */
ArchiverOutput outputKind; /* Flag for what we're currently writing */
bool pgCopyIn; /* Currently in libpq 'COPY IN'mode. */
int loFd; /* BLOB fd */
int writingBlob; /* Flag */
int blobCount; /* # of blobs restored */
char *fSpec; /*Archive File Spec */
FILE *FH; /*General purpose file handle */
void *OF;
int gzOut; /* Output file */
struct _tocEntry *toc; /* Header of circular list of TOCentries */
int tocCount; /* Number of TOC entries */
DumpId maxDumpId; /* largest DumpId among all TOC entries*/
/* arrays created after the TOC list iscomplete: */
struct _tocEntry **tocsByDumpId; /* TOCs indexed by dumpId */
DumpId *tableDataId; /* TABLE DATA ids, indexed by table dumpId */
struct _tocEntry *currToc; /* Used when dumping data */
int compression; /* Compression requested on open Possible
* values for compression: -1
* Z_DEFAULT_COMPRESSION 0 COMPRESSION_NONE
* 1-9 levels for gzip compression */
ArchiveMode mode; /* File mode - r or w */
void *formatData; /*Header data specific to file format */
/* these vars track state to avoidsending redundant SET commands */
char *currUser; /*current username, or NULL if unknown */
char *currSchema; /*current schema, or NULL */
char *currTablespace; /* current tablespace, orNULL */
bool currWithOids; /* current default_with_oids setting */
void *lo_buf;
size_t lo_buf_used;
size_t lo_buf_size;
int noTocComments;
ArchiverStage stage;
ArchiverStage lastErrorStage;
struct _tocEntry *currentTE;
struct _tocEntry *lastErrorTE;
};
ArchiveHandle結構第一個元素為Archive,可以看做是Archive結構的繼承,在保存有Archive成員結構指針的情況下,可以通過指針互轉來實現結構的轉換,此使用方式類似與c++的多態。
初始化 Archive結構變量
Archive*
CreateArchive(constchar *FileSpec, const ArchiveFormat fmt,
const int compression, ArchiveMode mode,SetupWorkerPtr setupDumpWorker)
函數CreateArchive 通過創建并初始化ArchiveHandle 變量,返回一個Archive 變量。
FileSpec需要輸出的文件名。
Fmt 文件格式
Compression壓縮級別
Mode 文件讀取方式
setupDumpWorker多任務啟動函數指針。
設置參數指針到archive.dopt
如果參數中-n, --schema,-N, --exclude-schema ,不空,則通過nspname查詢pg_namespace 獲取其oid,在后面獲取模式對象時進行過濾。
如果參數中 -t,--table ,-T, --exclude-table 不空,則通過relname 查詢pg_class表,獲取其oid
SELECT c.oid FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind in ('r', 'S', 'v', 'm', 'f','P')
如果參數中 --exclude-table-data不空 ,則通過relname 查詢需要忽略器數據的表對象oid。
函數原型: TableInfo *getSchemaData(Archive *fout, int *numTablesPtr)
返回TableInfo數組對象 以及 numTablesPtr表對象個數。
每一種數據對象都定義一種對應的數據結構類型,且都繼承于DumpableObject結構,獲取到的對象結構通過AssignDumpId函數將結構地址寄存于dumpIdMap數組中,通過objtype指定對象類型,以及通過dump成員變量設置是否需要進行備份。
Objtype類型:
typedefenum
{
/* When modifying this enum, updatepriority tables in pg_dump_sort.c! */
DO_NAMESPACE,
DO_EXTENSION,
DO_TYPE,
DO_SHELL_TYPE,
DO_FUNC,
DO_AGG,
DO_OPERATOR,
DO_access_METHOD,
DO_OPCLASS,
DO_OPFAMILY,
DO_COLLATION,
DO_CONVERSION,
DO_TABLE,
DO_ATTRDEF,
DO_INDEX,
DO_RULE,
DO_TRIGGER,
DO_CONSTRAINT,
DO_FK_CONSTRAINT, /* see note for ConstraintInfo */
DO_PROCLANG,
DO_CAST,
DO_TABLE_DATA,
DO_SEQUENCE_SET,
DO_DUMMY_TYPE,
DO_TSPARSER,
DO_TSDICT,
DO_TSTEMPLATE,
DO_TSCONFIG,
DO_FDW,
DO_FOREIGN_SERVER,
DO_DEFAULT_ACL,
DO_TRANSFORM,
DO_BLOB,
DO_BLOB_DATA,
DO_PRE_DATA_BOUNDARY,
DO_POST_DATA_BOUNDARY,
DO_EVENT_TRIGGER,
DO_REFRESH_MATVIEW,
DO_POLICY
}DumpableObjectType;
Dump備份級別:
#defineDUMP_COMPONENT_NONE (0)
#defineDUMP_COMPONENT_DEFINITION (1 <<0)
#defineDUMP_COMPONENT_DATA (1<< 1)
#defineDUMP_COMPONENT_COMMENT (1<< 2)
#defineDUMP_COMPONENT_SECLABEL (1<< 3)
#defineDUMP_COMPONENT_ACL (1<< 4)
#defineDUMP_COMPONENT_POLICY (1<< 5)
#defineDUMP_COMPONENT_USERMAP (1<< 6)
#defineDUMP_COMPONENT_ALL (0xFFFF)
1 獲取擴展對象:pg_extensions
ExtensionInfo*getExtensions(Archive *fout, int *numExtensions)
2 獲取擴展成員pg_depend
Void getExtensionMembership(Archive *fout,ExtensionInfo extinfo[],
int numExtensions)
3 獲取名空間pg_namespace
NamespaceInfo *getNamespaces(Archive *fout,int *numNamespaces)
4 獲取表對象pg_class relkind in ('S','r','v','c','m','f','P')
TableInfo*getTables(Archive *fout, int *numTables)
5 獲取隊列
Void getOwnedSeqs(Archive *fout, TableInfotblinfo[], int numTables)
6 獲取函數對象
FuncInfo *getFuncs(Archive *fout, int *numFuncs)
7 獲取數據類型
TypeInfo *getTypes(Archive *fout, int*numTypes)
8 獲取語言類型
ProcLangInfo *getProcLangs(Archive *fout, int*numProcLangs)
9 獲取聚合函數
AggInfo*getAggregates(Archive *fout, int *numAggs)
10 獲取操作符重載對象
OprInfo*getOperators(Archive *fout, int *numOprs)
11 獲取索引對象
AccessMethodInfo*getAccessMethods(Archive *fout, int *numAccessMethods)
12 獲取索引操作符類
OpclassInfo*getOpclasses(Archive *fout, int *numOpclasses)
13 操作符族
OpfamilyInfo*getOpfamilies(Archive *fout, int *numOpfamilies)
14 文本解析器
TSParserInfo*getTSParsers(Archive *fout, int *numTSParsers)
15 文本搜索模板
TSTemplateInfo*getTSTemplates(Archive *fout, int *numTSTemplates)
16 文本搜索字典
TSDictInfo*getTSDictionaries(Archive *fout, int *numTSDicts)
17 文本搜索配置
TSConfigInfo*getTSConfigurations(Archive *fout, int *numTSConfigs)
18 存儲外部數據封裝器
FdwInfo*getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
19 儲外部服務器
ForeignServerInfo*getForeignServers(Archive *fout, int *numForeignServers)
20 新創建對象的初始化權限
DefaultACLInfo*getDefaultACLs(Archive *fout, int *numDefaultACLs)
21 排序規則
CollInfo*getCollations(Archive *fout, int *numCollations)
22 編碼轉換信息
ConvInfo*getConversions(Archive *fout, int *numConversions)
23 存儲數據類型轉換路徑
CastInfo*getCasts(Archive *fout, int *numCasts)
24 pg_transform
TransformInfo*getTransforms(Archive *fout, int *numTransforms)
25 繼承對象
InhInfo*getInherits(Archive *fout, int *numInherits)
26 分區表
PartInfo*getPartitions(Archive *fout, int *numPartitions)
27 時間觸發器
EventTriggerInfo*getEventTriggers(Archive *fout, int *numEventTriggers)
28 處理擴展表
Void processExtensionTables(Archive*fout, ExtensionInfo extinfo[],
int numExtensions)
29 在tbinfo中擴展繼承信息
staticvoid
flagInhTables(TableInfo*tblinfo, int numTables,
InhInfo *inhinfo, int numInherits)
30 為分區表指定分區范圍,以及父表信息
staticvoid
flagPartitions(TableInfo*tblinfo, int numTables,
PartInfo *partinfo, int numPartitions)
31 獲取表對象附加屬性
void
getTableAttrs(Archive*fout, TableInfo *tblinfo, int numTables)
32 組織屬性到tblinfo信息中
staticvoid
flagInhAttrs(DumpOptions*dopt, TableInfo *tblinfo, int numTables)
34 獲取索引
void
getIndexes(Archive*fout, TableInfo tblinfo[], int numTables)
35 獲取約束
void
getConstraints(Archive*fout, TableInfo tblinfo[], int numTables)
36 獲取觸發器
void
getTriggers(Archive*fout, TableInfo tblinfo[], int numTables)
37 獲取規則
RuleInfo*
getRules(Archive*fout, int *numRules)
38 pg_policy策略
void
getPolicies(Archive*fout, TableInfo tblinfo[], int numTables)
40 獲取分區主表定義信息
void
getTablePartitionKeyInfo(Archive*fout, TableInfo *tblinfo, int numTables)
表對象信息結構:
typedefstruct _tableInfo
{
/*
*These fields are collected for every table in the database.
*/
DumpableObject dobj;
char *rolname; /*name of owner, or empty string */
char *relacl;
char *rrelacl;
char *initrelacl;
char *initrrelacl;
char relkind;
char relpersistence;/* relation persistence */
bool relispopulated;/* relation is populated */
char relreplident; /* replica identifier */
char *reltablespace; /* relation tablespace */
char *reloptions; /*options specified by WITH (...) */
char *checkoption; /* WITH CHECK OPTION, if any */
char *toast_reloptions; /* WITH options for the TOAST table */
bool hasindex; /* does it have any indexes? */
bool hasrules; /* does it have any rules? */
bool hastriggers; /* does it have any triggers? */
bool rowsec; /* is row security enabled? */
bool forcerowsec; /* is row security forced? */
bool hasoids; /* does it have OIDs? */
uint32 frozenxid; /* table's relfrozenxid */
uint32 minmxid; /* table's relminmxid */
Oid toast_oid; /* toast table's OID, or 0 if none */
uint32 toast_frozenxid; /* toast table's relfrozenxid, if any */
uint32 toast_minmxid; /* toast table's relminmxid */
int ncheck; /* # of CHECK expressions */
char *reloftype; /* underlying type for typed table */
/* these two are set only if table is asequence owned by a column: */
Oid owning_tab; /* OID of table owning sequence */
int owning_col; /* attr # of column owning sequence*/
int relpages; /* table's size in pages (frompg_class) */
bool interesting; /* true if need to collect more data */
bool dummy_view; /* view's real definition must bepostponed */
bool postponed_def; /* matview must be postponed intopost-data */
/*
*These fields are computed only if we decide the table is interesting
*(it's either a table to dump, or a direct parent of a dumpable table).
*/
int numatts; /* number of attributes */
char **attnames; /*the attribute names */
char **atttypnames; /* attribute type names */
int *atttypmod; /*type-specific type modifiers */
int *attstattarget; /* attribute statistics targets */
char *attstorage; /*attribute storage scheme */
char *typstorage; /*type storage scheme */
bool *attisdropped; /* true if attr is dropped; don't dump it */
int *attlen; /*attribute length, used by binary_upgrade */
char *attalign; /*attribute align, used by binary_upgrade */
bool *attislocal; /*true if attr has local definition */
char **attoptions; /*per-attribute options */
Oid *attcollation; /* per-attribute collation selection */
char **attfdwoptions; /* per-attribute fdw options */
bool *notnull; /*NOT NULL constraints on attributes */
bool *inhNotNull; /*true if NOT NULL is inherited */
struct _attrDefInfo **attrdefs; /* DEFAULT expressions */
struct _constraintInfo *checkexprs; /*CHECK constraints */
char *partkeydef; /*partition key definition */
/*
*Stuff computed only for dumpable tables.
*/
int numParents; /* number of (immediate) parenttables */
struct _tableInfo **parents; /* TableInfos of immediate parents */
struct _tableDataInfo *dataObj; /* TableDataInfo, if dumping itsdata */
int numTriggers; /* number of triggers for table */
struct _triggerInfo *triggers; /* array of TriggerInfo structs */
struct _tableInfo *partitionOf; /* TableInfo for the partition parent */
char *partitiondef; /* partition key definition */
}TableInfo;
當前節點完成需要備份數據的對象整理,主要數據對象通過遍歷tblinfo數組信息獲取,使用TableDataInfo結構保存需要備份數據的對象,不同的對象類型其objtype不一致。
TableDataInfo結構定義:
typedefstruct _tableDataInfo
{
DumpableObject dobj;
TableInfo *tdtable; /* link totable to dump */
bool oids; /* include OIDs in data? */
char *filtercond; /*WHERE condition to limit rows dumped */
}TableDataInfo;
不需要備份數據的對象:
1 --exclude-table-data 參數指定的表對象不需要備份數據
2 視圖對象不需要備份數據
3 外部表對象不需要備份數據
4 分區主表不需要備份數據
5 unlogged permanent table 表對象并設置了 --no-unlogged-table-data不需要備份數據。
Objtype 類型處理:
1 霧化視圖 dobj.objType =DO_REFRESH_MATVIEW
2 序列dobj.objType =DO_SEQUENCE_SET
3 其它dobj.objType =DO_TABLE_DATA
入口函數:
static void
getTableData(DumpOptions *dopt,TableInfo *tblinfo,intnumTables, booloids, charrelkind)
獲取系統所有對象后,所有對象存放在DumpableObject **dobjs數組當中(保存對象地址),在每個對象創建前可能會依賴于其它對象,因此在處理對象時需要按照一定的順序。
備份時排序通過兩種方式完成:
1 對象類型->模式名->對象名->對象oid
2 對于依賴其它對象的對象,被依賴的對象將優先處理。
通過對象類型排序:
1 對象類型排序順序
在對象數據生成時,每種對象定義對應的objtype,然后通過objtype作為下標定義其排序的優先順序,objtype定義參考DumpableObjectType。
優先順序定義:
staticconst int dbObjectTypePriority[] =
{
1, /*DO_NAMESPACE */
4, /*DO_EXTENSION */
5, /*DO_TYPE */
5, /*DO_SHELL_TYPE */
6, /*DO_FUNC */
7, /*DO_AGG */
8, /*DO_OPERATOR */
8, /* DO_ACCESS_METHOD*/
9, /*DO_OPCLASS */
9, /*DO_OPFAMILY */
3, /*DO_COLLATION */
11, /*DO_CONVERSION */
18, /*DO_TABLE */
20, /*DO_ATTRDEF */
28, /*DO_INDEX */
29, /*DO_RULE */
30, /* DO_TRIGGER */
27, /*DO_CONSTRAINT */
31, /*DO_FK_CONSTRAINT */
2, /*DO_PROCLANG */
10, /*DO_CAST */
23, /*DO_TABLE_DATA */
24, /*DO_SEQUENCE_SET */
19, /*DO_DUMMY_TYPE */
12, /*DO_TSPARSER */
14, /*DO_TSDICT */
13, /*DO_TSTEMPLATE */
15, /*DO_TSCONFIG */
16, /*DO_FDW */
17, /*DO_FOREIGN_SERVER */
32, /*DO_DEFAULT_ACL */
3, /*DO_TRANSFORM */
21, /*DO_BLOB */
25, /*DO_BLOB_DATA */
22, /*DO_PRE_DATA_BOUNDARY */
26, /*DO_POST_DATA_BOUNDARY */
33, /*DO_EVENT_TRIGGER */
34, /*DO_REFRESH_MATVIEW */
35 /*DO_POLICY */
};
2 objtype 一致時,優先根據模式名進行排序
cmpval = strcmp(obj1->namespace->dobj.name,
obj2->namespace->dobj.name)
3 模式名一致時 ,優先排序對象名
cmpval = strcmp(obj1->name,obj2->name);
4 模式名一致時,針對函數,操作運算符,對象屬性等 分別根據參數類型,操作符類型,屬性對象的順序(num)進行排序
5 其它情況優先參考oid大小順序。
排序入口函數:
staticint
DOTypeNameCompare(constvoid *p1, const void *p2)
通過依賴進行排序:
排序入口函數
staticbool
TopoSort(DumpableObject**objs,
int numObjs,
DumpableObject **ordering, /* output argument */
int *nOrdering) /* output argument */
如果參數-n ,-t參數沒有設置并且-a參數沒有設置,生成創建數據庫語法加入到輸出鏈表中(輸出鏈表在3.13中介紹)。
static voiddumpDatabase(Archive *fout)
對象備份根據前面獲取到的對象信息,按照對象本身的性質生成對象創建語法,對象數據備份有copy 方式和insert語法方式,當設定參數--inserts 時,備份的數據以insert 語法的形式輸出,否則以copy的形式輸出。
對象備份和數據備份同樣以DumpableObject的方式保存在對象數組當中,依次遍歷排好序的對象,然后根據定義的objType 類型,按照類型分別處理對象的輸出形式。
從上文中知道NamespaceInfo,ExtensionInfo等結構都繼承于DumpableObject結構,以下處理時能按照需要的結構類型進行轉換。處理邏輯如下:
staticvoid
dumpDumpableObject(Archive*fout, DumpableObject *dobj)
switch (dobj->objType)
{
case DO_NAMESPACE:
dumpNamespace(fout,(NamespaceInfo *) dobj);
break;
case DO_EXTENSION:
dumpExtension(fout,(ExtensionInfo *) dobj);
break;
case DO_TYPE:
dumpType(fout, (TypeInfo *)dobj);
break;
case DO_SHELL_TYPE:
dumpShellType(fout,(ShellTypeInfo *) dobj);
break;
case DO_FUNC:
dumpFunc(fout, (FuncInfo *)dobj);
break;
case DO_AGG:
dumpAgg(fout, (AggInfo *)dobj);
break;
case DO_OPERATOR:
dumpOpr(fout, (OprInfo *)dobj);
break;
case DO_ACCESS_METHOD:
dumpAccessMethod(fout,(AccessMethodInfo *) dobj);
break;
case DO_OPCLASS:
dumpOpclass(fout,(OpclassInfo *) dobj);
break;
case DO_OPFAMILY:
dumpOpfamily(fout,(OpfamilyInfo *) dobj);
break;
case DO_COLLATION:
dumpCollation(fout,(CollInfo *) dobj);
break;
case DO_CONVERSION:
dumpConversion(fout,(ConvInfo *) dobj);
break;
case DO_TABLE:
dumpTable(fout, (TableInfo*) dobj);
break;
case DO_ATTRDEF:
dumpAttrDef(fout,(AttrDefInfo *) dobj);
break;
case DO_INDEX:
dumpIndex(fout, (IndxInfo*) dobj);
break;
case DO_REFRESH_MATVIEW:
refreshMatViewData(fout,(TableDataInfo *) dobj);
break;
case DO_RULE:
dumpRule(fout, (RuleInfo *)dobj);
break;
case DO_TRIGGER:
dumpTrigger(fout,(TriggerInfo *) dobj);
break;
case DO_EVENT_TRIGGER:
dumpEventTrigger(fout,(EventTriggerInfo *) dobj);
break;
case DO_CONSTRAINT:
dumpConstraint(fout,(ConstraintInfo *) dobj);
break;
case DO_FK_CONSTRAINT:
dumpConstraint(fout,(ConstraintInfo *) dobj);
break;
case DO_PROCLANG:
dumpProcLang(fout,(ProcLangInfo *) dobj);
break;
case DO_CAST:
dumpCast(fout, (CastInfo *)dobj);
break;
case DO_TRANSFORM:
dumpTransform(fout,(TransformInfo *) dobj);
break;
case DO_SEQUENCE_SET:
dumpSequenceData(fout,(TableDataInfo *) dobj);
break;
case DO_TABLE_DATA:
dumpTableData(fout,(TableDataInfo *) dobj);
break;
case DO_DUMMY_TYPE:
/* table rowtypes and arraytypes are never dumped separately */
break;
case DO_TSPARSER:
dumpTSParser(fout,(TSParserInfo *) dobj);
break;
case DO_TSDICT:
dumpTSDictionary(fout,(TSDictInfo *) dobj);
break;
case DO_TSTEMPLATE:
dumpTSTemplate(fout,(TSTemplateInfo *) dobj);
break;
case DO_TSCONFIG:
dumpTSConfig(fout,(TSConfigInfo *) dobj);
break;
caseDO_FDW:
dumpForeignDataWrapper(fout,(FdwInfo *) dobj);
break;
case DO_FOREIGN_SERVER:
dumpForeignServer(fout,(ForeignServerInfo *) dobj);
break;
case DO_DEFAULT_ACL:
dumpDefaultACL(fout,(DefaultACLInfo *) dobj);
break;
case DO_BLOB:
dumpBlob(fout, (BlobInfo *)dobj);
break;
case DO_BLOB_DATA:
if (dobj->dump &DUMP_COMPONENT_DATA)
ArchiveEntry(fout,dobj->catId, dobj->dumpId,
dobj->name, NULL, NULL, "",
false, "BLOBS", SECTION_DATA,
"", "", NULL,
NULL, 0,
dumpBlobs, NULL);
break;
case DO_POLICY:
dumpPolicy(fout,(PolicyInfo *) dobj);
break;
case DO_PRE_DATA_BOUNDARY:
case DO_POST_DATA_BOUNDARY:
/* never dumped, nothing todo */
break;
}
}
組織好的語法使用雙向鏈表存儲,鏈表頭在ArchiveHandle結構中進行聲明,每處理一個對象,判別dobj.dump值,處理是否需要備份邏輯,然后將需要備份的對象添加到鏈表當中,輸出時從鏈表中獲取。
鏈表結構:
struct_tocEntry
{
struct _tocEntry *prev;
struct _tocEntry *next;
CatalogId catalogId;
DumpId dumpId;
teSection section;
bool hadDumper; /* Archiver was passed a dumperroutine (used
* in restore) */
char *tag; /*index tag */
char *namespace; /*null or empty string if not in a schema */
char *tablespace; /*null if not in a tablespace; empty string
* means use database default */
char *owner;
bool withOids; /* Used only by "TABLE" tags */
char *desc;
char *defn;
char *dropStmt;
char *copyStmt;
DumpId *dependencies; /* dumpIds of objects this one depends on */
int nDeps; /* number of dependencies */
DataDumperPtr dataDumper; /* Routine to dump data for object */
void *dataDumperArg; /* Arg for above routine */
void *formatData; /*TOC Entry data specific to file format */
/* working state while dumping/restoring*/
teReqs reqs; /* do we need schema and/or dataof object */
bool created; /* set for DATA member if TABLE wascreated */
/* working state (needed only forparallel restore) */
struct _tocEntry *par_prev; /* list linksfor pending/ready items; */
struct _tocEntry *par_next; /* these areNULL if not in either list */
int depCount; /* number of dependencies not yetrestored */
DumpId *revDeps; /*dumpIds of objects depending on this one */
int nRevDeps; /* number of such dependencies */
DumpId *lockDeps; /*dumpIds of objects this one needs lock on */
int nLockDeps; /* number of such dependencies */
};
鏈表輸出入庫函數:
void
ArchiveEntry(Archive*AHX, //ArchiveHandle 備份輸出總結構地址
CatalogId catalogId,// 對象id,
DumpId dumpId, //對象數組下表
const char *tag,//對象名
const char *namespace,//對象所屬模式
const char *tablespace,//表空間
const char *owner, //用戶名
boolwithOids,//是否備份oid
const char *desc,//備份對象的類型名
teSection section,// teSection
const char *defn,//對象創建語法
const char *dropStmt, //對象清除語法
constchar *copyStmt,//對象數據備份語法
const DumpId *deps, int nDeps,
DataDumperPtr dumpFn, void *dumpArg)
備份文件的輸出根據備份參數設置的不同,使用函數指針,實現在統一過程當中,實現不同文件類型的操作,指針的初始化在3.3 節中實現:
switch (AH->format)
{
case archCustom:
InitArchiveFmt_Custom(AH);
break;
case archNull:
InitArchiveFmt_Null(AH);
break;
case archDirectory:
InitArchiveFmt_Directory(AH);
break;
case archTar:
InitArchiveFmt_Tar(AH);
break;
default:
exit_horribly(modulename,"unrecognized file format /"%d/"/n", fmt);
}
其中InitArchiveFmt_Custom 在pg_backup_custom.c文件中實現, InitArchiveFmt_Null 在pg_backup_null.c中實現,InitArchiveFmt_Directory在 pg_backup_directory.c中實現 ,InitArchiveFmt_Tar 在pg_backup_tar.c中實現。
1 普通文本格式文件生成在
Void RestoreArchive(Archive *AHX) 函數中完成,依次輸出注釋,環境設置,對象生成語法到文件當中。
2 其它格式輸出按照占位的方式輸出 ,除了輸出文件頭和文件內容外,其它不同操作實現各不相同 參考如下:
Void CloseArchive(Archive *AHX) 函數中完成,實際通過函數指針調用各自格式的函數。除archNull格式,其它文件輸出都包含文件頭和文件內容兩部分。具體參考各自文件的staticvoid
_CloseArchive(ArchiveHandle *AH) 函數。
文件頭輸出格式一致,包含PGDMP,版本信息,備份時間等信息,具體如下:
void
WriteHead(ArchiveHandle*AH)
{
struct tm crtm;
(*AH->WriteBufPtr) (AH,"PGDMP", 5); /* Magiccode */
(*AH->WriteBytePtr) (AH,ARCHIVE_MAJOR(AH->version));
(*AH->WriteBytePtr) (AH,ARCHIVE_MINOR(AH->version));
(*AH->WriteBytePtr) (AH,ARCHIVE_REV(AH->version));
(*AH->WriteBytePtr) (AH,AH->intSize);
(*AH->WriteBytePtr) (AH,AH->offSize);
(*AH->WriteBytePtr) (AH,AH->format);
WriteInt(AH, AH->compression);
crtm =*localtime(&AH->createDate);
WriteInt(AH, crtm.tm_sec);
WriteInt(AH, crtm.tm_min);
WriteInt(AH, crtm.tm_hour);
WriteInt(AH, crtm.tm_mday);
WriteInt(AH, crtm.tm_mon);
WriteInt(AH, crtm.tm_year);
WriteInt(AH, crtm.tm_isdst);
WriteStr(AH, PQdb(AH->connection));
WriteStr(AH, AH->public.remoteVersionStr);
WriteStr(AH, PG_VERSION);
}
文件內容輸出:
for (te =AH->toc->next;te !=AH->toc;te =te->next)
{
if ((te->reqs & (REQ_SCHEMA |REQ_DATA |REQ_SPECIAL)) == 0)
continue;
WriteInt(AH,te->dumpId);
WriteInt(AH,te->dataDumper ? 1 :0);
/* OIDis recorded as a string for historical reasons */
sprintf(workbuf,"%u",te->catalogId.tableoid);
WriteStr(AH,workbuf);
sprintf(workbuf,"%u",te->catalogId.oid);
WriteStr(AH,workbuf);
WriteStr(AH,te->tag);
WriteStr(AH,te->desc);
WriteInt(AH,te->section);
WriteStr(AH,te->defn);
WriteStr(AH,te->dropStmt);
WriteStr(AH,te->copyStmt);
WriteStr(AH,te->namespace);
WriteStr(AH,te->tablespace);
WriteStr(AH,te->owner);
WriteStr(AH,te->withOids ?"true" : "false");
/* Dumplist of dependencies */
for (i = 0;i <te->nDeps;i++)
{
sprintf(workbuf,"%d",te->dependencies[i]);
WriteStr(AH,workbuf);
}
WriteStr(AH,NULL); /*Terminate List */
if (AH->WriteExtraTocPtr)
(*AH->WriteExtraTocPtr) (AH,te);
}
新聞熱點
疑難解答