日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

PostgreSQL逻辑备份pg_dump使用及其原理解析

發(fā)布時(shí)間:2024/3/13 数据库 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PostgreSQL逻辑备份pg_dump使用及其原理解析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、原理分析

1、循環(huán)調(diào)用getopt_long解析命令行參數(shù),將參數(shù)保存到static DumpOptions dopt;中
2、判斷參數(shù)是否相容,不相容則退出:

options -s/--schema-only and -a/--data-only cannot be used togetheroptions -c/--clean and -a/--data-only cannot be used togetheroptions --inserts/--column-inserts and -o/--oids cannot be used togetheroption --if-exists requires option -c/--clean

3、調(diào)用CreateArchive打開(kāi)輸出文件,輸出流為fout。該函數(shù)使用4個(gè)文件封裝了4種不同dump文件格式,增加新文件可以增加新的導(dǎo)出文件類型各自封裝,獨(dú)立易于維護(hù)。

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是一個(gè)重要的全局變量
5、調(diào)用ConnectDatabase連接數(shù)據(jù)庫(kù)
6、調(diào)用setup_connection,在連接上執(zhí)行一些SQL語(yǔ)句:

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、為兼容低版本,根據(jù)服務(wù)器版本號(hào)決定一些變量取值
8、調(diào)用tblinfo = getSchemaData(fout, &numTables);決定導(dǎo)出哪些數(shù)據(jù)庫(kù)對(duì)象。本函數(shù)又調(diào)用如下函數(shù),值得關(guān)注哦。為了存儲(chǔ)每個(gè)對(duì)象的元數(shù)據(jù),這些函數(shù)會(huì)malloc申請(qǐng)空間,直到pg_dump進(jìn)程結(jié)束才釋放。
?

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

?對(duì)于每個(gè)getXXXs函數(shù)都將執(zhí)行下面流程,以getTables為例:
?? ?1)根據(jù)服務(wù)器版本號(hào)查詢系統(tǒng)表,讀出對(duì)象的元數(shù)據(jù)信息
?? ?2)malloc內(nèi)存空間并將查詢結(jié)果存放到對(duì)象的數(shù)據(jù)結(jié)構(gòu)中,TableInfo
?? ?3)對(duì)于每條元數(shù)據(jù)信息,調(diào)用selectDumpableTable標(biāo)記需要導(dǎo)出的表,如果-t指定導(dǎo)出表,遍歷該列表,得到對(duì)應(yīng)表并標(biāo)記:DUMP_COMPONENT_ALL;-T指定刪除表,標(biāo)記tbinfo->dobj.dump = DUMP_COMPONENT_NONE
?? ?4)dumpIdMap[dobj->dumpId] = dobj;將導(dǎo)出表的元數(shù)據(jù)存放到dumpIdMap數(shù)組中
?? ?5)在導(dǎo)出表上執(zhí)行LOCK TABLE %s IN ACCESS SHARE MODE
?? ?6)將所有元數(shù)據(jù)信息保存后,執(zhí)行SET statement_timeout = 0保證語(yǔ)句不超時(shí),能夠一直執(zhí)行下去

9、調(diào)用getTableData函數(shù),獲取表對(duì)應(yīng)的數(shù)據(jù)。實(shí)際上,并不是表真正數(shù)據(jù),而是為表數(shù)據(jù)建立一個(gè)“導(dǎo)出對(duì)象”,將來(lái)導(dǎo)出時(shí),依據(jù)導(dǎo)出對(duì)象獲取真是的數(shù)據(jù)再導(dǎo)出。雖然先把導(dǎo)出對(duì)象放到AH->toc鏈表上,真正導(dǎo)出時(shí)導(dǎo)出數(shù)據(jù),不會(huì)占用大量?jī)?nèi)存空間,但是針對(duì)這些元數(shù)據(jù),當(dāng)表特別多的時(shí)候,由于不到進(jìn)程退出不釋放內(nèi)存,占用內(nèi)存還是非常可觀的。
?? ?該函數(shù)調(diào)用makeTableDataInfo:
?? ?1)view、外部表、分區(qū)表字表(從父表導(dǎo)出)和unlogged permanent table不用導(dǎo)出?
?? ?2)判斷該表是否制定導(dǎo)出時(shí)被排除
?? ?3)malloc一個(gè)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數(shù)組

