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

PostgreSQLでのトランザクション分離

    PostgreSQLには、複数のクライアントが同じデータを同時に更新しようとしたときに何が起こるかを正確に定義できる、確かな実績のある機能が付属しています。その1つは、トランザクションの分離レベルです。

    PostgreSQLでトランザクション分離がどのように機能するかについて詳しくは、以下をお読みください。

    トランザクションと分離レベル

    トランザクションは、RDBMSのデータを変更するための基本的な方法です。最新のRDBMSでは、複数のトランザクションを同時に実行できます。その結果、アプリケーション開発者がトランザクションを他のトランザクションと対話する方法と対話しない方法を指定するためのさまざまなツール(標準、RDBMS固有)が付属しています。

    トランザクション分離レベルと悲観的ロックは、そのような2つのツールです。これらはデータの整合性とパフォーマンスに必要ですが、残念ながら、理解したり使用したりするのは直感的ではありません。

    PostgreSQLでのトランザクションの分離レベルは、次のいずれかになります。

    • コミット済みを読む
    • 繰り返し読み取り
    • シリアル化可能

    すべてのトランザクションでは、作成時に分離レベルがこれらのいずれかに設定されています。デフォルトのレベルは「読み取りコミット」です。

    SQL標準では、Postgresではサポートされていない「コミットされていない読み取り」も定義されていることに注意してください。最も近い、より高いレベルの「読み取りコミット」を使用する必要があります。

    これらのレベルの意味を見てみましょう。

    コミット済みの読み取り

    1つの(未完了の)トランザクションがテーブルに行を挿入し、もう1つの(これも未完了の)トランザクションがテーブルのすべての行を読み取ろうとするとどうなりますか? 2番目のトランザクションが最初のトランザクションによって挿入された行を確認できる場合、その読み取りはダーティ読み取りと呼ばれます。 –最初のトランザクションはロールバックでき、2番目のトランザクションは存在しなかった「ファントム」行を読み取るためです。

    コミットされた読み取り 分離レベルは、ダーティリードが発生しないことを保証します。次に例を示します:

    ご覧のとおり、2番目のトランザクションは最初のトランザクションのまだコミットされていないデータを読み取ることができませんでした。PostgreSQLでは、分離レベルをこのレベルより低くしてダーティ読み取りを許可することはできません。

    繰り返し可能な読み取り

    さらに別の問題は、繰り返し不可能な読み取りの問題です。これらは、トランザクションが行を読み取り、少し後でもう一度読み取るときに発生しますが、別のトランザクションによって行が途中で更新されたため、異なる結果が得られます。読み取りは繰り返し不可になりました 、この例に示すように:

    この問題を修正するには、トランザクションの分離レベルを「repeatableread」に設定します。次にPostgreSQLは、2番目(または任意の)の読み取りでも最初の読み取りと同じ結果が返されるようにします。アップグレードされた分離レベルでの同じシナリオは次のとおりです。

    分離レベルは、BEGINステートメントとともに指定されていることに注意してください。これを接続レベルで(接続パラメーターとして)構成パラメーター(default_transaction_isolation)として指定することもできます。 )そしてSETTRANSACTIONステートメントを使用します。

    シリアル化可能

    次の分離レベルは、更新の喪失の問題に対処します 。次に示すように、1つのトランザクションで実行された更新は「失われる」か、同時に実行される別のトランザクションによって上書きされる可能性があります。

    ここでは、2番目のトランザクションのUPDATEがブロックされます。これは、PostgreSQLが最初のトランザクションが終了するまで、次の更新を防ぐためにロックを設定するためです。ただし、最初のトランザクションの変更は失われます。これは、2番目のトランザクションが行を「上書き」したためです。

    この種の動作が受け入れられない場合は、分離レベルをシリアル化可能にアップグレードできます。

    このレベルでは、2番目のトランザクションのコミットは失敗します。 2番目のトランザクションのアクションは、コミットしようとした時点で無効にされた事実に基づいていました。

    シリアル化は最高レベルの安全性を提供しますが、アプリケーションがそのようなコミットの失敗を検出し、トランザクション全体を再試行する必要があることも意味します。


    1. 更新/削除を無効にし、トリガーがそれらを実行できるようにする方法はありますか?

    2. ステップバイステップpostgres_fdw

    3. PostgreSQLのチェック制約を理解する

    4. SQLiteOpenHelper onCreateメソッドが呼び出されたとき?