锁定SQL Server表以防止插入

时间:2015-06-16 01:10:26

标签: sql sql-server table-locking

我在SQL Server 2008 R2中编写此过程:

CREATE Procedure [dbo].[SetLocalSeed](@tableName nvarchar(128)) 
AS
BEGIN
    -- Find the primary key column name
    DECLARE @pkName NVARCHAR(128)

    SELECT @pkName = COLUMN_NAME
    FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
    WHERE OBJECTPROPERTY(OBJECT_ID(constraint_name), 'IsPrimaryKey') = 1 
      AND TABLE_NAME = @tableName

    BEGIN TRANSACTION
        -- Find the max LOCAL pk value (< 10^7) - hold the lock until the transaction completes.
        DECLARE @max BIGINT
        DECLARE @sql NVARCHAR(MAX) = 'SELECT @max = MAX([' + @pkName + ']) FROM [' + @tableName + '] WITH (TABLOCKX, HOLDLOCK) WHERE [' + @pkName + '] < POWER(10,7)'; 
        EXEC sp_executeSql @sql, N'@max BIGINT OUT', @max=@max OUTPUT

        -- Reset the seed to the table
        DBCC CHECKIDENT(@tableName, RESEED, @max)

        COMMIT
    END

这是在我执行此查询并后续身份重新设定时锁定表格的正确方法吗?还想知道我上面做的是否有任何问题?这将用于自定义复制环境。

TIA

2 个答案:

答案 0 :(得分:1)

SQL Server默认允许脏读,而不允许脏写。为了防止这种情况,您需要像完成一样显式锁定表。如果你不这样做,看起来你可能遇到这样一种情况:两个不同的用户可以为你的@sql变量获得相同的值,如果他们都从表中读取其中一个进行重新设定之前(而尼克是正确的)重新种植期间的锁定,你在重新种植的背景之外做一个选择)。所以我认为你有这个权利。

您还需要查看this,了解为什么要将事务封装在SET_XACT_ABORT_ON / OFF命令中。

答案 1 :(得分:0)

您还可以考虑在Sql server中将隔离级别设置为READ COMMITTED以仅读取提交的数据

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

https://msdn.microsoft.com/en-us/library/ms173763.aspx