10、如果需要導(dǎo)出大對(duì)蝦,調(diào)用getBlobs,同上也是保存到數(shù)組,并沒(méi)有真正導(dǎo)出數(shù)據(jù)
11、調(diào)用getDependencies重新整理每個(gè)對(duì)象的依賴關(guān)系。
12、getDumpableObjects從dumpIdMap數(shù)組中獲取dump對(duì)象
13、sortDumpableObjectsByTypeName、sortDataAndIndexObjectsBySize(如果是并行dump,需要按表大小排序)、sortDumpableObjects把所有對(duì)象重新排列:不同類型對(duì)象導(dǎo)出優(yōu)先級(jí)依賴于dbObjectTypePriority數(shù)組;相同類型按名稱排序
?

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導(dǎo)出編碼信息,使用雙向鏈表TOCEntry保存導(dǎo)出對(duì)象。例如:

newToc->defn:"SET client_encoding='UTF8';\n"SET standard_conforming_string='on';SELECT pg_catalog.set_config('search_path','',false);\n

15、dumpDatabase導(dǎo)出本鏈接對(duì)應(yīng)的目的數(shù)據(jù)庫(kù)信息,同樣是newToc,newToc->defn:CREATE DATABASE yzs WITH TEMPLATE=template0 ENCODING='UTF8' LC_COLLATE='zh_CN.UTF-8' LC_CTYPE='zh_CN.UTF-8'
16、遍歷所有對(duì)象,對(duì)于每個(gè)對(duì)象調(diào)用dumpDumpableObject,本函數(shù)用一堆諸如dumpNamespace、dumpExtension等,將其插入循環(huán)鏈表。

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

--------------------------以上所有導(dǎo)出,不真正導(dǎo)出數(shù)據(jù)----------------------------
17、遍歷鏈表標(biāo)記哪些對(duì)象Toc entry需要導(dǎo)出:ProcessArchiveRestoreOptions
18、如果導(dǎo)出格式時(shí)plain,則調(diào)用RestoreArchive,輸出到文件顯示的是SQL語(yǔ)句,不再是不可識(shí)別的二進(jìn)制文件
19、關(guān)閉句柄釋放資源CloseArchive,根據(jù)函數(shù)指針調(diào)用不同文件類型的_CloseArchive

二、不同格式的處理函數(shù)

-F, --format=c|d|t|p ? output file format (custom, directory, tar,plain text (default))
目前,pg_dump支持4種導(dǎo)出格式:
?? ?custum(pg_backup_custum.c):導(dǎo)出二進(jìn)制格式的文件。包括文件頭和文件體。文件體是一個(gè)鏈表,保存每個(gè)備份對(duì)象,每個(gè)可備份對(duì)象都有一套統(tǒng)一的結(jié)構(gòu)表示,支持壓縮
?? ?plain(pg_backup_null.c):把SQL腳本內(nèi)容輸出到標(biāo)準(zhǔn)輸出,默認(rèn)方式
?? ?file(pg_backup_file.c):導(dǎo)出包括備份一個(gè)主文件和一些輔助文件,主文件方式類似于custom文件格式,輔助文件是數(shù)據(jù)文件,每個(gè)輔助文件對(duì)應(yīng)備份對(duì)象中的一個(gè)表,需要和-f一起使用
?? ?tar(pg_backup_tar.c):文件備份基本類似“file”方式,但最后備份的所有文件都要?dú)w檔到一個(gè)tar文件。文件最大大小為8GB(受限于tar file format)
PostgreSQL通過(guò)函數(shù)指針來(lái)實(shí)現(xiàn)這四種導(dǎo)出格式。在pg_backup_archive.h文件中有諸如下面的大量函數(shù)指針:

