私は当初、これにSQL Server Service Brokerを提案しました。ただし、いくつかの調査の結果、これはおそらく問題を処理する最善の方法ではないことが判明しました。
残っているのは、要求したテーブル アーキテクチャです。ただし、お気づきのように、ロック、トランザクション、およびそのようなスキームに対する高い圧力が非常に複雑であるため、指定された基準をすべて満たすソリューションを考え出すことができる可能性は低いです。同時実行性と 1 秒あたりの高いトランザクション。
注: 現在、この問題を調査しており、後ほどご連絡いたします。次のスクリプトは、指定された要件を満たすための私の試みです。ただし、頻繁にデッドロックが発生し、アイテムが順不同で処理されます。しばらくお待ちください。それまでの間、破壊的な読み取り方法 (OUTPUT または OUTPUT INTO を使用した DELETE) を検討してください。
SET XACT_ABORT ON; -- blow up the whole tran on any errors
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN TRAN
UPDATE X
SET X.StatusID = 2 -- in process
OUTPUT Inserted.*
FROM (
SELECT TOP 1 * FROM dbo.QueueTable WITH (READPAST, ROWLOCK)
WHERE StatusID = 1 -- ready
ORDER BY QueuedDate, QueueID -- in case of items with the same date
) X;
-- Do work in application, holding open the tran.
DELETE dbo.QueueTable WHERE QueueID = @QueueID; -- value taken from recordset that was output earlier
COMMIT TRAN;
複数または多数の行が 1 つのクライアントによって一度にロックされる場合、行ロックがエクステント、ページ、またはテーブル ロックにエスカレートする可能性があるため、注意してください。また、通常、ロックを維持する長時間実行されるトランザクションを保持することは、絶対に避けてください。この特別な使用例ではうまくいくかもしれませんが、複数のクライアントによる高い tps によってシステムが故障するのではないかと心配しています。通常、キュー テーブルにクエリを実行するプロセスは、キュー作業を行っているプロセスのみであることに注意してください。レポートを実行するすべてのプロセスは、READ UNCOMMITTED または WITH NOLOCK を使用して、キューとの干渉を回避する必要があります。
行が順不同で処理されることの意味は何ですか? 別のインスタンスが行を正常に完了している間にアプリケーション インスタンスがクラッシュした場合、この遅延により少なくとも 1 行の完了が遅れ、処理順序が正しくなくなる可能性があります。
上記のトランザクション/ロック方法が満足のいくものでない場合、アプリケーションのクラッシュを処理する別の方法として、インスタンスに名前を付けてから、それらの名前付きインスタンスが実行されているかどうかを定期的にチェックする機能を持つ監視プロセスを設定します。名前付きインスタンスが起動すると、そのインスタンス識別子を持つ未処理の行が常にリセットされます (「インスタンス A」と「インスタンス B」のような単純なものが機能します)。さらに、監視プロセスはインスタンスが実行されているかどうかを確認し、実行されていないインスタンスがある場合は、欠落しているインスタンスの行をリセットして、他のインスタンスを実行できるようにします。クラッシュと回復の間にはわずかな時間差がありますが、適切なアーキテクチャがあれば、それはかなり合理的です。
注: 次のリンクは啓発的である必要があります。