PG數據庫之間的導入導出
本文將介紹如何對PG數據庫進行導入、導出,主要利用的是PG自帶的pg_dump、pg_dumpall、pg_restore、psql等命令,版本是9.4(不同版本的pg_dump \ pg_restore選項可能會有些不同,請注意)。
導出、導入的整體思路是:
- 導出全局對象,如用戶、編碼、權限等,產生文件global-objs.dmp
- 導出每個數據庫中的對象、結構,如建庫語句、用戶、權限、編碼、表結構、自定義類型等,產生 [庫名]-objs.dmp文件,如dxm-objs.dmp
- 導出每個數據庫中的數據,這裏分兩種來考慮,一個是某庫中所有的數據(所有的表),生成單個文件dxm.dmp;一個是針對某庫中每個表分別進行導出備份,每個表一個文件,以[庫名]-[表名].dmp命名,如dxm-all_types.dmp
- 在目標實例上建立全局對象,即導入global-objs.dmp
- 導入對象,即dxm-objs.dmp文件中的內容
- 導入數據,根據導出的不同,分為一次導入dxm.dmp,和分別導入每個表的文件,如dxm-all_types.dmp
數據的導出這裏主要采用pg_dump工具,可以導出為SQL文件、目錄方式(“-Fd”)和自定義格式(“-Fc”)等。其中SQL文件比較適合較小的實例數據量較小的情況,目錄方式因為可以在導入、導出都用並發的方式,因此可以用於較大實例;自定義格式可以在導入的時候用上並發。
導出過程
可以采用以下步驟完成:
- 導出公共對象,比如用戶、權限、編碼等
- 導出某個庫上的對象,比如表、type等
- 導出某個庫上的數據,即各個表的數據等
之後恢複按同樣的步驟恢複就可以了。
第一步,導出所有公共對象,包括編碼用戶、權限等
將公共部分輸出到文件
- [dxm@rdsdba ~]$ /pkg/pgsql/bin/pg_dumpall -h 192.168.xx.xx -g -p 5432 -f gloable.dmp
這裏會將所有的結構、對象、編碼等必要信息導出,用於在新庫上執行。
需要注意一點的就是,進行導出的用戶必須有相應的權限(如上麵例子中默認用的的所在的操作係統用戶,即dxm,也是創建這個實例時的用戶,擁有最高權限。),沒有權限會報以下的日誌:
- [dxm@rdsdba ~]$ /pkg/pgsql/bin/pg_dumpall -h 192.168.xx.xx -p 5432 -U pgtmp
- ……
- pg_dumpall: query failed: ERROR: permission denied for relation pg_authid
- pg_dumpall: query was: SELECT oid, rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolconnlimit, rolpassword, rolvaliduntil, rolreplication, pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment, rolname = current_user AS is_current_user FROM pg_authid ORDER BY 2
第二步,導出庫上的結構和對象
這裏建議是將結構、對象與數據的導入、導出分開進行,會邏輯更清晰,也更好定位問題。
導出某個庫上的結構:
- [dxm@rdsdba ~]$ [backcolor=#ffff00][b]/pkg/pgsql/bin/pg_dump -s -C -v -fdxm-objs.dmp -ddxm -h 192.168.xx.xx -Udxm -p 5432[/b][/backcolor]
- Password:
- pg_dump: reading schemas
- ……
這裏因為帶了"-v"選項,所以會打印較多的信息,從中也能看出讀出了哪些信息。選項有:
- “-s”選項,可以將庫中所有的對象導出,而不導出數據
- “-x”選項,會去除GRANT/INVOKE語句
- 更多選項,請參考"pg_dump --help"
具體看看導出了什麼內容:
- [dxm@rdsdba ~]$ cat dxm-objs.dmp
- ……
- CREATE DATABASE "dxm" WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'zh_CN.UTF-8' LC_CTYPE = 'zh_CN.UTF-8';
- ALTER DATABASE "dxm" OWNER TO "dxm";
- \connect "dxm"
- ……
- CREATE TABLE single_types (
- id integer,
- name text,
- descrps character varying(800),
- md5 bytea
- );
- ……
由上麵的內容可以看出來,隻包含了所有的對象,而沒有數據,並且包含了創建數據庫的語句。有了這些對象後,再進行數據導入即可。
第三步,導出數據
導出的數據支持四種格式:SQL文件、自定義、目錄、壓縮格式。
- SQL文件
隻能通過psql來進行恢複,將SQL文件中的SQL語句進行重做,速度較慢,但較為簡單,出了問題修改SQL文件即可。但數據量大了之後,單個SQL文件就可以達到很大的規模,將很難處理。
- 自定義的格式,
會對數據進行一定的壓縮,且可以利pg_restore進行並發導入。但輸出的同樣是單個文件,對於數據量過大,同樣不太好處理。對於中等大小的實例比較合適,與SQL文件的大小簡單對比如下(all_types.dmp是SQL文件):
- -rw-rw-r-- 1 dxm dxm 111736 Jun 2 18:43 all_types.cs
- -rw-rw-r-- 1 dxm dxm 1218139 Jun 2 18:04 all_types.dmp
- 目錄的方式
目錄的方式目前比較適合較大的實例,原因如下:
- 可以使用pg_dump的並發導出
- 可以使用pg_restore的並發導入
- 每個表一個文件,不至於單個文件過大(如SQL文件的方式)
- 有數據壓縮
隻導出數據部分,不包括結構部分,是選項。
目錄方式和自定義格式
“-Fc”選項,會采用自定義的格式,會占用較小的空間 ,空間大小如下所示:
- [dxm@rdsdba ~]$ /pkg/pgsql/bin/pg_dump -a -v -f dxm.cs -Fc -d dxm -h 192.168.xx.xx -U dxm -p 5432
- -rw-rw-r-- 1 dxm dxm 51176 Jun 2 20:33 single_types.cs
- -rw-rw-r-- 1 dxm dxm 588859 Jun 2 19:50 single_types.dmp
"-Fd"選項,目錄格式。導出的時候,"-j NUM"會多線程的導出數據,提高性能,隻在"-Fd"選項下有效,例子如下:
- [dxm@rdsdba ~]$ [backcolor=#ffff00][b]/pkg/pgsql/bin/pg_dump -a -v -j 6 -f dxm.folder -Fd -d dxm -h 192.168.xx.xxx -U dxm -p 5432[/b][/backcolor]
- [dxm@rdsdba ~]$ ll dxm.folder/
- total 164
- -rw-rw-r-- 1 dxm dxm 50533 Jun 2 20:40 2866.dat.gz
- -rw-rw-r-- 1 dxm dxm 110270 Jun 2 20:40 2867.dat.gz
- -rw-rw-r-- 1 dxm dxm 817 Jun 2 20:40 toc.dat[font=arial] [/font]
恢複數據
恢複數據的時候,根據導出的過程,先恢複對象部分,再對數據進行恢複。
恢複對象
首先恢複全局的信息,包括用戶、編碼等:
- [dxm@rdsdba ~]$ /pkg/pgsql/bin/psql -d postgres -U dxm -h 192.168.xx.xxx -p 5433 -f gloable.dmp
- SET
- SET
- SET
- ……
其次,恢複某庫上的對象。
如果手動在目標實例上建了這個庫,則連到這個庫上即可;如果不是,則pg_dump的選項中應有“-C”,連到postgres即可。以下例子是帶有“-C”選項的,可以看到,導出的文件中包含了庫創建的語句:
- [dxm@rdsdba ~]$[backcolor=#ffff00][b] /pkg/pgsql/bin/psql -d postgres -U dxm -h 192.168.xx.xxx -p 5433 -f dxm-objs.dmp[/b][/backcolor]
- SET
- SET
- SET
- SET
- SET
- SET
- CREATE DATABASE
- ALTER DATABASE
- ……
自定義格式和目錄方式,在恢複的時候都是支持多線程的,這對於大數據量有較好的效果。本次不對性能做太多分析,隻看下功能。
自定義格式:
- [dxm@rdsdba ~]$ [b]/pkg/pgsql/bin/pg_restore -j4 -Fc -h 192.168.xx.xxx -d dxm -U dxm -p 5433 dxm.cs[/b]
目錄方式:
- [dxm@rdsdba ~]$ [b]/pkg/pgsql/bin/pg_restore -Fd -h 192.168.xx.xxx -d dxm -U dxm -p 5433 dxm.folder/[/b]
可以看得出來, pg_restore的使用方式要簡單很多。這裏主要是因為將數據和對象分開來考慮了,所以這一步就隻是數據。如果導出的文件包含數據和對象,通過pg_restore也是可以隻恢複對象,或者數據。
另外,自定義格式和目錄的方式,數據文件並不是可讀的,對於數據的安全也是多了一點點保障。
總結
- pg_dump/pg_restore功能是比較簡單有效的
- pg_dump對於對象類型的支持比較完整,包括複合數據類型、複雜類型等都有很好的支持
- PG還支持其他的方式(比如copy),有興趣的同學可以了解下
附
源庫結構、數據(已有數據的,可略過)
在進行導入、導出之前,需要在源庫上創建一些模擬數據。已經有數據和實例的,可以用已有的,可略過這一步。
創建原始的庫和表:
- create database "dxm" owner "dxm";
- 基本類型的表
- create table if not exists single_types(
- id integer,
- name text,
- descrps varchar(800),
- md5 bytea
- );
- ——創建複合類型
- create type branch_desc as (owner text, name text);
- ——擁有數組、複合類型和其他基本類型的表
- create table if not exists all_types(
- id integer primary key,
- name text not null,
- time timestamp not null,
- price decimal,
- num numeric,
- valid boolean,
- profit_per_quarter decimal[],
- branch branch_desc,
- md5 bytea
- );
插入數據
此處的數據自動生成,暫時不考慮邏輯性,即數據之間的關係(如關聯關係等)。因隻用於導入、導出,類型的多樣比邏輯關係更有作用。
- ——插入10000條記錄
- insert into single_types values(
- generate_series(0, 9999),
- substr('abcdefghijklmnopqrstuvwxyz',1,(random() * 26) ::integer), substr('abcdefghijklmnopqrstuvwxyz',1,(random() * 26) ::integer),
- E'\\xDEADBEAFAE346812734989'
- );
- ——插入10000條記錄
- insert into all_types values(
- generate_series(0, 9999),
- substr('abcdefghijklmnopqrstuvwxyz',1,(random() * 26) ::integer),
- generate_series(now(), now() + '1 week', '1 day')::timestamp,
- (random() * 100.)::numeric(10,2),
- (random() * 100.)::numeric(10,0),
- true,
- '{100,100,100,100}',
- '("dxm", "hangzhou")',
- E'\\xCA9F87A98270197FA9FA'
- );
注:原創,從https://bbs.aliyun.com/read/247030.html?spm=5176.bbsl264.0.0.QBfiR2 搬過來。
最後更新:2017-04-01 13:44:33