參考
http://www.postgres.cn/docs/11/app-pg-dumpall.html
http://www.postgres.cn/docs/11/continuous-archiving.html
http://www.postgres.cn/docs/11/recovery-target-settings.html
http://www.postgres.cn/docs/11/runtime-config-wal.html
http://m.blog.chinaunix.net/uid-20665047-id-5817656.html
http://m.blog.chinaunix.net/uid-20665047-id-5817656.html
http://www.postgres.cn/docs/11/continuous-archiving.html#BACKUP-ARCHIVING-WAL
https://blog.csdn.net/yaoqiancuo3276/article/details/80826073
http://www.postgres.cn/docs/11/runtime-config-replication.html
http://www.postgres.cn/docs/11/warm-standby.html#STREAMING-REPLICATION
https://lihaoquan.me/2018/9/29/postgresql-master-slave-ha.html
全量備份
我們要做實時恢復,就需要對數據庫做增量備份,也就是記錄每次數據庫的操作。恢復的時候,就按照記錄,一條條的把數據還原到正確的地方。但是不管怎么樣,都需要有一個基准,也就是從一個初始狀態開始,按照操作記錄,一條條的恢復。
pg_basebackup
pg_basebackup的作用相當於是把數據庫目錄下的相關數據文件拷貝到一個地方。
只能用這個做全量備份或是自己拷貝所有的數據庫文件,不可以使用pg_dump、pg_dumpall或者navicat的備份工具備份。因為pg_dump等只是把數據庫的表備份出來。postgresql的還原需要數據庫目錄中的一些信息。這也是與mysql不一樣的地方。
mysql是在當前數據的基礎上,一條條的執行binlog中的命令。而postgresql是在數據庫文件記錄的當前狀態下,向前同步到對應的狀態。比如同步了第幾條wal日志信息,還有哪些信息沒同步,需要同步到第幾個。如果僅僅是把數據庫的表導出來,這個無法做還原,因為數據庫當前狀態一直是最新的狀態,就算把數據改回原來的數據,對於數據庫來說,只不過是更新了新的數據,並不認為是回退到了原來的某個時間點。
pg_basebackup -D /home/postgres/basebackup/
把數據全備份到指定目錄
pg_dump
pg_dump dbname > dbback1
把數據庫名字是dbname的數據備份到dbback1中,上面的語句並沒有指定用戶名和密碼,是因為在postgres自己的用戶下,默認配置是peer訪問權限,也就是在自己用戶下,不需要輸入密碼。
psql db_payserver < dbback1
把原來備份的數據還原。
db_dumpall
db_dumpall備份的數據更多。這個是把整個數據庫備份。每個單獨的數據庫調用的是db_dump。但是它還額外備份了一些其他信息,其中包括
所有數據庫公用的全局對象(pg_dump不保存這些對象),數據庫角色和表空間都會被轉儲。包括適數據庫用戶和組、表空間以及適合所有數據庫的訪問權限等屬性。
pg_dumpall需要多次連接到PostgreSQL服務器(每個數據庫一次)。如果你使用口令認證,可能每次都會要求口令。這種情況下使用一個~/.pgpass
會比較方便。
pg_dumpall > dball
psql -f dball
打開歸檔
與mysql的binlog類似,postgresql也會保留對數據庫的操作日志,這也是時間點恢復的基礎。同樣需要我們配置相關參數打開。
修改配置
vim /etc/postgresql/11/main/postgresql.conf
wal_level = logical # minimal, replica, or logical # (change requires restart) archive_mode = on # enables archiving; off, on, or always # (change requires restart) archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' # command to use to archive a logfile segment # placeholders: %p = path of file to archive # %f = file name only # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f'
# e.g. 'copy "%p" d:\\pg_xlog_archive\\%f'
配置解釋
wal_level-設置wal log需要記錄哪些信息,minimal記錄的信息不全,不能恢復數據。所以信息需要是replica或是更高的logical。這個等級就是記錄的信息越來越多。
archive_mode-是否打開歸檔
archive_command-這個是當postgresql完成一個歸檔的時候,運行的命令。postgresql與mysql一樣會記錄每一次數據庫操作,放到一個文件中。這個文件是有大小限制的,默認16m的時候就會換一個文檔。當發生這個操作的時候,就會運行archive_command指定的命令。我們可以把當前的文檔拷貝到一個地方備份起來。test的目的是不要覆蓋已有的文件
wal_level是設置wal日志的模式,postgresql不管有沒有設置,都會有wal日志。
postgresql產生wal日志后,會不斷的刪除原來的wal文檔,為了可以恢復到以前更老的時間點,需要每次postgresql完成一個wal日志文件創建下一個文件的時候,把當前的文件拷貝到一個地方保存起來。歸檔的作用就是postgresql給我們提供的一個借口,可以自動的完成這個操作。
注意事項
windows下創建的目錄,用來拷貝保存wal日志。權限需要增加network service用戶組,不然會報錯沒有權限,無法拷貝數據。
重啟服務或是系統
//windows 在Computer Management->Services選擇postgres對應的服務項,右鍵,選擇重啟 //Debian service postgresql restart
我們可以調用pg_switch_wal
命令來刷新強制產生一次歸檔,看看數據是否拷貝到我們命令設置的地方。
數據還原測試
通過pg_basebackup全量本分數據庫
這就相當於做了一個還原點,從現在這個點往后的數據都可以還原
確定打開了wal日志,並設定為replica或logical
確定打開了歸檔
修改數據
第一條數據改為111
第二條數據改為222
第三條數據改為333
查看當前wal日志
SELECT pg_walfile_name(pg_current_wal_lsn())
查看當前wal詳細信息
/usr/lib/postgresql/11/bin/pg_controldata /var/lib/postgresql/11/main
手動歸檔當前wal日志
select pg_switch_wal();
手動把當前的wal刷新一下,切換到另一個新的日志。這樣就可以分析當前的日志了。因為分析正在使用的wal日志有可能會報錯。
運行這個命令或是數據庫在重啟(也就是關閉的時候)或是在系統重啟(也就是數據庫關閉的時候),都會切換日志,運行歸檔命令。
這個也可以不做,因為恢復數據的時候需要停止數據庫,這是也會歸檔wal日志。
停止數據庫
//Windows 在Computer Management->Services中選擇postgresql對應的服務,右鍵選擇stop //Debian service postgresql stop
把數據庫的data目錄拷貝到一個地方,防止恢復失敗的時候導致更多數據丟失
C:\Program Files\PostgreSQL\11\data
/var/lib/postgresql/11/main
上面是windows和linux下默認安裝的data目錄
清空原來的data目錄下的數據
把上面pg_basebackup備份的數據拷貝到data目錄
就相當於從備份那個點開始還原
分析日志
pg_waldump是用來分析wal日志的命令
pg_waldump 000000040000000000000010
這個命令就是導出日志的詳細信息。這個命令有可能不在系統的環境中,直接執行會報找不到命令的錯誤,可以通過find找到對應的位置。
postgresql的wal日志有一個很大的問題,就是不知道執行的是什么sql語句。這個與mysql的binlog比起來就麻煩了很多。雖然有一些方法可以導出來,但是太麻煩了。希望postgresql以后可以提供直接在日志中顯示sql語句的功能。
上面就是wal日志的詳細信息,我們可以看到COMMIT信息,還有對應的日期。COMMIT信息上面描述了這次操作的類型,比如HOT_UPDATE,就是運行了update命令,更新了數據。
我們看到中間有running xid 1205; online等信息,xid 1205就是這次運行的事務id。也就是我們修改數據庫,默認數據庫也會開啟事務,與我們自己寫的事務一樣,為了保證這次修改要么成功,要么沒修改,不存在中間狀態。
我們還原的時候可以根據這個事務id還原,就可以保證精確度。
上面修改了三次,我們看到這里有三個事務id,1205、1206、1207。所以如果還原到第二條修改,那就是1206.
拷貝wal日志到data目錄下的pg_wal
拷貝recovery.conf.sample到data目錄下,並且修改名字為recovery.conf
這里面有注釋,可以根據注釋修改,我這里只打開了兩個
restore_command = '' recovery_target_xid = '1206'
第一個是必須要開的,就是把原來的歸檔,wal日志,拷貝到pg_wal目錄,如果提前自己拷貝進來,直接是空就好了。
第二個是按照xid的模式還原到1206個xid
啟動數據庫
我們看到數據還原到第二條修改,第三條修改還是原來的值
//Windows 在Computer Management->Services選擇postgresql服務,右鍵,選擇start //Debian service postgresql start
主從異步流復制
注意事項
- 通過pg_basebackup備份過來的文件權限太多,需要設置成只能postgres自己才能訪問操作,過多的權限會導致數據庫無法啟動
- 從widows備份過來的文件和linux下的編碼格式不匹配,無法正常啟動,會報如下錯誤
psql: FATAL: database locale is incompatible with operating system
DETAIL: The database was initialized with LC_COLLATE "Chinese (Simplified)_People's Republic of China.936", which is not recognized by setlocale().
HINT: Recreate the database with another locale or install the missing locale.
- 如果不使用主服務器的備份,則無法啟動主從
最終測試下來失敗,如果有知道如何主從復制,主服務器是windows,從服務器是linux,請告知。