ALTER PROC [dbo].[getTopic]
(
@uid INT
)
AS
DECLARE @id uniqueidentifier
BEGIN
BEGIN TRAN
SET ROWCOUNT 1
SELECT @id=[id] FROM [topic] WITH(UPDLOCK, READPAST) WHERE [uid]=0
--waitfor delay '00:00:01'
if @@rowcount>0 BEGIN
SELECT * FROM [topic] WHERE [id]=@id
UPDATE [topic] SET [uid]=@uid WHERE [id]=@id
END
COMMIT TRAN
END
在当前存储过程执行中,当前记录不被别的连接访问,我不是很确定锁类型是否合理高并发不知道会不会出问题。
另外两个SELECT 一个赋值一个输出有没有办法合并成一个,会节约一些开支。
当从上述语句觉得可以简化成:ALTER PROC [dbo].[getTopic]
(
@uid INT
)
AS
DECLARE @id uniqueidentifier
BEGIN
UPDATE [topic] WITH(UPDLOCK, READPAST) SET [uid]=@uid WHERE [uid]=0
END
指定数据库引擎不读取由其他事务锁定的行。在大多数情况下,这同样适用于页。如果指定了 READPAST,则行级锁和页级锁都将被跳过。也就是说,数据库引擎将跳过这些行或页,而不是阻塞当前事务直到锁被释放。例如,假定表 T1 包含一个单精度整数列,其值为 1、2、3、4 和 5。如果事务 A 将值 3 值改为 8,但尚未提交,则 SELECT * FROM T1 (READPAST) 将生成值 1、2、4 和 5。使用 SQL Server 表实现工作队列时,READPAST 主要用于减少锁定争用。使用 READPAST 的队列读取器会跳过被其他事务锁定的队列项,跳至下一个可用的队列项,而不是等待其他事务释放锁。可为 UPDATE 或 DELETE 语句中以及 FROM 子句中引用的任何表指定 READPAST。如果 READPAST 是在 UPDATE 语句中指定的,则仅当读取数据以标识要更新的记录时才应用 READPAST,而不考虑语句中指定 READPAST 的位置。不能为 INSERT 语句的 INTO 子句中的表指定 READPAST。使用 READPAST 的读操作不会发生阻塞。读取外键或索引视图或者修改辅助索引时,使用 READPAST 的更新或删除操作可能发生阻塞。仅可在运行于 READ COMMITTED 或 REPEATABLE READ 隔离级别的事务中指定 READPAST。在从 SNAPSHOT 隔离级别操作的事务中指定时,READPAST 必须与需要锁的其他表提示(例如,UPDLOCK 和 HOLDLOCK)组合。当 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON 并且满足以下条件之一时,无法指定 READPAST 表提示。会话的事务隔离级别为 READ COMMITTED。
查询中也指定了 READCOMMITTED 表提示。
若要在上述情况下指定 READPAST 提示,请删除 READCOMMITTED 表提示(如果存在),然后在查询中包括 READCOMMITTEDLOCK 表提示。
(
@uid INT
)
AS
DECLARE @id uniqueidentifier
BEGIN
BEGIN TRAN
SET ROWCOUNT 1
SELECT @id=[id] FROM [topic] WHERE [uid]=0
if ISNULL(@id,0)>0 BEGIN
UPDATE [topic] SET [uid]=@uid WHERE [id]=@id
if (@@ERROR<>0)
begin
ROLLBACK TRAN
RETURN
end
END
COMMIT TRAN
END
ALTER PROC [dbo].[getTopic] @uid INT
AS
DECLARE @id uniqueidentifier
BEGIN
SELECT @id=[id] FROM [topic] WHERE [uid]=0
if ISNULL(@id,0)>0
BEGIN
BEGIN TRAN
UPDATE [topic] SET [uid]=@uid WHERE [id]=@id
if (@@ERROR<>0)
ROLLBACK TRAN
else
COMMIT TRAN
END END go