我需要先选择(假设)数据库中的10000行并将其返回。可能有更多的客户端一次执行此操作。我想出了这个查询:
update v set v.batch_Id = :batchId from tblRedir v inner join ( select top 10000 id from tblRedir where batch_Id is null order by Date asc ) v2 on v.id=v2.id
这是一个由更新和嵌套选择组成的操作。这两个查询都在同一表(tblRedir)上工作。这个想法是,这些行首先用唯一的batchId进行标记,然后通过进行返回
select * from tblRedir where batch_id = :batchId
(对于每个此更新,batchid是唯一的标识符(例如,时间戳或guid))
我的问题:
我认为 使用嵌套选择进行 的操作 更新 是原子的-这意味着每个客户端都将接收自己的唯一数据集(没有其他客户端会接收其数据的子集)。
但是,看来我是错的-在某些情况下,有些客户端没有接收到数据,因为可能它们首先 都 执行了选择, 然后都 执行了更新(因此第一个客户端没有标记的行)。
此操作是否为原子操作?
我使用Sql Server2005。查询是通过NHibernate这样运行的
session.CreateSQLQuery('update....')
SELECT在读取的行上放置共享锁,然后可以在READ COMMITED隔离模式下解除共享锁。
SELECT
READ COMMITED
UPDATE将更新锁升级为排他锁。直到交易结束它们才被解除。
UPDATE
您应将锁放置后立即保留。
您可以通过设置事务隔离级别来做到这一点,该级别REPEATABLE READ将保留共享锁直到事务结束,并防止UPDATE部分锁定这些行。
REPEATABLE READ
或者,您可以按以下方式重写查询:
WITH q AS ( SELECT TOP 10000 * FROM mytable WITH (ROWLOCK, READPAST) WHERE batch_id IS NULL ORDER BY date ) UPDATE q SET batch_id = @myid
,这只会跳过锁定的行。