2010-03-24 2 views
1

У меня есть веб-сайт, который используется всеми филиалами магазина, и что он делает, так это то, что он записывает покупки клиентов в таблицу с именем myTransactions.myTransactions, имеет столбец с именем SerialNumber. Для каждой покупки я создаю запись в таблице транзакций и назначаю ей серию. Хранимая процедура, которая выполняет это, вызывает функцию UDF, чтобы получить новый serialNumber перед вставкой записи. Как показано ниже:Уровень изоляции транзакции Serializable не работает для меня


Create Procedure mytransaction_Insert 
as begin 
insert into myTransactions(column1,column2,column3,...SerialNumber) 
values(Value1 ,Value2,Value3,...., getTransactionNSerialNumber()) 
end 

Create function getTransactionNSerialNumber 
as 
begin 
RETURN isnull(SELECT TOP (1) SerialNumber FROM myTransactions READUNCOMMITTED 
ORDER BY SerialNumber DESC),0) + 1 
end 

Сайт используется очень многими пользователями в разных магазинах в то же время, и это создает много повторяющихся serialNumbers (те же SerialNumbers). Таким образом, я добавил транзакцию Sql с уровнем ReadCommitted в транзакцию, и у меня остались дубликаты транзакций. Я изменил его на SERIALIZABLE, чтобы заблокировать ресурсы, и я получил не только дублированные номера транзакций (!! КАК !!), но я также получил спорадические взаимоблокировки между теми же вызовами хранимых процедур. Это то, что я пробовал: (С бездействием попытки уловом блоков и откатами)

Create Procedure mytransaction_Insert 
as begin 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 
BEGIN TRASNACTION ins 
insert into myTransactions(column1,column2,column3,...SerialNumber) 
values(Value1 ,Value2 , Value3, ...., getTransactionNSerialNumber()) 
COMMIT TRANSACTION ins 
SET TRANSACTION ISOLATION READCOMMITTED 
end 

Я даже скопировал функцию, которая получает серийный номер непосредственно в хранимой процедуру вместо вызова функции UDF и еще есть дублирующее serialNumbers. Итак, как строка хранимой процедуры создает что-то вроде блока C# lock() {}. Кстати, я должен реализовать серийный номер транзакции с использованием одного и того же шаблона, и я не могу изменить serialNumber в любое другое поле идентификации или что-то еще. И по некоторым причинам мне нужно сгенерировать serialNumber внутри базы данных, t переместите последовательность SerialNumber на уровень приложения.


Извините, но я уже пробовал это без READUNCOMMITTED в функции, и я все еще получаю дубликаты SerialNumbers.

Что касается столбца IDENTITY, я должен сказать, что это приложение будет использоваться другими компаниями, которым требуются разные SerialNumbers, и мы не можем просто изменить его на личность.

ответ

5

У вас есть READUNCOMMITTED в UDF. Это приведет к тому, что он будет игнорировать любые исключительные блокировки, удерживаемые другими транзакциями.

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE не совпадает с applock, это не «критический раздел» в базе данных, он просто контролирует поведение блокировки последующих операторов в транзакции.

Выньте READUNCOMMITTED, и он должен начать работать так, как вы ожидаете.

Конечно, это игнорирует тот факт, что вы существенно переделали столбец IDENTITY. Если ваши серийные номера действительно инкрементальны, вы должны выбросить все это и заменить его простым столбцом IDENTITY. Вы утверждаете, что вы «не можете», но не делаете никаких оправданий для этого утверждения; он выглядит как ты почти наверняка может.

+0

Спасибо за ссылку sp_getapplock. Я понятия не имел, что это существовало! – zvolkov

0

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

Но я бы сказал, что вы должны использовать столбец «Идентификация» (как сказано @Aaronaught) в SQL.Это начнется с того, что вы хотите, и увеличите вперед или назад. Если вам нужно, чтобы ваши заказы начинались с определенного номера, переместите его. Но если вам нужен идентификатор, который является уникальным, а также является целочисленным значением, используйте идентификатор.

Смежные вопросы