關(guān)鍵的 PostgreSQL 客戶(hù)端包含有價(jià)值的數(shù)據(jù),應(yīng)定期備份 PostgreSQL 數(shù)據(jù)庫(kù)。它的過(guò)程非常簡(jiǎn)單,重要的是要清楚地了解技術(shù)和假設(shè)。
SQL 轉(zhuǎn)儲(chǔ)
這種轉(zhuǎn)儲(chǔ)方法背后的想法是使用 SQL 命令從 DataCenter1 生成一個(gè)文本文件,當(dāng)反饋到 DataCenter2 服務(wù)器時(shí),將重新創(chuàng)建與轉(zhuǎn)儲(chǔ)時(shí)相同狀態(tài)的數(shù)據(jù)庫(kù)。在這種情況下,如果客戶(hù)端無(wú)法訪(fǎng)問(wèn)主服務(wù)器,他們可以訪(fǎng)問(wèn) BCP 服務(wù)器。PostgreSQL 為此提供了實(shí)用程序 pg_dump。該命令的基本用法是: pg_dump dbname >backupoutputfile.db。
如您所見(jiàn),pg_dump 將其結(jié)果寫(xiě)入標(biāo)準(zhǔn)輸出。下面,我們將看到這如何有用。
pg_dump 是一個(gè)常規(guī)的 PostgreSQL 客戶(hù)端應(yīng)用程序。這意味著您可以從任何有權(quán)訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的遠(yuǎn)程主機(jī)執(zhí)行此備份過(guò)程。pg_dump 不以特殊權(quán)限運(yùn)行。特別是,它必須對(duì)您要備份的所有表具有讀訪(fǎng)問(wèn)權(quán)限,因此在實(shí)踐中,您幾乎總是必須以數(shù)據(jù)庫(kù)超級(jí)用戶(hù)身份運(yùn)行它。
pg_dump 創(chuàng)建的轉(zhuǎn)儲(chǔ)在內(nèi)部是一致的,也就是說(shuō),轉(zhuǎn)儲(chǔ)代表 pg_dump 開(kāi)始運(yùn)行時(shí)數(shù)據(jù)庫(kù)的快照。pg_dump 在工作時(shí)不會(huì)阻止對(duì)數(shù)據(jù)庫(kù)的其他操作。(具有排他鎖的例外,例如大多數(shù)形式的 ALTER TABLE。)
重要提示:如果您的數(shù)據(jù)庫(kù)模式依賴(lài)于 OID(例如作為外鍵),您必須指示 pg_dump 也轉(zhuǎn)儲(chǔ) OID。為此,請(qǐng)使用 -o 命令行選項(xiàng)。
SQL 轉(zhuǎn)儲(chǔ)自動(dòng)化
- 首先,創(chuàng)建劇本 pgbackup.yml
- 創(chuàng)建角色 pgbackup,它將從 pgbackup.yml 中調(diào)用
Pgbackup.yml
---
- hosts: database_prim:database_replica
gather_facts: true
vars_files:
- mysecret_vars/{{ environ }}.yml
# This is to Identify if DB is Primary and replicating data to secondary
tasks:
- name: select pg status
command: psql -c "SELECT pg_is_in_recovery();"
register: IsPromoted
changed_when: False
environment:
PGDATABASE: "{{ pg_database }}"
PGUSER : "{{ pg_username }}"
PGPASSWORD : "{{ pg_password }}"
#Get the DB parameter from run time on Client application, Not required if you have parameters
- block:
- name: Get client database settings
shell: "awx-manage print_settings | grep '^DATABASES'"
register: results
changed_when: False
delegate_to: "{{ groups['client’][0] }}"
- name: Ingest client database settings
set_fact:
client_db_settings: "{{ results.stdout | regex_replace('DATABASES\\s+= ', '') }}"
delegate_to: "{{ groups['client'][0] }}"
- include_role:
name: pgbackup
when: "'f' in IsPromoted.stdout"
tags: pgbackup
- pgbackup 角色
---
- name: Determine the timestamp for the backup.
set_fact:
now: '{{ lookup("pipe", "date +%F-%T") }}'
- name: Create a directory for a backup to live.
file:
path: '{{ backup_dir.rstrip("/") }}/{{ now }}/'
mode: 0775
owner: root
state: directory
- name: Create a directory for non-instance specific backups
file:
path: '{{ backup_dir.rstrip("/") }}/common/'
mode: 0775
owner: root
state: directory
# create dump, Here adding runtime param. You can add param whatever ways
- name: Perform a PostgreSQL dump.
shell: "pg_dump --clean --create --host='{{ client_db_settings.default.HOST }}' --port={{ client_db_settings.default.PORT }} --username='{{ tower_db_settings.default.USER }}' --dbname='{{ tower_db_settings.default.NAME }}' > pgbackup.db"
args:
chdir: '{{ backup_dir.rstrip("/") }}/common/'
environment:
PGPASSWORD: "{{ client_db_settings.default.PASSWORD }}"
- name: Copy file with owner and permissions
copy:
src: '{{ backup_dir.rstrip("/") }}/common/pgbackup.db'
dest: '{{ backup_dir.rstrip("/") }}/{{ now }}/'
remote_src: yes
[all:vars]
# database settings
.linux.us.ams1907.com
[client]
linuxclient.us.com
[database_prim]
linuxmas.us.com
[database_replica]
linuxreplica.us.com
mysecret_vars/{{ environ }}.yml
ansible-vault encrypt mysecretvar.yml
存儲(chǔ)此類(lèi)參數(shù):pg_password、pg_username 和 pg_database
恢復(fù)轉(zhuǎn)儲(chǔ)
pg_dump 創(chuàng)建的文本文件旨在由 psql 程序讀取?;謴?fù)轉(zhuǎn)儲(chǔ)的一般命令形式是 psql dbname < infile
在數(shù)據(jù)中心 2 中恢復(fù)
Infile 是您用作 pg_dump 命令的備份輸出文件的文件。該命令不會(huì)創(chuàng)建數(shù)據(jù)庫(kù) dbname,因此您必須在執(zhí)行 psql 之前從 template0 自己創(chuàng)建它(例如,使用 createdb -T template0 dbname)。psql 支持類(lèi)似于 pg_dump 的選項(xiàng),用于指定要連接的數(shù)據(jù)庫(kù)服務(wù)器和要使用的用戶(hù)名。有關(guān)更多信息,請(qǐng)參閱 psql 參考頁(yè)。
在還原 SQL 轉(zhuǎn)儲(chǔ)之前,擁有對(duì)象或被授予轉(zhuǎn)儲(chǔ)數(shù)據(jù)庫(kù)中對(duì)象權(quán)限的所有用戶(hù)必須已經(jīng)存在。如果不這樣做,則還原將無(wú)法重新創(chuàng)建具有原始所有權(quán)和/或權(quán)限的對(duì)象。
無(wú)論哪種方式,您都將擁有一個(gè)僅部分恢復(fù)的數(shù)據(jù)庫(kù)?;蛘撸梢灾付ㄕ麄€(gè)轉(zhuǎn)儲(chǔ)應(yīng)作為單個(gè)事務(wù)恢復(fù),以便完全完成或完全回滾恢復(fù)。這種模式可以通過(guò)將 -1 或 --single-transaction 命令行選項(xiàng)傳遞給 psql 來(lái)指定。使用此模式時(shí),請(qǐng)注意,即使是最小的錯(cuò)誤也可能回滾已運(yùn)行數(shù)小時(shí)的還原。但是,這可能仍然比在部分還原轉(zhuǎn)儲(chǔ)后手動(dòng)清理復(fù)雜數(shù)據(jù)庫(kù)更可取。
數(shù)據(jù)庫(kù)恢復(fù)
- hosts: database_prim[0]
tasks:
- name: Get client database settings
shell: "awx-manage print_settings | grep '^DATABASES'"
register: results
changed_when: False
delegate_to: "{{ groups['client'][0] }}"
- name: Ingest client database settings
set_fact:
tower_db_settings: "{{ results.stdout | regex_replace('DATABASES\\s+= ', '') }}"
delegate_to: "{{ groups['client'][0] }}"
# Create User
- name: PostgreSQL | Create test user if its not there
postgresql_user:
name: "test"
password: "{{ client_db_settings.default.PASSWORD }}"
port: "5432"
state: present
login_user: "postgres"
no_password_changes: no
become: yes
become_user: "postgres"
become_method: su
# Create Database
- name: PostgreSQL | Create test Database if its not there
postgresql_db:
name: "test"
owner: "test"
encoding: "UTF-8"
lc_collate: "en_US.UTF-8"
lc_ctype: "en_US.UTF-8"
port: "5432"
template: "template0"
state: present
login_user: "postgres"
become: yes
become_user: "postgres"
become_method: su
- include_role:
name: pgrecover
---
- name: Create a directory for non-instance specific backups
file:
path: '{{ backup_dir.rstrip("/") }}/restore/'
mode: 0775
owner: root
state: directory
- name: Copy file for restore
copy:
src: '{{ backup_dir.rstrip("/") }}/common/client.db'
dest: '{{ backup_dir.rstrip("/") }}/restore/'
remote_src: yes
- name: Perform a PostgreSQL restore
shell: "psql --host='{{ client_db_settings.default.HOST }}' --port={{ client_db_settings.default.PORT }} --username='{{ client_db_settings.default.USER }}' --dbname='test' < ./client.db"
args:
chdir: '{{ backup_dir.rstrip("/") }}/restore/'
environment:
PGPASSWORD: "{{ client_db_settings.default.PASSWORD }}"
使用 pg_dumpall
pg_dump 一次只轉(zhuǎn)儲(chǔ)一個(gè)數(shù)據(jù)庫(kù),它不會(huì)轉(zhuǎn)儲(chǔ)有關(guān)角色或表空間的信息(因?yàn)樗鼈兪羌悍秶亩皇敲總€(gè)數(shù)據(jù)庫(kù)的)。為了支持方便地轉(zhuǎn)儲(chǔ)數(shù)據(jù)庫(kù)集群的全部?jī)?nèi)容,提供了 pg_dumpall 程序。pg_dumpall 備份給定集群中的每個(gè)數(shù)據(jù)庫(kù),還保留集群范圍的數(shù)據(jù),例如角色和表空間定義。該命令的基本用法是:
pg_dumpall > 輸出文件
可以使用 psql 恢復(fù)生成的轉(zhuǎn)儲(chǔ): psql -f infile Postgres。
(實(shí)際上,您可以指定任何現(xiàn)有的數(shù)據(jù)庫(kù)名稱(chēng)作為開(kāi)始,但是如果您要重新加載到一個(gè)空集群中,那么通常應(yīng)該使用 Postgres。)在恢復(fù) pg_dumpall 轉(zhuǎn)儲(chǔ)時(shí)始終需要具有數(shù)據(jù)庫(kù)超級(jí)用戶(hù)訪(fǎng)問(wèn)權(quán)限,因?yàn)槟鞘切枰謴?fù)角色和表空間信息。如果您使用表空間,請(qǐng)注意轉(zhuǎn)儲(chǔ)中的表空間路徑是否適合新安裝。
pg_dumpall 通過(guò)發(fā)出命令來(lái)重新創(chuàng)建角色、表空間和空數(shù)據(jù)庫(kù),然后為每個(gè)數(shù)據(jù)庫(kù)調(diào)用 pg_dump。這意味著雖然每個(gè)數(shù)據(jù)庫(kù)將在內(nèi)部保持一致,但不同數(shù)據(jù)庫(kù)的快照可能不會(huì)完全同步。
通過(guò)在自動(dòng)化腳本中實(shí)現(xiàn)微小的更改,您可以將其更改為 pg_dumpall。