一、循環調用getopt_long解析命令行參數,將參數保存到static DumpOptions dopt;中
二、判斷參數是否相容,不相容則退出:git
options -s/--schema-only and -a/--data-only cannot be used together options -c/--clean and -a/--data-only cannot be used together options --inserts/--column-inserts and -o/--oids cannot be used together option --if-exists requires option -c/--clean
三、調用CreateArchive打開輸出文件,輸出流爲fout。該函數使用4個文件封裝了4種不一樣dump文件格式,增長新文件能夠增長新的導出文件類型各自封裝,獨立易於維護。sql
CreateArchive->_allocAH: 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); }
四、fout是一個重要的全局變量
五、調用ConnectDatabase鏈接數據庫
六、調用setup_connection,在鏈接上執行一些SQL語句:數據庫
SELECT pg_catalog.set_config('search_path', '', false); set client_encoding to '%s'//pg_dump -E指定 SET ROLE %s// SET DATESTYLE = ISO; SET INTERVALSTYLE = POSTGRES; SET extra_float_digits TO 3; SET synchronize_seqscans TO off; SET statement_timeout = 0; SET lock_timeout = 0; SET idle_in_transaction_session_timeout = 0; SET row_security = off; BEGIN; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ ONLY;
七、爲兼容低版本,根據服務器版本號決定一些變量取值
八、調用tblinfo = getSchemaData(fout, &numTables);決定導出哪些數據庫對象。本函數又調用以下函數,值得關注哦。爲了存儲每一個對象的元數據,這些函數會malloc申請空間,直到pg_dump進程結束才釋放。數組
extinfo = getExtensions(fout, &numExtensions); extinfoindex = buildIndexArray(extinfo, numExtensions, sizeof(ExtensionInfo)); getExtensionMembership(fout, extinfo, numExtensions); nspinfo = getNamespaces(fout, &numNamespaces); nspinfoindex = buildIndexArray(nspinfo, numNamespaces, sizeof(NamespaceInfo)); tblinfo = getTables(fout, &numTables); tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo)); getOwnedSeqs(fout, tblinfo, numTables); funinfo = getFuncs(fout, &numFuncs); funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo)); typinfo = getTypes(fout, &numTypes); typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo)); getProcLangs(fout, &numProcLangs); getAggregates(fout, &numAggregates); oprinfo = getOperators(fout, &numOperators); oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo)); getAccessMethods(fout, &numAccessMethods); getOpclasses(fout, &numOpclasses); getOpfamilies(fout, &numOpfamilies); getTSParsers(fout, &numTSParsers); getTSTemplates(fout, &numTSTemplates); getTSDictionaries(fout, &numTSDicts); getTSConfigurations(fout, &numTSConfigs); getForeignDataWrappers(fout, &numForeignDataWrappers); getForeignServers(fout, &numForeignServers); getDefaultACLs(fout, &numDefaultACLs); collinfo = getCollations(fout, &numCollations); collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo)); getConversions(fout, &numConversions); getCasts(fout, &numCasts); getTransforms(fout, &numTransforms); inhinfo = getInherits(fout, &numInherits); getEventTriggers(fout, &numEventTriggers); processExtensionTables(fout, extinfo, numExtensions); flagInhTables(tblinfo, numTables, inhinfo, numInherits); getTableAttrs(fout, tblinfo, numTables); flagInhAttrs(fout->dopt, tblinfo, numTables); getIndexes(fout, tblinfo, numTables); getExtendedStatistics(fout); getConstraints(fout, tblinfo, numTables); getTriggers(fout, tblinfo, numTables); getRules(fout, &numRules); getPolicies(fout, tblinfo, numTables); getPublications(fout); getPublicationTables(fout, tblinfo, numTables); getSubscriptions(fout);
對於每一個getXXXs函數都將執行下面流程,以getTables爲例: 1)根據服務器版本號查詢系統表,讀出對象的元數據信息 2)malloc內存空間並將查詢結果存放到對象的數據結構中,TableInfo 3)對於每條元數據信息,調用selectDumpableTable標記須要導出的表,若是-t指定導出表,遍歷該列表,獲得對應表並標記:DUMP_COMPONENT_ALL;-T指定刪除表,標記tbinfo->dobj.dump = DUMP_COMPONENT_NONE 4)dumpIdMap[dobj->dumpId] = dobj;將導出表的元數據存放到dumpIdMap數組中 5)在導出表上執行LOCK TABLE %s IN ACCESS SHARE MODE 6)將全部元數據信息保存後,執行SET statement_timeout = 0保證語句不超時,可以一直執行下去
九、調用getTableData函數,獲取表對應的數據。實際上,並非表真正數據,而是爲表數據創建一個「導出對象」,未來導出時,依據導出對象獲取真是的數據再導出。雖然先把導出對象放到AH->toc鏈表上,真正導出時導出數據,不會佔用大量內存空間,可是針對這些元數據,當表特別多的時候,因爲不到進程退出不釋放內存,佔用內存仍是很是可觀的。
該函數調用makeTableDataInfo:
1)view、外部表、分區表字表(從父表導出)和unlogged permanent table不用導出
2)判斷該表是否制定導出時被排除
3)malloc一個TableDataInfo,保存表信息服務器
typedef struct _tableDataInfo { DumpableObject dobj; TableInfo *tdtable; /* link to table to dump */ bool oids; /* include OIDs in data? */ char *filtercond; /* WHERE condition to limit rows dumped */ } TableDataInfo;
4)tdinfo->dobj.catId.tableoid、tdinfo->dobj.catId.oid、tdinfo->dobj.name、tdinfo->dobj.namespace 信息,並將dobj保存到dumpIdMap數組
十、若是須要導出大對蝦,調用getBlobs,同上也是保存到數組,並無真正導出數據
十一、調用getDependencies從新整理每一個對象的依賴關係。
十二、getDumpableObjects從dumpIdMap數組中獲取dump對象
1三、sortDumpableObjectsByTypeName、sortDataAndIndexObjectsBySize(若是是並行dump,須要按表大小排序)、sortDumpableObjects把全部對象從新排列:不一樣類型對象導出優先級依賴於dbObjectTypePriority數組;相同類型按名稱排序session
static const 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_STATSEXT */ 30, /* DO_RULE */ 31, /* DO_TRIGGER */ 27, /* DO_CONSTRAINT */ 32, /* 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 */ 38, /* DO_REFRESH_MATVIEW */ 34, /* DO_POLICY */ 35, /* DO_PUBLICATION */ 36, /* DO_PUBLICATION_REL */ 37 /* DO_SUBSCRIPTION */ };
1四、dumpEncoding、dumpStdStrings、dumpSearchPath導出編碼信息,使用雙向鏈表TOCEntry保存導出對象。例如:數據結構
newToc->defn:"SET client_encoding='UTF8';\n" SET standard_conforming_string='on'; SELECT pg_catalog.set_config('search_path','',false);\n
1五、dumpDatabase導出本連接對應的目的數據庫信息,一樣是newToc,newToc->defn:CREATE DATABASE yzs WITH TEMPLATE=template0 ENCODING='UTF8' LC_COLLATE='zh_CN.UTF-8' LC_CTYPE='zh_CN.UTF-8'
1六、遍歷全部對象,對於每一個對象調用dumpDumpableObject,本函數用一堆諸如dumpNamespace、dumpExtension等,將其插入循環鏈表。app
for (i = 0; i < numObjs; i++) dumpDumpableObject(fout, dobjs[i]);
--------------------------以上全部導出,不真正導出數據----------------------------
1七、遍歷鏈表標記哪些對象Toc entry須要導出:ProcessArchiveRestoreOptions
1八、若是導出格式時plain,則調用RestoreArchive,輸出到文件顯示的是SQL語句,再也不是不可識別的二進制文件
1九、關閉句柄釋放資源CloseArchive,根據函數指針調用不一樣文件類型的_CloseArchiveide
-F, --format=c|d|t|p output file format (custom, directory, tar,plain text (default))
目前,pg_dump支持4種導出格式:
custum(pg_backup_custum.c):導出二進制格式的文件。包括文件頭和文件體。文件體是一個鏈表,保存每一個備份對象,每一個可備份對象都有一套統一的結構表示,支持壓縮
plain(pg_backup_null.c):把SQL腳本內容輸出到標準輸出,默認方式
file(pg_backup_file.c):導出包括備份一個主文件和一些輔助文件,主文件方式相似於custom文件格式,輔助文件是數據文件,每一個輔助文件對應備份對象中的一個表,須要和-f一塊兒使用
tar(pg_backup_tar.c):文件備份基本相似「file」方式,但最後備份的全部文件都要歸檔到一個tar文件。文件最大大小爲8GB(受限於tar file format)
PostgreSQL經過函數指針來實現這四種導出格式。在pg_backup_archive.h文件中有諸以下面的大量函數指針:函數
typedef void (*ClosePtrType) (ArchiveHandle *AH); typedef void (*ReopenPtrType) (ArchiveHandle *AH); typedef void (*ArchiveEntryPtrType) (ArchiveHandle *AH, TocEntry *te);
這些函數指針,在下面文件裏分別初始化:
pg_backup_custum.c->InitArchiveFmt_Custom(ArchiveHandle *AH) pg_backup_null.c->InitArchiveFmt_Null(ArchiveHandle *AH) pg_backup_file.c->InitArchiveFmt_Directory(ArchiveHandle *AH) pg_backup_tar->InitArchiveFmt_Tar(ArchiveHandle *AH)
在數據結構ArchiveHandle中使用了大量函數指針,是的在初始化不一樣導出文件格式的Archive結構時,能爲處理函數賦值爲各自不一樣的處理函數。這樣在pg_dump.c中只須要根據用戶指定的文件格式的參數,就能夠調用相應的處理函數。見第一部分的第3步。
概況的說,pg_dump導出的內容能夠分爲數據庫對象的定義和數據。數據庫對象的定義導出時經過查詢系統表把對應元數據信息讀取出來後,把該對象的各種信息置於一個鏈表上包括其依賴對象的oid。而具體的數據,也就是每一個數據包的數據也被抽象爲一個數據庫對象,保存在此鏈表中。
經過調節導出順序把數據庫對象的定義導出而後導出數據,置於經過鏈表中對應數據對象節點的信息,執行相應的SQL語句,從表中讀出數據而後導出寫出去。因此,在內存中只是鏈表上對象的定義,數據是邊讀邊寫出的,可使用流式讀出。
1)以目錄格式導出,須要和-f一塊兒使用。toc.dat保存全部可導出對象的信息(表定義等),其餘文件是數據,以表的oid爲命名,test是目錄。
[postgres@localhost ~]$ pg_dump --format=d yzs -f test [postgres@localhost ~]$ cd test [postgres@localhost test]$ ll total 8 -rw-rw-r--. 1 postgres postgres 31 Mar 23 06:07 3010.dat.gz -rw-rw-r--. 1 postgres postgres 2124 Mar 23 06:07 toc.dat
2)導出SQL語句到test.sql中
[postgres@localhost ~]$ pg_dump --format=p yzs -f test.sql
3)以二進制格式輸出
[postgres@localhost ~]$ pg_dump --format=c -f test yzs
4)以tar格式輸出。與d格式不一樣在於多了一個restore.sql文件(plain格式文件),並將全部文件打包成一個文件
[postgres@localhost ~]$ pg_dump --format=t -f test yzs [postgres@localhost ~]$ tar -xvf test toc.dat 3010.dat restore.sql
5)僅導出數據庫結構(不指定庫,默認是postgres)
pg_dump -s yzs -f 1.sql
6)導出時導出drop database和create database語句。需注意,導入時若有用戶鏈接這該庫,則drop語句執行失敗
pg_dump -s yzs -C -c -f 1.txt
七、-t指定導出某些表,只導出item開頭的表等對象
pg_dump -t temp* -f 1.txt yzs
八、-n只導出指定的schema,能夠多個-n;-N指定不導出的schema