同じmysqlテーブルから行を選択する5つ以上のプロセスが同時にあります。各プロセスは 100 行を選択し、選択した行を処理し、削除します。
しかし、同じ行が 2 回以上選択されて処理されています。
MYSQL 側または Ruby on Rails 側で発生しないようにするにはどうすればよいですか?
アプリは Ruby On Rails で構築されています...
同じmysqlテーブルから行を選択する5つ以上のプロセスが同時にあります。各プロセスは 100 行を選択し、選択した行を処理し、削除します。
しかし、同じ行が 2 回以上選択されて処理されています。
MYSQL 側または Ruby on Rails 側で発生しないようにするにはどうすればよいですか?
アプリは Ruby On Rails で構築されています...
テーブルはワークフローのように見えます。つまり、行の状態を示すフィールドが必要です (この場合は「要求済み」)。他のプロセスは、要求されていない行を選択する必要があります。これにより、プロセスが互いの行を踏むのを防ぐことができます。
さらに一歩進めたい場合は、プロセス識別子を使用して、何が何に取り組んでいるか、おそらくどれくらいの時間がかかりすぎているか、完了しているかどうかなどを知ることができます。
ええ、以前の質問に戻って、いくつかの回答を承認してください。あなたが間違いなく見逃したものを少なくとも 1 つ見ました。
エリックの答えは良いですが、少し詳しく説明する必要があると思います...
テーブルに次のような追加の列があります。
lockhost VARCHAR(60),
lockpid INT,
locktime INT, -- Or your favourite timestamp.
それらをすべてデフォルトで NULL にします。
次に、次のようにして、ワーカー プロセスに行を「要求」させます。
UPDATE tbl SET lockhost='myhostname', lockpid=12345,
locktime=UNIX_TIMESTAMP() WHERE lockhost IS NULL ORDER BY id
LIMIT 100
次に、要求された行を SELECT ... WHERE lockhost='myhostname' および lockpid=12345 で処理します。
行の処理が終了したら、必要な更新を行い、lockhost、lockpid、および locktime を NULL に戻します (または削除します)。
これにより、同じ行が一度に複数のプロセスによって処理されるのを防ぎます。処理を行うホストが複数ある場合があるため、ホスト名が必要です。
バッチの処理中にプロセスがクラッシュした場合は、「locktime」列が非常に古いかどうかを確認できます (処理にかかる可能性があるよりもはるかに古い、たとえば数時間)。次に、lockhost が null でなくても、古い「locktime」を持ついくつかの行を再利用できます。
これは、データベースでよく見られる「キュー パターン」です。非常に効率的ではありません。アイテムがキューに出入りする割合が非常に高い場合は、代わりに適切なキュー サーバーの使用を検討してください。