MySQL の同時ワーカー スレッドによるアトミックな読み取りと更新
P粉239164234
P粉239164234 2023-12-21 13:38:51
0
2
437

MySQL テーブルに対して同時に読み書きできるワーカーが複数あるとします (例: jobs)。各ワーカーのタスクは次のとおりです:

  1. 最も古い キューに入れられた ジョブ
  2. ステータスを RUNNING
  3. に設定します
  4. 対応するIDを返します。

ワーカーがステップ #1 を実行するとき、適格なジョブが 存在しない可能性があることに注意してください (つまり、QUEUED)。

これまでのところ、次の疑似コードがあります。ステップ #1 でジョブが返されない場合は、(

ROLLBACK) トランザクションをキャンセルする必要があると思います。以下のコードでこれを行うにはどうすればよいでしょうか? ああああ

P粉239164234
P粉239164234

全員に返信(2)
P粉536909186

あなたが何を望んでいるのかは明確ではありません。しかし、あなたのタスクが次の QUEUED ジョブを見つけることであるとします。ステータスを RUNNING に設定し、適切な ID を選択します。

シングルスレッド環境では、コードをそのまま使用できます。選択した ID をアプリケーション コードの変数に抽出し、WHERE 句の UPDATE クエリに渡します。 write ステートメントは 1 つだけなので、トランザクションも必要ありません。これを SQLscript で真似ることができます。

これがあなたの現在のステータスであると仮定します:

リーリー

次のキューに入れられたジョブ (id=2) を開始したいと考えています。

リーリー

あなたは得ます

リーリー

最後の選択から開始します。テーブルのステータスは次のようになります:

リーリー

DB Fiddle で見る

ジョブを起動するプロセスが複数ある場合は、FOR UPDATE を使用して行をロックする必要があります。ただし、LAST_INSERT_ID() を使用すると、この状況を回避できます。

上記のステータスから開始すると、ジョブ 2 はすでに実行中です:

リーリー

次のものが得られます:

リーリー

新しいステータスは次のとおりです:

リーリー

DB Fiddle で見る

UPDATE ステートメントがどの行にも影響を与えなかった (キューに入れられた行がない) 場合、

ROW_COUNT()0 になります。

私が気づいていないリスクがいくつかあるかもしれませんが、それは私の実際のアプローチ方法でもありません。むしろ、より多くの情報を

jobs テーブルに保存したいと考えています。簡単な例: リーリー ###そして### リーリー

現在実行中のジョブは特定のプロセスに属しており、

を使用するだけで選択できます。 リーリー

もっと知りたいかもしれません - 例:

queued_at

started_atfinished_at

いいねを押す +0
P粉635509719

今週、私はあなたのケースと非常によく似たものを実装します。複数のワーカー。それぞれが一連の行の「次の行」を取得して作業します。

疑似コードは次のとおりです:

リーリー

FOR UPDATE を使用することは、競合状態 (つまり、複数のワーカーが同じ行を取得しようとすること) を回避するために重要です。

SELECT ... INTO の詳細については、https://dev.mysql.com/doc/refman/8.0/en/select-into.html を参照してください。

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!