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

同時アクセス時にテーブル内の特定の行数をマークする方法

    あなたが言及している関連する答えで:

    • PostgresUPDATE...制限1

    目的は、1つをロックすることです 一度に行。 デッドロックの可能性がないため、これはアドバイザリロックの有無にかかわらず正常に機能します。 -同じトランザクションでより多くの行をロックしようとしない限り。

    あなたの例は、一度に3000行をロックしたいという点で異なります 。 あります すべての同時書き込み操作が同じ一貫した順序で行をロックする場合を除いて、デッドロックの可能性があります。ドキュメントごと:

    デッドロックに対する最善の防御策は、通常、データベースを使用するすべてのアプリケーションが一貫した順序で複数のオブジェクトのロックを取得することを確認することにより、デッドロックを回避することです。

    サブクエリでORDERBYを使用して実装します。

    UPDATE cargo_item item
    SET job_id = 'SOME_UUID', job_ts = now()
    FROM  ( 
       SELECT id
       FROM   cargo_item
       WHERE  state='NEW' AND job_id is null 
       ORDER  BY id
       LIMIT  3000
       FOR UPDATE
       ) sub
    WHERE  item.id = sub.id;
    

    すべてである限り、これは安全で信頼できます トランザクションは同じ順序でロックを取得し、順序列の同時更新は予期されません。 (マニュアルのこの章の最後にある黄色の「注意」ボックスをお読みください。)したがって、idを更新する予定はないので、これはあなたの場合は安全です。 列。

    事実上、一度に1つのクライアントのみがこの方法で行を操作できます。同時トランザクションは、同じ(ロックされた)行をロックしようとし、最初のトランザクションが終了するのを待ちます。

    アドバイザリーロック 実行中の同時トランザクションが多数または非常に長い場合に役立ちます(そうではないようです)。ほんの数個で、上記のクエリを使用して同時トランザクションを順番に待機させる方が全体的に安価になります。

    オールインワンアップデート

    セットアップでは、同時アクセス自体は問題ではないようです。同時実行性は、現在のソリューションによって作成された問題です。

    代わりに、すべてを1つのUPDATEで実行してください nのバッチを割り当てます 各UUIDに番号(例では3000)を付けて、一度に更新します。最速である必要があります。

    UPDATE cargo_item c
    SET    job_id = u.uuid_col
         , job_ts = now()
    FROM  (
       SELECT row_number() OVER () AS rn, uuid_col
       FROM   uuid_tbl WHERE  <some_criteria>  -- or see below
       ) u
    JOIN (
       SELECT (row_number() OVER () / 3000) + 1 AS rn, item.id 
       FROM   cargo_item
       WHERE  state = 'NEW' AND job_id IS NULL
       FOR    UPDATE   -- just to be sure
       ) c2 USING (rn)
    WHERE  c2.item_id = c.item_id;
    

    主なポイント

    • 整数除算は切り捨てられます。最初の3000行に1、次の3000行に2を取得します。など

    • 行を任意に選択します。ORDER BYを適用できます row_number()のウィンドウ内 特定の行を割り当てる。

    • ディスパッチするUUIDのテーブルがない場合(uuid_tbl )、VALUESを使用します それらを供給するための表現。例。

    • 3000行のバッチを取得します。割り当てる3000の倍数が見つからない場合、最後のバッチは3000未満になります。



    1. SQL Server実行プラン—それは何であり、パフォーマンスの問題にどのように役立ちますか?

    2. SQLServerでネストされたcaseステートメントロジックを実行するための最良の方法

    3. MariaDB SUBSTR()の説明

    4. 既存のRailsアプリをherokuに移動するにはどうすればよいですか? (sqliteからpostgresへ)