これは、日々のバックアップを失敗させていた PostgreSQL テーブルのチャンク欠落エラーに関する投稿です。問題を解決したので、この問題に直面している他の誰かの役に立つかもしれないので、使用した方法を説明します。これは、PostgreSQL のチャンク欠落エラーを適切に解決するためのガイドや専門的な指示ではありません。なぜなら、私は専門家ではなく、あまり知識がないまま行ったからです。しかし、最終的にはうまくいきました。
バックアップ中に発生していたエラー:
pg_dump: error: Dumping the contents of table "stylesheet_cache" failed: PQgetResult() failed.
pg_dump: error: Error message from server: ERROR: missing chunk number 0 for toast value 1903804 in pg_toast_22663
pg_dump: error: The command was: COPY public.stylesheet_cache (id, target, digest, content, created_at, updated_at, theme_id, source_map) TO stdout;
したがって、問題は stylesheet_cache テーブルにあり、エラーは「ERROR: missing chunk number 0 for toast value 1903804 in pg_toast_22663」でした。
私は Discourse を Docker で使用しているので、行ったことは次のとおりです。
ssh into the server
cd /path/to/discourse
./launcher rebuild app
su postgres -c "psql discourse"
PostgreSQL に接続したら、問題を解決することを期待してテーブルを REINDEX しようとしました。
discourse=# select reltoastrelid::regclass from pg_class where relname = 'stylesheet_cache';
reltoastrelid
------------------------
pg_toast.pg_toast_18396
(1 row)
REINDEX table stylesheet_cache;
REINDEX table pg_toast.pg_toast_18396;
VACUUM analyze stylesheet_cache;
再度バックアップを試みましたが、まだ失敗したため、破損の特定を続ける必要がありました。
テーブルの合計行数を次のように計算しました。
select count(*) from stylesheet_cache;
2260 行というカウントが得られました。
破損した正確な行を見つけて削除しました。stylesheet_cache はデータベース全体を壊すようなものではないと、何らかの形で仮定しました。前述したように、私は専門家ではないので、これは大きな賭けだったかもしれません。これを実行するとデータベースが破損する可能性があるため、注意してください。
LIMIT と OFFSET クエリを使用して、破損した行を見つけました。
select * from stylesheet_cache order by id limit 100 offset 0;
オフセットとリミットを調整して「Missing chunk…」エラーが発生するまで試行し、その後 LIMIT 1 と、破損した行のオフセットに絞り込みました。私の場合は 5 行が破損していました。
より少ない労力で行を見つけるために sh スクリプトを使用することもできます。私は手動で行いましたが、時間がかかりましたが、これを使用できます。
#!/bin/sh
j=0
while [ $j -lt 2260 ]
do
psql -U postgres -d discourse -c "SELECT * FROM stylesheet_cache LIMIT 1 offset $j" >/dev/null || echo $j
j=$(($j+1))
done
破損した行の ID を次のコマンドで見つけました。
select id from stylesheet_cache order by id limit 1 offset 450;
id
----
11498
したがって、破損した行の ID は 11498 でした。
次のコマンドでその行を削除しました。
delete from stylesheet_cache where id = 11498;
破損した行を削除した後、再度 REINDEX しました。
REINDEX table stylesheet_cache;
REINDEX table pg_toast.pg_toast_40948;
VACUUM analyze stylesheet_cache;
そして再度バックアップを試みたところ、今回はうまくいきました。この PostgreSQL の復旧手順を参考にしました: Postgres error: Missing chunk 0 for toast value in pg_toast · GitHub
免責事項: これは専門家の意見ではありません。同様のチャンク欠落の破損を修正しようとする場合は、注意して進めてください。