2015-06-16 4 views
1

Я пишу эту процедуру в SQL Server 2008 R2:Блокировка таблицы SQL Server, чтобы предотвратить вставки

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', @[email protected] OUTPUT 

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

     COMMIT 
    END 

Является ли это правильный способ заблокировать таблицу для вставки в то время как я делаю этот запрос и последующее тождество переустановку? Также хотелось бы знать, есть ли какие-либо проблемы в том, что я делаю выше? Это будет использоваться в пользовательской среде репликации.

ТИА

ответ

1

SQL Server по умолчанию позволяет грязное чтение, не позволяя грязные записи. Чтобы этого не произошло, вам необходимо явно заблокировать таблицу, как вы это делали. Если вы этого не сделаете, похоже, вы можете столкнуться с ситуацией, когда два разных пользователя могут получить одинаковое значение для вашей переменной @sql, если они оба прочитают из таблицы, прежде чем один из них выполнит повторную загрузку (в то время как Ник прав блокировки во время повторного копирования, вы делаете выбор вне контекста повтора). Поэтому я думаю, что у вас есть это право.

Вы также захотите посмотреть на this, почему вы должны заключить транзакцию в командах SET_XACT_ABORT_ON/OFF.

+0

Большое спасибо! – user4013241

0

вы можете также рассмотреть вопрос об установлении уровней изолированности ЧИТАТЬ COMMITTED в сервере Sql только для чтения поручены данные

SET TRANSACTION ISOLATION LEVEL READ COMMITTED; 

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