ロックされていないPostgresqlの行を選択する方法はありますか?私は次のことを行うマルチスレッドアプリを持っています:
Select... order by id desc limit 1 for update
テーブルの上。
複数のスレッドがこのクエリを実行する場合、両方が同じ行を引き戻そうとします。
1つは行ロックを取得し、他はブロックし、最初のブロックが行を更新した後に失敗します。私が本当に望んでいるのは、2番目のスレッドが、WHERE
句に一致し、まだロックされていない最初の行を取得することです。
明確にするために、selectを実行した後、各スレッドが最初に使用可能な行をすぐに更新するようにします。
したがって、の行がある場合はID: 1,2,3,4
、最初のスレッドが入り、の行を選択しID=4
てすぐに更新します。
ID=3
そのトランザクション中に2番目のスレッドが来た場合は、その行を取得してすぐにその行を更新したいと思います。
句がロックされた行と一致するnowait
ため、Shareはこれを達成しません。基本的に私が欲しいのは、条項の「ANDNOTLOCKED」のようなものです。WHERE
(ID=4 in my example)
WHERE
Users
-----------------------------------------
ID | Name | flags
-----------------------------------------
1 | bob | 0
2 | fred | 1
3 | tom | 0
4 | ed | 0
クエリが" Select ID from users where flags = 0 order by ID desc limit 1
"で、行が返されたときに次のものが " Update Users set flags = 1 where ID = 0
"の場合、最初のスレッドで行を取得し、次のスレッドで。ID 4
で行を取得しID 3
ます。
selectに""を追加For Update
すると、最初のスレッドが行を取得し、2番目のスレッドがブロックして、最初のトランザクションがコミットされるとWHERE
句が満たされないため、何も返されません。
""を使用しない場合はFor Update
、後続の更新でWHERE句を追加する必要があります(WHEREフラグ= 0)。これにより、1つのスレッドのみが行を更新できます。
2番目のスレッドは最初のスレッドと同じ行を選択しますが、2番目のスレッドの更新は失敗します。
いずれにせよ、トランザクションが重複する最初のスレッドに行4を、2番目のスレッドに行3を与えるデータベースを取得できないため、2番目のスレッドは行の取得と更新に失敗します。