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

クエリをブロックする必要があるpostgresでのロックとトランザクション

    あなたが説明する振る舞いは正常であり、どのトランザクションリレーショナルデータベースでも予想されます。

    PostgreSQLがeditedの値を表示した場合 最初のSELECT そうするのは間違っているでしょう-それは「ダーティリード」と呼ばれ、データベースでは悪いニュースです。

    PostgreSQLはSELECTで待機することが許可されます コミットまたはロールバックするまで、ただしSQL標準では必須ではなく、待機するように指示しておらず、技術的な理由で待機する必要もないため、要求したデータが返されます。すぐに。結局のところ、コミットされるまで、そのupdate ある種のものだけが存在します-それはまだ起こるかもしれないし、起こらないかもしれません。

    PostgreSQLが常にここで待機していると、データベースに対して一度に1つの接続しか実行できないという状況にすぐに遭遇します。パフォーマンスにはあまり良くなく、ほとんどの場合まったく不要です。

    同時のUPDATEを待ちたい場合 (またはDELETE )、SELECT ... FOR SHAREを使用します 。 (ただし、これはINSERTでは機能しないことに注意してください 。

    詳細:

    SELECT FOR UPDATEなし またはFOR SHARE 句は行レベルのロックを取りません。したがって、現在コミットされている行が何であるかを確認し、その行を変更する可能性のある実行中のトランザクションの影響を受けません。概念は、ドキュメントのMVCCセクション で説明されています。 。一般的な考え方は、PostgreSQLはコピーオンライトであり、トランザクションまたはステートメントが開始時に「見る」ことができたもの、つまりPostgreSQLが「スナップショット」と呼ぶものに基づいて正しいコピーを返すことができるバージョン管理を備えているというものです。

    デフォルトのREAD COMMITTED 分離スナップショットはステートメントレベルで取得されるため、SELECT 行、COMMIT 別のトランザクションからの変更、およびSELECT ここでも、1回のトランザクション内でも異なる値が表示されます。 SNAPSHOTを使用できます トランザクションの開始後にコミットされた変更を確認したくない場合は分離、またはSERIALIZABLE 特定の種類のトランザクションの相互依存性に対する保護をさらに強化するための分離。

    ドキュメントのトランザクション分離の章 を参照してください。 。

    SELECTが必要な場合 進行中のトランザクションが選択されている行への変更をコミットまたはロールバックするのを待つには、SELECT ... FOR SHAREを使用する必要があります 。これにより、UPDATEによって取得されたロックがブロックされます またはDELETE ロックを取得したトランザクションがロールバックまたはコミットするまで。

    INSERT ただし、違います。タプルは、コミットするまで他のトランザクションには存在しません。同時INSERTを待つ唯一の方法 sはEXCLUSIVEを取ることです テーブルレベルのロック。これにより、テーブルを読んでいる間、他の誰もテーブルを変更していないことがわかります。通常、これを行う必要があるということは、アプリケーションに設計上の問題があることを意味します。ただし、アプリは気にしないでください コミットされていないinsertがある場合 まだ飛行中です。

    ドキュメントの明示的なロックの章 を参照してください。 。



    1. MySIAMではなくInnoDBを使用する理由

    2. 関数に値の複数のセットまたは配列を渡します

    3. 大きなMySqlテーブルのエクスポート

    4. 名前を知らずにSQLのデフォルトの制約を削除するにはどうすればよいですか?