PROCESS_IND
= 'N' のレコードのテーブルをクエリし、何らかの処理を行ってPROCESS_IND
から 'Y' に更新する単一のプロセスがあります。
このプロセスの複数のインスタンスを実行できるようにしたいのですが、同時実行の問題を回避するためのベスト プラクティスがわかりません。
どこから始めればよいですか?
PROCESS_IND
= 'N' のレコードのテーブルをクエリし、何らかの処理を行ってPROCESS_IND
から 'Y' に更新する単一のプロセスがあります。
このプロセスの複数のインスタンスを実行できるようにしたいのですが、同時実行の問題を回避するためのベスト プラクティスがわかりません。
どこから始めればよいですか?
私が使用するパターンは次のとおりです。
各タスクは、次のようなクエリを実行します。
UPDATE taskstable SET lockedby=(my id), locktime=now() WHERE lockedby IS NULL ORDER BY ID LIMIT 10
10 は「バッチ サイズ」です。
LIMIT 10 は MySQL 固有ですが、他のデータベースにも同等のものがあります。ORDER BY は、クエリが非決定論的であることを避けるためにインポートされます。
意図は理解できますが、すぐに行レベルのロックに移行することに同意しません。これにより、応答時間が短縮され、実際に状況が悪化する可能性があります. テスト後に APL の同時実行性の問題が発生した場合は、最初に「データページ」ロックに繰り返し移行する必要があります。
この質問に適切に答えるには、関連するテーブル構造とインデックスに関するより多くの情報が必要ですが、さらに説明する必要があります。
DOL、データ行のロックは、全ページ/ページ レベルのロックよりも多くのロックを使用します。すべてのロックを管理するオーバーヘッドと、キャッシュ内のより多くのロック構造の要求による使用可能なメモリの減少により、パフォーマンスが低下し、より同時実行のアプローチに移行することで得られる可能性のある利益が相殺されます。
最初に APL で移動せずにアプローチをテストし (すべてのページ ロックの「デフォルト」)、問題が見られる場合は DOL に移動します (最初にデータページ、次にデータ行)。テーブルを DOL に切り替えると、そのテーブルのすべての応答がわずかに悪化し、テーブルがより多くのスペースを使用し、テーブルが断片化しやすくなり、定期的なメンテナンスが必要になることに注意してください。
つまり、すぐにデータ行に移動しないでください。最初に同時実行アプローチを試してください。問題がある場合は、最初にデータページのロックを使用し、最後にデータ行を使用してください。
row level locking
次を使用してテーブルで有効にする必要があります。
CREATE TABLE mytable (...) LOCK DATAROWS
次にあなた:
FOR UPDATE
ます(ロックされます)トランザクションが終了するまで、他のプロセスはこの行に対して何もできません。
PSを使用することで発生する可能性のあるオーバーヘッドの問題に言及する人もいますLOCK DATAROWS
。
はい、オーバーヘッドがありますが、このようなテーブルではほとんど問題とは言えません。
しかし、次に切り替えると(デフォルトでは) DATAPAGES
1 行につき 1 行しかロックできず、行が 1 ページに存在するプロセスは同時に実行できなくなります。PAGE
2k
一度に数十行がロックされているテーブルについて話している場合、顕著なパフォーマンスの低下はほとんどありません。
そのような設計では、プロセスの並行性がはるかに重要です。
最も明白な方法はロックです。データベースにロックがない場合は、「ロック済み」フィールドを追加して自分で実装できます。
同時実行を簡素化する方法のいくつかは、未処理のアイテムへのアクセスをランダム化することです。そのため、最初のアイテムで競合するのではなく、アクセスをランダムに分散します。
プロシージャを単一のSQLステートメントに変換し、複数の行を単一のバッチとして処理します。これは、データベースが機能することになっている方法です。