【发布时间】:2012-11-17 23:50:06
【问题描述】:
我正在编写一个程序来协调实时数据库上的最终事务。我正在做的工作不能作为集合操作完成,所以我使用了两个嵌套游标。
当我为每个客户端进行协调时,我需要在事务表上使用排他锁,但我想释放锁并让其他人在我处理的每个客户端之间运行他们的查询。
我很想在行级别而不是表级别上做一个排他锁,但是what I have read so far 说如果其他事务在READCOMMITED 隔离级别上运行,我不能做with (XLOCK, ROWLOCK, HOLDLOCK)(这是为了我)。
我是否正确地使用了表级独占锁,Server 2008 R2 中是否有任何方法可以让行级独占锁按照我想要的方式工作,而无需修改数据库上运行的其他查询?
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 我担心其他人的视图状态不一致。我正在尝试纠正一个影响一小部分客户的错误,但是该纠正过程在几个表中留下了几个相互依赖的行(我实际上将锁定 5 个表,但将我的代码示例简化为一个表)在期间处于不一致状态修正过程。不一致是每个客户端隔离的,但是在“更正”过程中对一个客户端执行
SELECT SUM(ColA) FROM trnHistory会返回不正确的值。所以我需要采取排他锁来防止读取。 -
我不明白为什么交易不能保护你免受这种情况的影响,除非你有人在做 read_uncommitted。
-
@Laurence 我知道确实如此,我的问题是:“我是否正确使用了表级排他锁,Server 2008 R2 中是否有任何方法可以让行级排他锁按我想要的方式工作到不修改数据库上运行的其他查询?”。正如我之前所说,我正在使用 5 个数据库,我想同时锁定所有 5 个数据库,而不是第一次触摸每个数据库以保持一致性。我将更新我的代码示例以显示其他表,因为您让我意识到我确实犯了一个错误。
-
我可能很密集,但是如果您只是担心其他读者,那么交易还不够吗?开始事务,使不一致,使一致,提交事务。没有人看到中间的部分,除非他们说他们不介意不一致的数据。如果您担心其他作家,那么我认为行 xlocks 会很好。不过,您确实曾经提到过 5 个数据库。分布式事务可能会出现问题。
标签: sql sql-server sql-server-2008-r2 locking