一、循环调用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