执行完第一个连接马上执行第2个,总是只能更新1行当你的事务提交以后你的锁自然就释放了,不可能说你更新了一行,那么这一行永远都保留更新信息的,你自己想想这样也不合理 --整理一下,发代码别偷懒 DECLARE @id int BEGIN TRAN SET @id = 0 SELECT TOP 1 @id = id FROM t_73 WITH (UPDLOCK,HOLDLOCK) WHERE teacode1 = ' ' WAITFOR delay '00:00:03 ' IF @id > 0 BEGIN UPDATE t_73 SET teacode1 = '1 ' WHERE id = @id --如果这里没提交,执行第二个是可以更新第二行的,可是提交了锁自然就释放了 --COMMIT
是不合理, SET TRANSACTION ISOLATION LEVEL REPEATABLE READbegin transelect * from tablename with (rowlock) where id=3waitfor delay '00:00:05'commit tran
这样的结果是正确的.在用这些锁之前要了解这些锁的作用,UPDLOCK一般是可用来防止丢失更新. UPDLOCK 读取表时使用更新锁,而不使用共享锁,并将锁一直保留到语句或事务的结束。UPDLOCK 的优点是允许您读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。在第一个连接中执行 SELECT TOP 1 @id = id FROM t_73 WITH (UPDLOCK) WHERE teacode1 = ' ' 就等于告诉服务器"我将要更新teacode1 = ' ' 的记录,所有在这条语句后所发出的更新语句(即第二个连接的UPDLOCK语句处)都必须等待,也就是这两个连接是第一个事物执行完后,第二个才开始. 当第一个连接执行完了,teacode1 = 1,接着在第二个连接(UPDLOCK)处开始执行,满足teacode1 = ' '的记录没有.所以只有第一个连接更新了.
DECLARE @id int BEGIN TRAN SET @id = 0 SELECT TOP 1 @id = id FROM t_73 WITH (UPDLOCK,READPAST) --加上readpast WHERE teacode1 = ' '
WAITFOR delay '00:00:10 ' IF @id > 0 BEGIN PRINT(@id) UPDATE t_73 SET teacode1 = convert(varchar(10),id) WHERE id = @id endcommit tran执行后出现死锁(发生位置在Update处),为什么会这样呢,其实在这里我们忽略了索引对并发的影响. 在id上建立个索引就可以避免死锁了.
--整理一下,发代码别偷懒
DECLARE @id int
BEGIN TRAN
SET @id = 0
SELECT TOP 1 @id = id
FROM t_73 WITH (UPDLOCK,HOLDLOCK)
WHERE teacode1 = ' ' WAITFOR delay '00:00:03 '
IF @id > 0
BEGIN
UPDATE t_73 SET teacode1 = '1 '
WHERE id = @id --如果这里没提交,执行第二个是可以更新第二行的,可是提交了锁自然就释放了
--COMMIT
SET TRANSACTION ISOLATION LEVEL REPEATABLE READbegin transelect * from tablename with (rowlock) where id=3waitfor delay '00:00:05'commit tran
UPDLOCK
读取表时使用更新锁,而不使用共享锁,并将锁一直保留到语句或事务的结束。UPDLOCK 的优点是允许您读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。在第一个连接中执行
SELECT TOP 1 @id = id
FROM t_73 WITH (UPDLOCK)
WHERE teacode1 = ' '
就等于告诉服务器"我将要更新teacode1 = ' ' 的记录,所有在这条语句后所发出的更新语句(即第二个连接的UPDLOCK语句处)都必须等待,也就是这两个连接是第一个事物执行完后,第二个才开始.
当第一个连接执行完了,teacode1 = 1,接着在第二个连接(UPDLOCK)处开始执行,满足teacode1 = ' '的记录没有.所以只有第一个连接更新了.
我如何才能只锁定第一个teacode1= ' '的记录呢?
我现在没办法只能用的表锁定,还好一个表至多不超过3万行,最多20用户同时操作。
但是要是只锁定行就更好了。
操作很简单,2万条teacode1 = ' ' 的记录,那个客户请求就分配一条记录给客户修改,并做上标记(当前的事务就是完成这个功能,并做成存储过程)。客户修改完毕后再根据返回的id更新数据。
BEGIN TRAN
SET @id = 0
SELECT TOP 1 @id = id
FROM t_73 WITH (UPDLOCK,READPAST) --加上readpast
WHERE teacode1 = ' '
WAITFOR delay '00:00:10 '
IF @id > 0
BEGIN
PRINT(@id)
UPDATE t_73 SET teacode1 = convert(varchar(10),id)
WHERE id = @id
endcommit tran执行后出现死锁(发生位置在Update处),为什么会这样呢,其实在这里我们忽略了索引对并发的影响.
在id上建立个索引就可以避免死锁了.