間違ったUPDATE
ステートメントをコミットし、一部のデータを失いました。
すでにコミットした後、今すぐロールバックすることは可能ですか?
何か助け?
ROLLBACK
NOTICE: there is no transaction in progress
。
いいえ、コミットを取り消したり、ロールバックしたり、取り消したりすることはできません。
(注:ファイルシステムからデータディレクトリを削除した場合は、データベースを停止しないでください。次のアドバイスは、rm -rf /data/directory
シナリオではなく、DELETE
または類似の偶発的なコミットに適用されます。
このデータが重要である場合、データベースを今すぐ停止し、再起動しないでください。 pg_ctl stop -m immediate
を使用して、シャットダウン時にチェックポイントが実行されないようにします。
トランザクションがコミットされると、トランザクションをロールバックできません。バックアップからデータを復元するか、 ポイントインタイムリカバリ を使用する必要があります。これはセットアップされている必要がありますbefore事故が発生しました。
PITR/WALアーカイブを設定しておらず、バックアップがない場合は、本当に困っています。
データベースが停止したら、データディレクトリ全体(base
、pg_clog
などを含むフォルダ)のファイルシステムレベルを作成する必要があります。コピーすべてを新しい場所。新しい場所にあるコピーには何もしないでください。バックアップがない場合は、データを回復する唯一の希望です。可能であれば、リムーバブルストレージに別のコピーを作成し、そのストレージをコンピューターから取り外します。 pg_xlog
などを含む、データディレクトリの絶対にすべての部分が必要であることを忘れないでください。重要な部分はありません。
コピーの正確な作成方法は、実行しているオペレーティングシステムによって異なります。データディレクトリの場所は、実行しているOSとPostgreSQLのインストール方法によって異なります。
DBをすぐに停止すると、テーブルからデータを回復できる可能性があります。これは、PostgreSQLが マルチバージョン同時実行制御(MVCC) を使用してストレージへの同時アクセスを管理するためです。場合によっては、テーブルに更新する行の新しいバージョンを書き込み、古い行はそのままにして「削除済み」としてマークします。しばらくすると autovaccum が現れ、行に空きスペースとしてマークを付けるため、後のINSERT
またはUPDATE
で上書きできます。したがって、UPDATE
d行の古いバージョンはまだ存在している可能性がありますが、アクセスできません。
さらに、Pgは2つのフェーズで書き込みます。最初のデータは、先行書き込みログ(WAL)に書き込まれます。 WALに書き込まれてディスクにヒットすると、「ヒープ」(メインテーブル)にコピーされ、そこにあった古いデータが上書きされる可能性があります。 WALコンテンツは、bgwriter
および定期的なチェックポイントによってメインヒープにコピーされます。デフォルトでは、5分ごとにチェックポイントが発生します。チェックポイントが発生する前にデータベースを停止し、ハードキル、マシンのプラグを抜く、またはimmediate
モードでpg_ctl
を使用してデータベースを停止した場合、データをキャプチャした可能性がありますチェックポイントが発生する前に、古いデータがヒープに残っている可能性が高くなります。
データディレクトリの完全なファイルシステムレベルのコピーを作成したので、本当に必要な場合はデータベースをバックアップできます。データは失われますが、データを回復できる可能性があることを確認するために、できることを実行しました。選択を考えると、おそらく安全のためにDBをシャットダウンしたままにします。
データ復旧の試みを支援するために、PostgreSQLの内部の専門家を雇う 必要があるかもしれません 。おそらくかなりの時間をかけて、専門家に時間を支払う準備をしてください。
これについてはPgメーリングリストに投稿し、 ВикторЕгоровはdepeszのpg_dirtyread への投稿にリンクしました。 TOAST
edのデータは復元されませんが、ユーティリティは限られています。運がよければうまくいくかもしれません。
参照: pg_dirtyread on GitHub .
このツールで廃止されたため、このセクションで記述した内容は削除しました。
ブログのエントリ を参照してください。PostgreSQLデータベースの破損を防止します 。
半関連の補足説明で、 2フェーズコミット を使用している場合、コミットの準備はできているが完全にはコミットされていないトランザクションに対してROLLBACK PREPARED
を実行できます。これは、すでにコミットされたトランザクションをロールバックするのに最も近いものであり、状況には当てはまりません。