typedef void (*ClosePtrType) (ArchiveHandle *AH);typedef void (*ReopenPtrType) (ArchiveHandle *AH);typedef void (*ArchiveEntryPtrType) (ArchiveHandle *AH, TocEntry *te);

這些函數(shù)指針,在下面文件里分別初始化:

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)

在數(shù)據(jù)結(jié)構(gòu)ArchiveHandle中使用了大量函數(shù)指針,是的在初始化不同導(dǎo)出文件格式的Archive結(jié)構(gòu)時(shí),能為處理函數(shù)賦值為各自不同的處理函數(shù)。這樣在pg_dump.c中只需要根據(jù)用戶指定的文件格式的參數(shù),就可以調(diào)用相應(yīng)的處理函數(shù)。見(jiàn)第一部分的第3步。
概況的說(shuō),pg_dump導(dǎo)出的內(nèi)容可以分為數(shù)據(jù)庫(kù)對(duì)象的定義和數(shù)據(jù)。數(shù)據(jù)庫(kù)對(duì)象的定義導(dǎo)出時(shí)通過(guò)查詢系統(tǒng)表把對(duì)應(yīng)元數(shù)據(jù)信息讀取出來(lái)后,把該對(duì)象的各類信息置于一個(gè)鏈表上包括其依賴對(duì)象的oid。而具體的數(shù)據(jù),也就是每個(gè)數(shù)據(jù)包的數(shù)據(jù)也被抽象為一個(gè)數(shù)據(jù)庫(kù)對(duì)象,保存在此鏈表中。通過(guò)調(diào)節(jié)導(dǎo)出順序把數(shù)據(jù)庫(kù)對(duì)象的定義導(dǎo)出然后導(dǎo)出數(shù)據(jù),置于通過(guò)鏈表中對(duì)應(yīng)數(shù)據(jù)對(duì)象節(jié)點(diǎn)的信息,執(zhí)行相應(yīng)的SQL語(yǔ)句,從表中讀出數(shù)據(jù)然后導(dǎo)出寫(xiě)出去。所以,在內(nèi)存中只是鏈表上對(duì)象的定義,數(shù)據(jù)是邊讀邊寫(xiě)出的,可以使用流式讀出。

三、使用方法

1)以目錄格式導(dǎo)出,需要和-f一起使用。toc.dat保存所有可導(dǎo)出對(duì)象的信息(表定義等),其他文件是數(shù)據(jù),以表的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)導(dǎo)出SQL語(yǔ)句到test.sql中

[postgres@localhost ~]$ pg_dump --format=p yzs -f test.sql

3)以二進(jìn)制格式輸出

[postgres@localhost ~]$ pg_dump --format=c -f test yzs

4)以tar格式輸出。與d格式不同在于多了一個(gè)restore.sql文件(plain格式文件),并將所有文件打包成一個(gè)文件

[postgres@localhost ~]$ pg_dump --format=t -f test yzs [postgres@localhost ~]$ tar -xvf test toc.dat 3010.dat restore.sql

5)僅導(dǎo)出數(shù)據(jù)庫(kù)結(jié)構(gòu)(不指定庫(kù),默認(rèn)是postgres)

pg_dump -s yzs -f 1.sql

6)導(dǎo)出時(shí)導(dǎo)出drop database和create database語(yǔ)句。需注意,導(dǎo)入時(shí)如有用戶連接這該庫(kù),則drop語(yǔ)句執(zhí)行失敗

pg_dump -s yzs -C -c -f 1.txt

7、-t指定導(dǎo)出某些表,只導(dǎo)出item開(kāi)頭的表等對(duì)象

pg_dump -t temp* -f 1.txt yzs

8、-n只導(dǎo)出指定的schema,可以多個(gè)-n;-N指定不導(dǎo)出的schema

總結(jié)

以上是生活随笔為你收集整理的PostgreSQL逻辑备份pg_dump使用及其原理解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。