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

UPDATE実行時のPostgreSQLのデッドロック

    PostgreSQLでは、行は更新されるとロックされます。実際、これが実際に機能する方法は、各タプル(行のバージョン)にxminというシステムフィールドがあることです。 どのトランザクションがそのタプルを(挿入または更新によって)最新にし、xmaxと呼ばれるシステムフィールドを示します。 どのトランザクションがそのタプルを期限切れにしたかを示します(更新または削除によって)。データにアクセスすると、アクティブな「スナップショット」をこれらの値と照合することにより、各タプルをチェックして、トランザクションに表示されているかどうかを判断します。

    UPDATEを実行していて、検索条件に一致するタプルにxminがあり、スナップショットとアクティブなトランザクションのxmaxに表示される場合、そのタプルはブロックされ、そのトランザクションが完了するのを待ちます。タプルを最初に更新したトランザクションがロールバックすると、トランザクションがウェイクアップして行を処理します。最初のトランザクションがコミットされると、トランザクションはウェイクアップし、現在のトランザクション分離レベルに応じてアクションを実行します。

    明らかに、デッドロックは、これが異なる順序で行に発生した結果です。 RAMには、すべての行に対して同時に取得できる行レベルのロックはありませんが、行が同じ順序で更新される場合、循環ロックを使用することはできません。残念ながら、提案されたIN(1, 2) 構文はそれを保証するものではありません。セッションが異なれば、アクティブなコスト要因も異なります。バックグラウンドの「分析」タスクによって、あるプランの生成と別のプランの生成の間でテーブルの統計が変更される場合があります。または、seqscanを使用していて、PostgreSQLの最適化の影響を受けて新しいseqscanが発生する場合があります。すでに進行中の1つに参加し、「ループアラウンド」してディスクI/Oを削減します。

    アプリケーションコードまたはカーソルを使用して、同じ順序で一度に1つずつ更新を行うと、デッドロックではなく、単純なブロックのみが発生します。ただし、一般に、リレーショナルデータベースはシリアル化に失敗する傾向があるため、SQLSTATEに基づいてリレーショナルデータベースを認識し、トランザクション全体を最初から自動的に再試行するフレームワークを介してアクセスするのが最適です。 PostgreSQLでは、シリアル化の失敗は常に40001または40P01のSQLSTATEになります。

    http://www.postgresql.org/docs/current/interactive/mvcc-intro.html




    1. 2つの日付の間の日付を選択するSQLクエリ

    2. Java:PreparedStatementを使用してMySQLに複数の行を挿入します

    3. RedHatにsqlcmdとbcpをインストールする方法

    4. Tanh()がPostgreSQLでどのように機能するか