Будет ли использование подсказок TABLOCK и HOLDLOCK в SQL Server 2005 ПОЛНОСТЬЮ предотвращать вставки до конца транзакции? - PullRequest
4 голосов
/ 11 августа 2010

Мне нужно получить поле идентификатора, сгенерированное SQL Server 2005. Обычно я просто использую SCOPE_IDENTITY или добавляю OUTPUT CLAUSE к вставке, однако ни один из этих методов не помогает в этой ситуации: так как триггер INSTEAD OF присоединен стол. Затем я рассмотрел @@ IDENTITY, но поскольку к таблице подключен еще один триггер, это тоже не годится. Поэтому я решил использовать IDENT_CURRENT. Однако, поскольку это небезопасно для сеанса, мне нужен какой-то способ убедиться, что никакой другой сеанс не может быть вставлен в таблицу, пока я не получу новый идентификатор. Я экспериментировал с использованием подсказок TABLOCK и HOLDLOCK, похоже, это работает, но я не администратор баз данных. Поэтому мой вопрос заключается в том, позволят ли использование подсказок TABLOCK и HOLDLOCK в SQL Server 2005 ПОЛНОСТЬЮ предотвратить вставки до конца транзакции?

Надеюсь, этот надуманный пример объяснит ситуацию. (Я понимаю, что функционально хранимая процедура может заменить оба триггера в этом случае.)

CREATE TABLE Person
(
 PersonID  INT IDENTITY PRIMARY KEY,
 FirstName VARCHAR(50)
);
GO

CREATE TABLE PersonHistory
(
 PersonHistoryID INT IDENTITY(5,1) PRIMARY KEY,
 PersonId INT,
 FirstName VARCHAR(50)
);
GO

CREATE TRIGGER PersonAudit ON Person
AFTER Insert
AS
INSERT INTO PersonHistory (PersonID, FirstName)
SELECT Inserted.PersonID, Inserted.FirstName
FROM Inserted;
GO

CREATE TRIGGER PersonCleaner ON Person
INSTEAD OF Insert
AS
INSERT INTO Person (FirstName)
SELECT UPPER(Inserted.FirstName)
FROM Inserted;
GO

BEGIN TRAN;

INSERT INTO Person WITH (TABLOCK, HOLDLOCK) (FirstName) 
VALUES ('George');

--SELECT @@IDENTITY AS '@@IDENTITY'; -- 5 
--SELECT IDENT_CURRENT('Person') AS 'IDENT_CURRENT'; -- 1
--SELECT SCOPE_IDENTITY() AS 'SCOPE_IDENITIY'; -- NULL

DECLARE @PersonID int;
SELECT @PersonID = IDENT_CURRENT('Person');
SELECT @PersonID; -- 1

COMMIT TRAN;

--SELECT * FROM Person;
--SELECT * FROM PersonHistory;

DROP TABLE Person;
DROP TABLE PersonHistory;

1 Ответ

2 голосов
/ 10 июня 2011

Лучшей вашей ставкой была бы подсказка TABLOCKX, которая указывает, что эксклюзивная блокировка берется на стол до завершения транзакции.Исключительные (X) блокировки препятствуют доступу к ресурсу параллельными транзакциями.Никакие другие транзакции не могут читать или изменять данные, заблокированные с помощью эксклюзивной блокировки (X).

...