59

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

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

何か助けはありますか?

ROLLBACK

と言いNOTICE: there is no transaction in progressます。

4

1 に答える 1

116

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

データベースを止めろ!

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

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

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

PITR / WAL アーカイブをセットアップしておらず、バックアップも持っていない場合は、本当に困ったことになります。

緊急緩和

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

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

一部のデータが生き残った可能性がある方法

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

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

データディレクトリの完全なファイルシステムレベルのコピーを作成したので、本当に必要な場合はデータベースのバックアップを開始できます。データはまだ失われていますが、回復できる可能性があるという希望を自分に与えるためにできることはすべて実行しました。選択肢があれば、安全のためにDBをシャットダウンしたままにするでしょう。

回復

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

私はこれについて Pg メーリング リストに投稿し、Виктор Егоров は pg_dirtyread に関する depesz の投稿にリンクし ましTOAST。運が良ければうまくいくかもしれませんので、試してみてください。

参照: GitHub の pg_dirtyread

このセクションで書いたものは、そのツールによって廃止されたため、削除しました。

PostgreSQL 行ストレージの基礎も参照してください。

防止

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


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

于 2012-09-18T07:50:01.493 に答える