PostgreSQL DELETE FROMが「エラー:不可視のタプルを削除しようとしました」で失敗します


25

エラー

無効なタイムスタンプを含むタプルを削除しようとしています

DELETE FROM comments WHERE date > '1 Jan 9999' OR date < '1 Jan 2000' OR date_found > '1 Jan 9999' OR date_found < '1 Jan 2000';

で終わる

ERROR:  attempted to delete invisible tuple

2009年には、OPで修正されたまったく同じエラーメッセージについて議論するメーリングリストがありますが彼がそれをどのようにしたのか、またはこのエラーにつながったのかについての説明はありません。

Googleでヒットがなく、PostgreSQLの知識が限られているため、私は無力です。

腐敗の原因

OSカーネルがパニックになったときに、おそらくスワップが配置されている/ dev / md1を再構築しているときに、Debian 8で実行しているPostgreSQL 9.5.5サーバー(メモリ制限の上限を除くすべてのデフォルト設定)を実行しました。それ以前は、PostgreSQLは400GBのログファイルでほとんどすべてのディスク領域を使い果たしました。OSは二度と起動しなかったので、ディスクチェックは問題ありませんでした。念のため、LiveCDから起動し、各ブロックデバイスをイメージにバックアップしました。/ dev / md2から/ディレクトリを正常に再構築しました。fsckはクリーンなファイルシステムを示し、PGDATAフォルダーを外部HDDにバックアップしました。

回復を試みるためにしたこと

mdデバイスをフォーマットし、新鮮なpostgresql-9.5とともにOSを再インストールした後、PostgreSQLサーバーを停止し、PGDATAフォルダーをpostgresユーザーに移動してchownし、サーバーを起動しました。

すぐに私が始めてきたようにpg_dumpall、それはで死にました

Error message from server: ERROR:  timestamp out of range

私は自然に問題のタプルを削除しようとしましたが、同じinvisible tupleエラーが何度も何度も発生するだけです。

試したこと

まず、ページの破損が原因でDELETEクエリが失敗したため、次の設定を行いました。

zero_damaged_pages = on
ignore_system_indexes = on
enable_indexscan = off
enable_bitmapscan = off
enable_indexonlyscan = off

今、私は同じクエリを再度実行すると、サーバーが同じページを何度もゼロ設定することに気付きました。

invalid page in block 92800 of relation base/16385/16443; zeroing out page

私は未定義の順序で以下を試しました:

  • pg_resetxlog -D $PGDATA エラーやメッセージなしで仕事をした
  • pkey制約を含むすべてのインデックスを削除しました
  • CREATE TABLE aaa AS (SELECT * FROM comments);リードにSegmentation fault

    heap_deform_tuple (tuple=tuple@entry=0x7f0d1be29b08, tupleDesc=tupleDesc@entry=0x7f0d1a35abe0, values=values@entry=0x7ffd57a5beb0, isnull=isnull@entry=0x7ffd57a65af0 "\001\001") 再現性があり、〜9GBのコアダンプが残ります。

  • SELECT COUNT(*) from comments;VACUUM comments;完了することができますが、他のテーブルでは同じトリックは機能しません。
  • SELECT COUNT(*) from photos;そしてVACUUM photos;今では死ぬERROR: MultiXactId 302740528 has not been created yet -- apparent wraparound-これはすべてのテーブルに出没し、他のエラーはもうポップアップしません。

考え

  • DBは、(多くので打たなっていたが、おそらく複製)を書き込んON CONFLICT DBをやっていたVACUUM私はそれがとのトラブルを引き起こしているということで残っているものであると信じて、カーネルパニックが発生したときnonexistent MultiXactIdsinvisible tuple
  • データは2年以上にわたってクローラーで収集されましたが、一部を失っても大丈夫です
  • 今、バックアップを行います
  • テーブル間にトリガーもトリガーもありませんでした

現在のpg_controldataの出力は次のとおりです。

