web-dev-qa-db-ja.com

すでにコミットしたトランザクションをロールバックできますか? (データロス)

間違ったUPDATEステートメントをコミットし、一部のデータを失いました。

すでにコミットした後、今すぐロールバックすることは可能ですか?

何か助け?

ROLLBACK

NOTICE: there is no transaction in progress

46
SSS

いいえ、コミットを取り消したり、ロールバックしたり、取り消したりすることはできません。

データベースを停止します!

(注:ファイルシステムからデータディレクトリを削除した場合は、データベースを停止しないでください。次のアドバイスは、rm -rf /data/directoryシナリオではなく、DELETEまたは類似の偶発的なコミットに適用されます。

このデータが重要である場合、データベースを今すぐ停止し、再起動しないでください。 pg_ctl stop -m immediateを使用して、シャットダウン時にチェックポイントが実行されないようにします。

トランザクションがコミットされると、トランザクションをロールバックできません。バックアップからデータを復元するか、 ポイントインタイムリカバリ を使用する必要があります。これはセットアップされている必要がありますbefore事故が発生しました。

PITR/WALアーカイブを設定しておらず、バックアップがない場合は、本当に困っています。

緊急の緩和

データベースが停止したら、データディレクトリ全体(basepg_clogなどを含むフォルダ)のファイルシステムレベルを作成する必要があります。コピーすべてを新しい場所。新しい場所にあるコピーには何もしないでください。バックアップがない場合は、データを回復する唯一の希望です。可能であれば、リムーバブルストレージに別のコピーを作成し、そのストレージをコンピューターから取り外します。 pg_xlogなどを含む、データディレクトリの絶対にすべての部分が必要であることを忘れないでください。重要な部分はありません。

コピーの正確な作成方法は、実行しているオペレーティングシステムによって異なります。データディレクトリの場所は、実行しているOSとPostgreSQLのインストール方法によって異なります。

いくつかのデータが生き残った方法

DBをすぐに停止すると、テーブルからデータを回復できる可能性があります。これは、PostgreSQLが マルチバージョン同時実行制御(MVCC) を使用してストレージへの同時アクセスを管理するためです。場合によっては、テーブルに更新する行の新しいバージョンを書き込み、古い行はそのままにして「削除済み」としてマークします。しばらくすると autovaccum が現れ、行に空きスペースとしてマークを付けるため、後のINSERTまたはUPDATEで上書きできます。したがって、UPDATEd行の古いバージョンはまだ存在している可能性がありますが、アクセスできません。

さらに、Pgは2つのフェーズで書き込みます。最初のデータは、先行書き込みログ(WAL)に書き込まれます。 WALに書き込まれてディスクにヒットすると、「ヒープ」(メインテーブル)にコピーされ、そこにあった古いデータが上書きされる可能性があります。 WALコンテンツは、bgwriterおよび定期的なチェックポイントによってメインヒープにコピーされます。デフォルトでは、5分ごとにチェックポイントが発生します。チェックポイントが発生する前にデータベースを停止し、ハードキル、マシンのプラグを抜く、またはimmediateモードでpg_ctlを使用してデータベースを停止した場合、データをキャプチャした可能性がありますチェックポイントが発生する前に、古いデータがヒープに残っている可能性が高くなります。

データディレクトリの完全なファイルシステムレベルのコピーを作成したので、本当に必要な場合はデータベースをバックアップできます。データは失われますが、データを回復できる可能性があることを確認するために、できることを実行しました。選択を考えると、おそらく安全のためにDBをシャットダウンしたままにします。

回復

データ復旧の試みを支援するために、PostgreSQLの内部の専門家を雇う 必要があるかもしれません 。おそらくかなりの時間をかけて、専門家に時間を支払う準備をしてください。

これについてはPgメーリングリストに投稿し、 ВикторЕгоровはdepeszのpg_dirtyread への投稿にリンクしました。 TOASTedのデータは復元されませんが、ユーティリティは限られています。運がよければうまくいくかもしれません。

参照: pg_dirtyread on GitHub .

このツールで廃止されたため、このセクションで記述した内容は削除しました。

参照 PostgreSQL行ストレージの基本

防止

ブログのエントリ を参照してください。PostgreSQLデータベースの破損を防止します


半関連の補足説明で、 2フェーズコミット を使用している場合、コミットの準備はできているが完全にはコミットされていないトランザクションに対してROLLBACK PREPAREDを実行できます。これは、すでにコミットされたトランザクションをロールバックするのに最も近いものであり、状況には当てはまりません。

89
Craig Ringer