sql >> データベース >  >> RDS >> PostgreSQL

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

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

    データベースを停止してください!

    (注:ファイルシステムからデータディレクトリを削除した場合は、データベースを停止しないでください。次のアドバイスは、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 。したがって、古いバージョンのUPDATE d行はまだ存在しているが、アクセスできない可能性があります。

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

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

    回復

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

    私はこれについてPgメーリングリストに投稿しました。また、TOASTは回復しませんが、pg_dirtyreadのdepeszの投稿にリンクされています。 データを編集したので、有用性は限られています。運が良ければうまくいくかもしれません。試してみてください。

    参照:GitHubのpg_dirtyread。

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

    PostgreSQL行ストレージの基礎

    も参照してください。

    予防

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

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




    1. goinsqlを使用して動的クエリを実行します

    2. より良い動的SQLのために避けるべき10のSP_EXECUTESQLの落とし穴

    3. パラメータスニッフィング入門書

    4. PostgreSQLで月名を月番号に変換する