pg_control version number:            942
Catalog version number:               201510051
Database system identifier:           6330224129664261958
Database cluster state:               in production
pg_control last modified:             Thu 08 Dec 2016 01:06:22 AM EET
Latest checkpoint location:           1562/8F9F8A8
Prior checkpoint location:            1562/8F7F460
Latest checkpoint's REDO location:    1562/8F9F8A8
Latest checkpoint's REDO WAL file:    000000010000156200000008
Latest checkpoint's TimeLineID:       1
Latest checkpoint's PrevTimeLineID:   1
Latest checkpoint's full_page_writes: on
Latest checkpoint's NextXID:          0/40781255
Latest checkpoint's NextOID:          67798231
Latest checkpoint's NextMultiXactId:  1
Latest checkpoint's NextMultiOffset:  0
Latest checkpoint's oldestXID:        615
Latest checkpoint's oldestXID's DB:   1
Latest checkpoint's oldestActiveXID:  0
Latest checkpoint's oldestMultiXid:   1
Latest checkpoint's oldestMulti's DB: 1
Latest checkpoint's oldestCommitTsXid:0
Latest checkpoint's newestCommitTsXid:0
Time of latest checkpoint:            Thu 08 Dec 2016 01:06:22 AM EET
Fake LSN counter for unlogged rels:   0/1
Minimum recovery ending location:     0/0
Min recovery ending loc's timeline:   0
Backup start location:                0/0
Backup end location:                  0/0
End-of-backup record required:        no
wal_level setting:                    minimal
wal_log_hints setting:                off
max_connections setting:              100
max_worker_processes setting:         8
max_prepared_xacts setting:           0
max_locks_per_xact setting:           64
track_commit_timestamp setting:       off
Maximum data alignment:               8
Database block size:                  8192
Blocks per segment of large relation: 131072
WAL block size:                       8192
Bytes per WAL segment:                16777216
Maximum length of identifiers:        64
Maximum columns in an index:          32
Maximum size of a TOAST chunk:        1996
Size of a large-object chunk:         2048
Date/time type storage:               64-bit integers
Float4 argument passing:              by value
Float8 argument passing:              by value
Data page checksum version:           0

更新

  • 2016年12月9日存在しないMultiXactIdsについて読んでいると、クラッシュの時点でデータベースに運用負荷がかかっていなかったことを思い出しましたが、手動VACUUM要求を処理していました。ディスクに残っているスペースが3%しかないことに気付いた後、ウェブサーバーとクローラーをオフラインにしました。/var/log大きなファイルをチェックする必要がありましたが、誤ってPostgreSQLを非難しVACUUM FULL、デバイスに残されたスペースがわずかであるために中止されたことがわかりました。それで、私は普通のVACUUMを始めて、それを残しました。
  • 2016年12月14日)PostgreSQLソースの9.5ブランチをGithubからダウンロードし、heapam.cおよびmultixact.cのブロックをコメント化し、これらのエラーがスローされないことを期待してコンパイルしました。しかし、APTで使用していたものと同じフラグを使用してサーバーを構成する必要があったため、サーバーは起動しませんでした。約47のフラグがあり、それぞれに非自明な名前の依存関係が必要だったため、私はその考えをあきらめました。
  • 2016年12月16日)関連するページをゼロにすることで、無効なタイムスタンプを持つタプルを削除する方法を見つけました。最初に次のオプションを設定しますpsql

    \set FETCH_COUNT 1
    \pset pager off

    それから私はしますSELECT ctid, * FROM comments;。そのようにしてctid、クエリが終了する前に、悪いタプルを吐き出します。その後、そのページをゼロで埋めます。dd if=/dev/zero of=/var/lib/postgresql/9.5/main/base/16385/16443 bs=8K seek=92803 count=1 conv=notruncしかし、この方法でゼロにされた各ページは前のページを壊し、結果としてページ16442に無効なタイムスタンプを持つタプルができます。ここで私が間違っていることはわかりません。

  • 2016年12月16日pg_dump -Fc --table photos vw > photos.bak1.3GB(おそらく800GBのうち)が書き込まれた後、セグメンテーションエラーが発生します。サーバーログは次のとおりです。

    2016-12-16 18:48:05 EET [19337-2] LOG:  server process (PID 29088) was terminated by signal 11: Segmentation fault
    2016-12-16 18:48:05 EET [19337-3] DETAIL:  Failed process was running: COPY public.photos (id, owner_id, width, height, text, date, link, thumb, album_id, time_found, user_id, lat, long) TO stdout;
    2016-12-16 18:48:05 EET [19337-4] LOG:  terminating any other active server processes
    2016-12-16 18:48:05 EET [19342-2] WARNING:  terminating connection because of crash of another server process
    2016-12-16 18:48:05 EET [19342-3] DETAIL:  The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
    2016-12-16 18:48:05 EET [19342-4] HINT:  In a moment you should be able to reconnect to the database and repeat your command.
    2016-12-16 18:48:05 EET [19337-5] LOG:  all server processes terminated; reinitializing
    2016-12-16 18:48:06 EET [29135-1] LOG:  database system was interrupted; last known up at 2016-12-14 22:58:59 EET
    2016-12-16 18:48:07 EET [29135-2] LOG:  database system was not properly shut down; automatic recovery in progress
    2016-12-16 18:48:07 EET [29135-3] LOG:  invalid record length at 1562/A302F878
    2016-12-16 18:48:07 EET [29135-4] LOG:  redo is not required
    2016-12-16 18:48:07 EET [29135-5] LOG:  MultiXact member wraparound protections are now enabled
    2016-12-16 18:48:07 EET [19337-6] LOG:  database system is ready to accept connections
    2016-12-16 18:48:07 EET [29139-1] LOG:  autovacuum launcher started

    ここに短いスタックトレースがあります:

    #0  pglz_decompress (source=source@entry=0x7fbfb6b99b13 "32;00/0ag4d/Jnz\027QI\003Jh3A.jpg", slen=<optimized out>,
        dest=dest@entry=0x7fbf74a0b044 "", rawsize=926905132)
    #1  0x00007fc1bf120c12 in toast_decompress_datum (attr=0x7fbfb6b99b0b)
    #2  0x00007fc1bf423c83 in text_to_cstring (t=0x7fbfb6b99b0b)

    私はそれを回避する方法がわかりません。

  • 2016年12月29日SELECT * FROM tablename LIMIT 10000 OFFSET 0オフセットをインクリメントし、デッドタプルの周りを絞り込むユーティリティを作成しました。タプル以外のローカルマシンでデータを正常に複製しました(唯一のものを願っています)。手動で破損しました。サーバーが再起動する場合も待機することになっています。ただし、RAIDに十分なスペースが残っていなかっslowdiskたため、8TB HDDにテーブルスペースを作成しました。私がしようとするとCREATE DATABASE vwslow WITH TABLESPACE slowdisk、エラーが発生しません:

    2016-12-29 02:34:13 EET [29983-1] LOG:  request to flush past end of generated WAL; request 950412DE/114D59, currpos 1562/A3030C70
    2016-12-29 02:34:13 EET [29983-2] CONTEXT:  writing block 58368001 of relation base/16385/16473
    2016-12-29 02:34:13 EET [29983-3] ERROR:  xlog flush request 950412DE/114D59 is not satisfied --- flushed only to 1562/A3030C70
    2016-12-29 02:34:13 EET [29983-4] CONTEXT:  writing block 58368001 of relation base/16385/16473
    2016-12-29 02:34:13 EET [30005-44212] postgres@vw ERROR:  checkpoint request failed
    2016-12-29 02:34:13 EET [30005-44213] postgres@vw HINT:  Consult recent messages in the server log for details.
    2016-12-29 02:34:13 EET [30005-44214] postgres@vw STATEMENT:  CREATE DATABASE vwslow WITH TABLESPACE slowdisk;

    手動CHECKPOINTでも同じエラーが発生しました。

    サーバーを再起動すると、チェックポイントエラーがなくなり、ツールを実行できます。私の質問に答え、それが機能する場合、コードを公開します。


