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

Atomic UPDATE..PostgresのSELECT

    アーウィンの提案はおそらく最も単純な 正しい動作を取得する方法(SQLSTATEで例外が発生した場合にトランザクションを再試行する限り of 40001)、キューイングアプリケーションは、その性質上、SERIALIZABLEのPostgreSQL実装よりも、キューで順番を変えるチャンスをブロックするリクエストでより適切に機能する傾向があります。 トランザクション。これにより、より高い同時実行性が可能になり、衝突の可能性についていくらか「楽観的」になります。

    質問のクエリ例は、現状では、デフォルトのREAD COMMITTEDにあります。 トランザクション分離レベルでは、2つ(またはそれ以上)の同時接続で、両方がキューから同じ行を「要求」できます。何が起こるかはこれです:

    • T1が開始し、UPDATEの行をロックするところまで到達します フェーズ。
    • T2は実行時にT1とオーバーラップし、その行を更新しようとします。保留中のCOMMITをブロックします またはROLLBACK T1の。
    • T1はコミットし、行を正常に「要求」しました。
    • T2は行を更新しようとし、T1がすでに持っていることを検出し、行の新しいバージョンを探し、それがまだ選択基準(id)を満たしていることを検出します。 一致)、および行を「要求」します。

    正しく動作するように変更できます(FOR UPDATEを許可するバージョンのPostgreSQLを使用している場合 サブクエリの句)。 FOR UPDATEを追加するだけです IDを選択するサブクエリの最後まで、これが発生します:

    • T1が起動し、選択する前に行をロックします。 ID。
    • T2は、実行時間とブロックでT1とオーバーラップし、IDを選択しようとしている間、COMMITを保留します。 またはROLLBACK T1の。
    • T1はコミットし、行を正常に「要求」しました。
    • T2が読むことができるようになるまでに IDを表示する行は、それが要求されていることを確認するため、次に使用可能なIDを検索します。

    REPEATABLE READで またはSERIALIZABLE トランザクション分離レベルでは、書き込みの競合によりエラーがスローされます。これをキャッチして、SQLSTATEに基づくシリアル化の失敗であると判断し、再試行してください。

    一般にSERIALIZABLEトランザクションが必要であるが、キューイング領域での再試行を回避したい場合は、アドバイザリロックを使用してそれを実行できる可能性があります。



    1. SECOND()の例– MySQL

    2. log-slow-queriesのMySQLLongQuery時間値を変更または設定する

    3. インクリメンタル統計は、クエリオプティマイザでは使用されません

    4. 致命的なエラー:未定義の関数session_register()の呼び出し