Skip to content

Простая лабораторная работа для демонстрации опасности NOLOCK в операторах INSERT

Пересказ статьи William Assaf. A simple lab to demonstrate the danger of NOLOCKs in INSERT statements


Уровню изоляции READ UNCOMMITTED, который активирует табличный хинт NOLOCK, не следует доверять, когда он используется при записи данных. Вы не всегда защищены ошибкой 1065 в случаях, когда запись сталкивается с NOLOCK.
Ошибка 1065 говорит: "Хинты NOLOCK и READUNCOMMITTED не разрешаются для таблиц при операторах INSERT, UPDATE, DELETE или MERGE". Однако NOLOCK может все же представлять опасность для источника записи. (NOLOCK также может завершиться с ошибкой 601 даже в базовых операторах SELECT, но программистов это не всегда пугает.)

Вот самый элементарный пример, которым можно поделиться на вечеринках, чтобы отпугнуть разработчиков от авантюрного использования NOLOCK:

-- Соединение 1
DROP TABLE IF EXISTS dbo.testnolock1
GO
CREATE TABLE dbo.testnolock1
(id int not null IDENTITY (1,1) PRIMARY KEY,
text1 varchar(10) not null
)
GO
INSERT INTO dbo.testnolock1 (text1) VALUES (1);
GO

Итак, в таблице у нас имеется одна строка. Давайте начнем транзакцию для вставки другой строки, но не фиксируем её.

-- Соединение 1
BEGIN TRAN
INSERT INTO dbo.testnolock1 (text1) VALUES (2);

А для второй таблицы давайте выполним INSERT на базе оператора SELECT с табличным хинтом NOLOCK.

-- Соединение 2
DROP TABLE IF EXISTS dbo.testnolock2
GO
CREATE TABLE dbo.testnolock2
(id int not null IDENTITY (1,1) PRIMARY KEY,
text1 varchar(10) not null
)
GO
INSERT INTO testnolock2
SELECT TEXT1 FROM testnolock1 (NOLOCK)

Без хинта NOLOCK это будет блокироваться незафиксированным оператором INSERT в подключении 1.

С хинтом NOLOCK оператор INSERT во втором подключении сразу выполняется... однако вернемся к подключению 1:

-- Подключение 1
ROLLBACK TRAN

Что мы теперь имеем? На любом подключении:

SELECT * FROM testnolock1;
SELECT * FROM testnolock2;



В то время когда INSERT в testnolock1 откатывается (по одной из многих возможных ошибок или сбоев, не обязательно из-за ROLLBACK), INSERT с обреченной строкой, у которой text1=2, отлично отработал в testnolock2. Это плохо! Если на соединении 1 повторят свой INSERT, мы получили бы дублирующиеся данные, нарушение ограничения первичного ключа и т.п.

Если это кажется вам элементарным, отлично! У вас есть здоровое понимание и страх перед хаосом, который NOLOCK может посеять.

Обратные ссылки

Нет обратных ссылок

Комментарии

Показывать комментарии Как список | Древовидной структурой

Нет комментариев.

Автор не разрешил комментировать эту запись

Добавить комментарий

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Form options

Добавленные комментарии должны будут пройти модерацию прежде, чем будут показаны.