用于什么类型的锁(表提示)?

时间:2012-12-07 04:42:10

标签: sql concurrency locking rdbms

假设我有两列CategoryId和SubcategoryId。 SubcategoryId从每个CategoryId的1开始。插入新的子类别时,我需要为给定的CategoryId计算MAX(SubcategoryId)+1。

以下是否正确?

BEGIN TRANSACTION
DECLARE @NextId bigint;
SELECT @NextId = ISNULL(MAX(SubcategoryId),0) + 1 
FROM Subcategory WITH (UPDLOCK, HOLDLOCK) 
WHERE CategoryId = @CategoryId;
INSERT INTO Subcategory
(
    CategoryId, 
    SubcategoryId
) 
VALUES
(
    @CategoryId, 
    @NextId
 );
COMMIT

WITH(UPDLOCK,HOLDLOCK)是否也阻止了具有相同CategoryId的新行的并发插入,还是仅锁定SELECT时匹配的现有行?如果是后者我应该把它改成TABLOCK吗?是否还需要某种独家锁?

1 个答案:

答案 0 :(得分:1)

一般来说,除非您有特殊要求,否则不建议使用锁定级别。根据我的理解,SQL Server服务器引擎可以处理并发问题而无需锁定提示。

所以你的表定义是:

CREATE TABLE Subcategory
(
   CategoryId bigint, 
   SubcategoryId bigint
 )

如果您将表格定义更改为:

CREATE TABLE Subcategory
(
   CategoryId bigint NOT NULL, 
   SubcategoryId bigint IDENTITY(1,1) NOT NULL
 ) ON [PRIMARY];
 ALTER TABLE Subcategory
 ADD CONSTRAINT pk_Subcategory PRIMARY KEY (CategoryId,SubcategoryId  )

子类别ID将成为自动编号。此数字将在每个插入时递增。因此,您不需要在插入期间指定子类别,这将允许SQL服务器处理并发。最好让SQL处理表的锁定并处理并发。

如果您将表格结构更改为我的建议,您的查询也会变得更简单。

BEGIN TRAN
INSERT INTO Subcategory
(
    CategoryId, 

) 
VALUES
(
    @CategoryId, 

 );
 COMMIT TRAN

这可能是您的解决方案。抱歉,我的语法可能有误,因为我几个月没有碰过SQL服务器。