我需要在数据库中首先选择(比如说)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是每个此更新的唯一标识符(例如timestamp或guid))
我的问题:
我认为使用嵌套select 的操作更新是原子的 - 这意味着每个客户端都会收到他自己的唯一数据集(没有其他客户端收到他的数据子集)。
然而,看起来我错了 - 在某些情况下,有些客户端没有收到任何数据,因为可能他们首先两者执行select而然后两者执行更新(因此第一个客户端没有标记的行)。
此操作是否为原子?
我使用Sql server 2005.查询通过NHibernate运行,如此
session.CreateSQLQuery('update....')
答案 0 :(得分:5)
SELECT
在读取的行上放置共享锁,然后可以在READ COMMITED
隔离模式下解除。
UPDATE
将更新锁稍后提升为独占锁。直到交易结束才取消它们。
您应该在锁定后立即保留锁定。
您可以通过设置事务隔离级别REPEATABLE READ
来执行此操作,该事务隔离级别将保留共享锁,直到事务结束并阻止UPDATE
部分锁定这些行。
或者,您可以按以下方式重写查询:
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
,它将跳过锁定的行。