wiki.postgresql.org/wiki/Corruptionを実行する前にこれを読んで実行してください。少し遅いように見えますが。ここでは、ディスクの問題/ RAIDの再構築が根本的な原因であると強く疑っています。
クレイグリンガー

resetxlogなどを実行する前のデータディレクトリのコピーを保存しましたか?
クレイグリンガー

datadir自体ではありませんが、rawディスクイメージをより安全な場所に移動しました。RAIDを再構築したので、それらは問題ありません。
カイ

1
@CraigRingerはこれについて答えを書きますか?あなたはおそらく、Postgresタグで回答し、この問題に関して何か有益なことを言うことができる数少ないユーザーの1人です。できることはほとんどないようです。
ypercubeᵀᴹ

4
これに関する答えを見つけることはできません。アーウィンはあなたを助けることができるかもしれません。それについては、irc.freenode.net /#postgresqlでDavid FetterまたはAndrewSW / RhodiumToadを探してください。彼らが見つけたものを(dba.se)教えてください。これは、データベースへの完全なアクセスを必要とする有料のコンサルティング業務になると感じています。developer.postgresql.org/~adunstan linkedin.com/in/davidfetter 私はそれらの人たちや彼らの会社のどちらとも提携していません。しかし、それらは私が個人的にそのひっかかりから抜け出すと信じている唯一のものです。
エヴァンキャロル

回答:


2

まあ、私はの回復プロセスを自動化するために管理しているSELECTINSERT INTO範囲をスキップして、サーバがクラッシュした場合待っています、。Nodeで最初にコーディングしました。破損していないデータをからリッピングしcomments、現在も使用しています。

昨日はGolangをしようとすることを決めた、とここに行くコードでレポできました:https://github.com/kaivi/pg_ripperは、それは本当に悪いのタプルを回避しますので、私はすぐにそれを更新するだけではなく、全体を断念します1を含む範囲。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.