あなたは以前にこの質問をし、答えを与えられました:スキーマとコードを修正してください。その投稿では、ロックの競合はIXロックであり、インテントロックの競合は、粒度の高いロックを示しています。これは、テーブルスキャンを示しています。ロックヒントは必要ありません。必要なのはインデックスと適切なクエリだけです。たとえば、他の質問を考えてみましょう。SQLサーバーで行レベルのロックが正しく機能していないように見えるのはなぜですか。答えは簡単です。ロックテーブルは、LockNameのクラスター化されたインデックスで整理する必要があります。
CREATE TABLE [dbo].[Locks](
[LockName] [varchar](50) NOT NULL,
[Locked] [bit] NOT NULL,
CONSTRAINT [PK_Locks] PRIMARY KEY CLUSTERED ([LockName]));
GO
insert into Locks (LockName, Locked) values ('A', 0);
insert into Locks (LockName, Locked) values ('B', 0);
GO
1つのセッションでこれを行います:
begin transaction
update Locks
set Locked=1
output inserted.*
where LockName = 'A';
他のセッションでは、これを行います。
begin transaction
update Locks
set Locked=1
output inserted.*
where LockName = 'B';
更新の競合、ブロッキング、(間違った)ヒントの必要はなく、何もありません。ちょうど良いoleの正しいスキーマとクエリの設計。
ちなみに、ここで説明するロックはすでに存在し、キーロックと呼ばれます。これらは、SQLServerが動作するデフォルトの暗黙モードです。SQLServerが1秒あたり16000tpcトランザクションのTPC-Cベンチマーク数を公開できると世界でどのように想像しますか?サーバーに必要なすべての並列処理機能があります。使用方法を理解するには、1冊か2冊の本を読む必要があります。このテーマに関する文献はたくさんあります。トランザクション処理:概念と手法から始めることができます。
更新しました
begin transaction
select lockname from locks where lockname='A'
update Locks Set locked=1 where lockname='A'
これは、ロックのヒントがいくつ/多様であっても、機能しません。これが、出力構文を含む更新がある理由です。
begin transaction
update Locks
Set locked=1
output inserted.*
where lockname='A'
これにより、最初に更新してから、更新したものを返すことが保証されます。この手法は、データベースでは、求めるセマンティクスであるリソースの取得に非常によく使用されます。実際、この手法は、リソース獲得ポスターの子であるキュー処理の基礎です。OUTPUT句の「キュー」段落を参照してください。キューには、処理するリソースのテーブルがあり、各スレッドは1つを取得してロックし、処理を開始します。
create table Resources (
id int identity(1,1) not null,
enqueue_time datetime not null default getutcdate(),
is_processing bit not null default 0,
payload xml);
create clustered index cdxResources on Resources
(is_processing, enqueue_time);
go
-- enqueue:
insert into Resources (payload) values ('<do>This</do>');
insert into Resources (payload) values ('<do>That</do>');
insert into Resources (payload) values ('<do>Something</do>');
insert into Resources (payload) values ('<do>Anything</do>');
別々のセッションから、これを実行します。
--dequeue
begin transaction;
with cte as (
select top(1) *
from Resources with(readpast)
where is_processing = 0
order by enqueue_time)
update cte
set is_processing = 1
output inserted.*;
各セッションがそれ自体のリソースを取得し、それをロックし、他のすべての人によってロックされているすべてのものをスキップするのがわかります。たまたま私はこのように動作するシステムを運用しており、テーブル内に500万を超えるリソース(Webサービスの支払い処理要求)があり、100個の同時プロセッサーから1秒あたり約50個のキューを取り出して処理しています(約2秒かかります)。プロセスの呼び出しごと)。ジャンクハードウェアの一部。だからそれは絶対に可能です。