1

こんにちは Slack Overflowvians。

それで、8.3.11を実行しているこのPostgreSQLサーバーに出くわしました(ええ、知っています)、それはロックされた状態でした:

ERROR:  database is not accepting commands to avoid wraparound data loss in database "postgres"
HINT:  Stop the postmaster and use a standalone backend to vacuum that database.

通常、自動バキューム デーモン ( autovacuum=on) がこれを処理しますが、次の 4 つの TOAST (パンのような大きなフィールド値 8 kB スライスの格納を許可する) のため、データベース オブジェクト. しかし、これらの破損したデータベース オブジェクトが原因で、このデータベースの XID がリセットされることはありませんでした。

以下は、admin ユーザーを使用してシングルユーザー モードでサーバーを実行したときの出力のスニペットです。

SELECT oid, relname, age(relfrozenxid) FROM pg_class WHERE relkind = 't' ORDER BY age(relfrozenxid) DESC LIMIT 4;


    ----
     1: oid = "2421459"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421456"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)
    ----
     1: oid = "2421450"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421447"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)
    ----
     1: oid = "2421435"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421432"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)
    ----
     1: oid = "2421426"     (typeid = 26, len = 4, typmod = -1, byval = t)
     2: relname = "pg_toast_2421423"        (typeid = 19, len = 64, typmod = -1, byval = f)
     3: age = "2146484084"  (typeid = 23, len = 4, typmod = -1, byval = t)

vacuum_freeze_min_ageこのサーバーでは age が (VACUUM が成功した後に設定された値) をはるかに上回っていることに注意してください。上記はVACUUM FULL;を実行した後です。他のすべてのテーブルは問題ありません。

SELECT relfilenode FROM pg_class WHERE oid=2421459;

そのため、ディスクを調べたところ (上記の各テーブルに pg_class.relfilenode 値を使用)、トースト テーブルのファイルが見つかりませんでした。

$ find /var/lib/pgsql/data/ -type f -name '2421426' | wc -l  # Bad toast
0

トーストのインデックスでディスクを見たとき

 SELECT relfilenode FROM pg_class WHERE (select reltoastidxid FROM pg_class WHERE oid=2421459)

$ find /var/lib/pgsql/data/ -type f -name '2421459' | wc -l  # Bad toast's index
0

次に、不良トースト レコードが関連付けられているテーブルを見つけようとしました。

SELECT * FROM pg_class WHERE reltoastrelid=2421459;

上記の各テーブルで 0 件の結果が得られました! VACUUMこれらの関係の XID をリセットするコマンド のテーブルはありません。

pg_depend テーブルを確認したところ、これらの TOAST テーブルには参照がないことがわかりました。

SELECT * FROM pg_depend WHERE refobjid IN(2421459,2421450,2421435,2421426)

質問

  1. pg_class テーブルから不適切な TOAST テーブルと TOAST テーブル インデックスを削除できますか (例DELETE FROM pg_class where oid=2421459)
  2. リレーションを削除する必要がある他のテーブルはありますか?
  3. 一時テーブルを作成して、それを TOAST のインデックスの oid にリンクすることはできますか?

上記の #3 の例:

CREATE TABLE adoptedparent (colnameblah char(1));
UPDATE pg_class SET reltoastrelid=2421459 WHERE relname='adoptedparent';  
VACUUM FULL VERBOSE adoptedparent

編集:

select txid_current()は 3094769499 であるため、これらのテーブルはかなり前に破損しています。データを回復する必要はありません。Linux 2.6.18-238.el5 で ext4 ファイル システムを実行しています。関連するlost+found/ディレクトリを確認しましたが、ファイルはありませんでした。

4

1 に答える 1

0

自宅の聴衆のために、この特定のケースでは解決策は pg_class を直接編集することでした。もちろん、サーバーをサポートされているバージョンの Postgres に更新してください!

具体的な回答:

  1. はい、できます。ただし、ほとんどの場合、空のテーブルを作成し、トースト リレーションをそのテーブルにアタッチし、pg_depend エントリを追加して、テーブルを削除する方が適切です。この場合、それらのトースト テーブルに依存する他のオブジェクトが実際には存在しないため、これは意味がありません。

    1. 通常、トースト テーブルには pg_index にインデックスがあり、pg_depend にエントリがあります。これらはしませんでした。

    2. 上記を参照。

于 2015-10-01T03:27:34.107 に答える