У меня есть таблица, которая выглядит, как этотПопытка заблокировать базу данных, но не работает
Create Table Items(
[Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[UniqueCol] [nvarchar](20) NOT NULL,
[Col] int NOT NULL
)
ALTER TABLE Items ADD CONSTRAINT UN_UniqueCol UNIQUE(UniqueCol)
У меня есть хранимая процедура в SQL Server 2008, который выглядит следующим образом.
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION
if not exists(select * from Items where UniqueCol=uniqueval)
begin
insert into Items (UniqueCol, Col) values (uniqueval, val)
end
select * from Items where UniqueCol = uniqueval
COMMIT TRANSACTION
EDIT: Это Merge работает правильно
MERGE INTO Items as Target USING (VALUES(uniqueval)) as source (UniqueCol)
on (source.UniqueCol = Target.UniqueCol)
WHEN MATCHED THEN
update set col = val
WHEN NOT MATCHED BY Target THEN
insert (UniqueCol, col) VALUES (uniqueval, val);
Я бегу веб-сайт в ASP.NET MVC, снимающей эту процедуру очень часто. Причина, по которой я делаю это в хранимой процедуре, - это то, что я считал, что это самое простое место для обработки проблем параллелизма, которые возникали, когда две вещи пытались вставить одну и ту же вещь одновременно.
Выбор в конце как-то возвращает значение моей модели в asp.net mvc. Я не уверен, что это правильный способ сделать это, но он работает, когда я пытаюсь вызвать хранимую процедуру с веб-сервера.
Эта хранимая процедура вызывается очень часто и потенциально имеет 2 одинаковой вещи в в то же время. Уникальный ключ предотвращает хранение плохих данных, но я бы не захотел зафиксировать и исключить уникальное ключевое исключение для обработки параллельных вставок, когда они происходят. Могу ли я заблокировать таблицу, не убивая производительность здесь?
Я предполагал, что это заблокирует Элементы, чтобы 2 запроса не могли попытаться вставить в него одновременно (и вызвать дублирование идентификатора), и они не могли попытаться вставить одно и то же значение в таблицу дважды (2 ряда с UniqueCol = uniqueval)
Я делаю это неразумно? Я просто пытался несколько раз вызвать этот хранимый процесс параллельно, и один из них дал мне сообщение о том, что произошло дублирование ПК.
Похоже, что уровень изоляции транзакций не предназначен для блокировки таблиц таким образом. Может ли кто-то объяснить, для чего он предназначен, а также правильный способ блокировки таблицы для этого типа транзакций?
Я бы ожидал, что «Id» будет объявлен первичным ключом. –
о, извините, но. Я забыл поместить это. – bdwain
Команда 'INSERT' ** только ** блокирует строки (строки), которые она свежая вставка - ничего больше. Он не блокирует всю таблицу - и это хорошая вещь *! В противном случае производительность пострадает ужасно .... –