一、道理剖析

1、轮回挪用getopt_long剖析命令行参数,将参数生存到static DumpOptions dopt;中
2、判定参数是不是相容,不相容则退出:

    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

3、挪用CreateArchive翻开输出文件,输出流为fout。该函数运用4个文件封装了4种差别dump文件格式,增添新文件能够增添新的导出文件类型各自封装,自力易于保护。

    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);
        }

4、fout是一个主要的全局变量
5、挪用ConnectDatabase衔接数据库
6、挪用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;

7、为兼容低版本,凭据服务器版本号决意一些变量与值
8、挪用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包管语句不超时,可以或许一向实行下去

9、挪用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数组
10、若是需求导出大对虾,挪用getBlobs,同上也是生存到数组,并没有真正导出数据
11、挪用getDependencies从新整顿每一个工具的依靠干系。
12、getDumpableObjects从dumpIdMap数组中获得dump工具
13、sortDumpableObjectsByTypeName、sortDataAndIndexObjectsBySize(若是是并行dump,需求按表巨细排序)、sortDumpableObjects把所有工具从新分列:不同类型工具导出优先级依赖于dbObjectTypePriority数组;雷同范例按称号排序

    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 */
    };

14、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

15、dumpDatabase导出本链接对应的目标数据库信息,一样是newToc,newToc->defn:CREATE DATABASE yzs WITH TEMPLATE=template0 ENCODING='UTF8' LC_COLLATE='zh_CN.UTF-8' LC_CTYPE='zh_CN.UTF-8'
16、遍历所有工具,关于每一个工具挪用dumpDumpableObject,本函数用一堆诸如dumpNamespace、dumpExtension等,将其插入轮回链表。

    for (i = 0; i < numObjs; i++)
        dumpDumpableObject(fout, dobjs[i]);

--------------------------以上所有导出,不真正导出数据----------------------------
17、遍历链表符号哪些工具Toc entry需求导出:ProcessArchiveRestoreOptions
18、若是导出花样时plain,则挪用RestoreArchive,输出到文件显现的是SQL语句,不再是弗成辨认的二进制文件
19、封闭句柄开释资本CloseArchive,凭据函数指针挪用差别文件类型的_CloseArchive

二、差别花样的处置惩罚函数

-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

7、-t指定导出某些表,只导出item开头的表等工具

pg_dump -t temp* -f 1.txt yzs

8、-n只导出指定的schema,能够多个-n;-N指定不导出的schema