5

これが私がやろうとしていることの擬似コードです:

rate_count = SELECT COUNT(id) FROM job WHERE last_processed_at >= ?

current_limit = rate_limit - rate_count
if current_limit > 0
  UPDATE job SET state='processing'
  WHERE id IN(
    SELECT id FROM job
    WHERE state='pending'
    LIMIT :current_limit
  )

並行性の問題を除いて、私はそれを機能させています。同時に複数のセッションから実行すると、両方のセッションが選択され、したがって同じものが更新されます:(

SELECT サブクエリに FOR UPDATE を追加することで、アトミックな 2 番目のクエリを取得できます。しかし、FOR UPDATE は集計関数では許可されていないため、最初のクエリに FOR UPDATE を追加することはできません。

このピースをアトミックトランザクションにするにはどうすればよいですか?

4

1 に答える 1

4

サブクエリ内で FOR UPDATE を実行できます。

rate_count := COUNT(id) 
              FROM (
                SELECT id FROM job
                WHERE last_processed_at >= ? FOR UPDATE
                ) a;

このすべてを 1 つのクエリで実行することもできます。

UPDATE job SET state='processing'
WHERE id IN (
  SELECT id FROM job
  WHERE state='pending'
  LIMIT (SELECT GREATEST(0, rate_limit - COUNT(id))
         FROM (SELECT id FROM job
               WHERE last_processed_at >= ? FOR UPDATE) a
        )
)
于 2016-06-24T07:11:35.113 に答える