Postgresql

如何驗證 PostgreSQL 基礎 + WAL 備份已正確恢復

  • November 1, 2015

同事們試圖從 9.1 版的熱備用備份中提取 PostgreSQL 數據庫副本,但這並不可靠——我們每天都會執行它,但通常在對副本執行查詢時會出現各種錯誤。

可悲的是,我無法在網路上找到一個明確的答案,並且 PostgreSQL IRC 頻道中的一個好心人讓我直截了當 - 不支持從備用伺服器中進行這樣的備份-該版本中的盒子。

因此,為了其他可能遇到相同問題並嘗試使用Google搜尋的人的利益,我將在下面的答案中寫下我們的筆記。

答案將包含兩個部分 - 首先,恢復後在日誌中可以看到的內容,其次是一些不可接受的範例。第一部分應該是相當確定的,而第二部分基本上是隨機分類的發生在我們身上的任何事情,表明我們遇到了問題。

可接受的日誌輸出

在開始時:

2015-07-23 06:51:24 UTC LOG: database system was interrupted; last known up at 2015-07-23 02:10:42 UTC

重要的是要看到恢復的 PostgreSQL 知道它最後一次啟動的時間。我認為之所以如此,是因為這意味著它是從檢查點開始的。

xlog min recovery request … 已超過目前點

剛開始時,可能會發生其中一些:

2015-07-23 06:51:30 UTC WARNING:  xlog min recovery request 1027/B0A28D98 is past current point 1027/2BE36DA8
2015-07-23 06:51:30 UTC CONTEXT:  writing block 0 of relation base/117264/9551898_vm
      xlog redo insert: rel 1663/117264/8310261; tid 68622/40

但根據http://www.postgresql.org/message-id/CAB7nPqTd43hqpuC+M8fo+xkqHv1WtFe_16NUttu1pHcBtZhZmw@mail.gmail.com是無害的

FATAL:數據庫系統正在啟動

任何數量的這些都可能發生:

2015-07-23 06:51:24 UTC FATAL:  the database system is starting up

這實際上應該是無害的,因為在我們的例子中,它們是SELECT 1腳本執行以檢查 PostgreSQL 是否準備就緒的自動 ping 類查詢的結果。

意外的pageaddr …在日誌文件中…,段…,偏移量…

最後,是這樣的:

2015-07-23 06:52:21 UTC LOG:  restored log file "0000000100001027000000B2" from archive
2015-07-23 06:52:21 UTC LOG:  consistent recovery state reached at 1027/B2F8F2F8
sh: 1: cannot open ../../../wal_backup/0000000100001027000000B3: No such file
2015-07-23 06:52:21 UTC LOG:  unexpected pageaddr 1027/AA000000 in log file 4135, segment 179, offset 0
2015-07-23 06:52:21 UTC LOG:  redo done at 1027/B2F8F2F8
2015-07-23 06:52:21 UTC LOG:  last completed transaction was at log time 2015-07-23 02:17:33.842307+00

但根據http://www.postgresql.org/message-id/CAGrpgQ-BbXUNErrAtToYhRyUef9_GdUQz1T3CXbpTMLTnuKANQ@mail.gmail.com這也是無害的

請注意,在那之後可能會有更多的 WAL 恢復:

2015-07-23 06:52:21 UTC LOG:  restored log file "0000000100001027000000B2" from archive

這僅僅意味著您提供了recovery.conf比嚴格必要的更多的 WAL 文件。

00000002.history:沒有這樣的文件

在 WAL 展開過程的最後,有這樣的:

sh: 1: cannot open ../../../wal_backup/00000002.history: No such file
2015-07-23 06:52:21 UTC LOG:  selected new timeline ID: 2
sh: 1: cannot open ../../../wal_backup/00000001.history: No such file
2015-07-23 06:52:21 UTC LOG:  archive recovery complete

這顯然/希望無關緊要,因為這是恢復的數據庫(複製)開始新生命(時間線)的地方。

不可接受的日誌輸出

在開始時:

2015-07-20 12:38:31 UTC LOG: database system was interrupted while in recovery at log time 2015-07-20 01:41:22 UTC

這很關鍵——這意味著備份過程沒有在正確的時間開始——在pg_start_backup(...)檢查點之後——而不是數據庫正常工作並且處於某個隨機點,這意味著這種恢復更類似於恢復崩潰的數據庫。

pg_toast 中缺少塊…

這表明還原不正確。作為快速修復,我們嘗試了來自http://postgresql.nabble.com/select-table-indicate-missing-chunk-number-0-for-toast-value-96635-in-pg-toast-2619-的配方td5682176.html

mydb=# vacuum analyze mytable; -- trigger the error to see the problem toast
ERROR:  missing chunk number 0 for toast value 13044178 in pg_toast_2619
mydb=# reindex table pg_toast.pg_toast_2619;
REINDEX

這有時可以使表恢復工作狀態,但有時也不會產生這種效果。之後我們又戳了一下,以為我們發現它只是一次性的 pg_statistic :

mydb=# reindex table pg_statistic;
ERROR:  could not create unique index "pg_statistic_relid_att_inh_index"
DETAIL:  Key (starelid, staattnum, stainherit)=(884792, 34, f) is duplicated.
mydb=# delete from pg_statistic;
DELETE 188540
mydb=# reindex table pg_statistic;
REINDEX
mydb=# vacuum analyze mytable;
VACUUM

右兄弟的左連結不匹配

CREATE TABLE "myschema"."mytable" ( ... )
ERROR: right sibling's left-link doesn't match: block 27 links to 21379 instead of expected 21393 in index "pg_depend_reference_index"

我們試圖通過以下方式快速繞過它:

mydb=# set zero_damaged_pages=on;
SET
mydb=# reindex table pg_depend;
REINDEX
mydb=# set zero_damaged_pages=off;
SET

無法讀取文件中的塊…

2015-05-12 13:32:53 UTC ERROR:  could not read block 76408 in file "pg_tblspc/4606764/PG_9.1_201105231/117264/4614269": read only 0 of 8192 bytes

這顯然是一個無賴。我們無法快速解決這個問題:

mydb=# select cl.relfilenode, nsp.nspname as schema_name, cl.relname, cl.relkind from pg_class cl join pg_namespace nsp on cl.relnamespace = nsp.oid where relfilenode = 4614269;
relfilenode | schema_name | relname | relkind
-------------+-------------+---------+---------
    4614269 | myschema    | mytable | r
(1 row)

mydb=# select pg_relation_filepath('myschema.mytable');
              pg_relation_filepath
---------------------------------------------------
pg_tblspc/4606764/PG_9.1_201105231/117264/4614269
(1 row)

% sudo ls -lah /var/lib/postgresql/9.1/main/pg_tblspc/4606764/PG_9.1_201105231/117264/4614269
-rw------- 1 postgres postgres 597M May 11 19:22 /var/lib/postgresql/9.1/main/pg_tblspc/4606764/PG_9.1_201105231/117264/4614269

這是一個很好的指標,表明太多數據正在“失去”。

重複鍵值違反唯一約束“pg_type_typname_nsp_index”

這是恢復被破壞的另一個指標:

CREATE TABLE "myschema"."mytable" ( ... )
ERROR: duplicate key value violates unique constraint "pg_type_typname_nsp_index" DETAIL: Key (typname, typnamespace)=(mytable_mycolumn_seq, 3780903) already exists.

對此的快速破解是移動序列位置:

SELECT setval('mytable_id_seq', (SELECT MAX(id) FROM mytable));

引用自:https://dba.stackexchange.com/questions/119766