ライブデータベース上の精巧なトランザクションを調停する手順を書いています。私が行っている作業はセット操作として行うことができないので、2つのネストされたカーソルを使用しています。排他的ロックを取る正しい方法
私はクライアントごとに調整している間にトランザクションテーブルを排他的にロックする必要がありますが、ロックを解除して、処理する各クライアントの間で他の人にクエリを実行させたいと思います。
私の代わりに、テーブルレベルの行レベルの排他ロックを行うのが大好きだが、what I have read so farは、他のトランザクションが(それは私のためである)READCOMMITED
分離レベルで実行されている場合、私はwith (XLOCK, ROWLOCK, HOLDLOCK)
を行うことができないと言います。
テーブルレベルの排他ロックを正しく実行していますが、行レベル排他ロックをデータベースで実行中の他のクエリを変更せずに動作させる方法はありますか?
declare client_cursor cursor local forward_only for
select distinct CLIENT_GUID from trnHistory
open client_cursor
declare @ClientGuid uniqueidentifier
declare @TransGuid uniqueidentifier
fetch next from client_cursor into @ClientGuid
WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
begin tran
declare @temp int
--The following row will not work if the other connections are running READCOMMITED isolation level
--select @temp = 1
--from trnHistory with (XLOCK, ROWLOCK, HOLDLOCK)
--left join trnCB with (XLOCK, ROWLOCK, HOLDLOCK) on trnHistory.TRANS_GUID = trnCB.TRANS_GUID
--left join trnClients with (XLOCK, ROWLOCK, HOLDLOCK) on trnHistory.TRANS_GUID = trnClients.TRANS_GUID
--(Snip) --Other tables that will be "touched" during the reconcile
--where trnHistory.CLIENT_GUID = @ClientGuid
--Works allways but locks whole table.
select top 1 @temp = 1 from trnHistory with (XLOCK, TABLOCK)
select top 1 @temp = 1 from trnCB with (XLOCK, TABLOCK)
select top 1 @temp = 1 from trnClients with (XLOCK, TABLOCK)
--(Snip) --Other tables that will be "touched" during the reconcile
declare trans_cursor cursor local forward_only for
select TRANS_GUID from trnHistory where CLIENT_GUID = @ClientGuid order by TRANS_NUMBER
open trans_cursor
fetch next from trans_cursor into @TransGuid
WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
--Do Work here
END
fetch next from trans_cursor into @TransGuid
END
close trans_cursor
deallocate trans_cursor
--commit the transaction and release the lock, this allows other
-- connections to get a few queries in while it is safe to read.
commit tran
END
fetch next from client_cursor into @ClientGuid
END
close client_cursor
deallocate client_cursor
私は排他ロックが必要な理由を理解しようとしています。他の人がレコードを挿入しそうですか?レコードを更新する他の人?あなたは、他の人々がデータの一貫性のない見方をすることを心配していますか? – Laurence
@Laurence私は、他の人が一貫性のないビュー状態になることを心配しています。私はクライアントの小さな%に影響を与えるエラーを修正しようとしていますが、訂正プロセスはいくつかの相互依存する行をいくつかのテーブルに残します(実際には5つのテーブルをロックしますが、補正処理を行う。矛盾はクライアントごとに分離されますが、その1つのクライアントで 'SELECT SUM(ColA)FROM trnHistory'を実行すると、「訂正」プロセス中に不正な値が返されます。だから私は読み込みを防ぐために排他的なロックを取る必要があります。 –
私はread_uncommittedをしている人がいない限り、トランザクションがあなたをこのことから保護しない理由を理解していません。 – Laurence