Я работаю над переписыванием хранимой процедуры в SQL Server 2008, которая используется в процессе выставления счетов POS.Первый шаг - получить номер счета, который представляет собой автоматический поворот порядкового номера с добавленным префиксом.
По мере того, как количество одновременно работающих терминалов растет ~ 10-30, мы столкнулись с рядом проблем, таких как дублирование номера, блокировка блокировки.Оптимизация, над которой я сейчас работаю, получена из здесь , которая улучшена до расширенного (без дубликатов).Но когда я попытался протестировать с SQLQueryStress на основе этого предложения с использованием 10 итераций и 10 параллельных потоков, я увидел мертвую блокировку в нескольких тестах и непоследовательный сбой, получая префикс из той же таблицы дляпервая (несколько итераций)
Procudure имеет эти в настоящее время
- УСТАНОВИТЬ УРОВЕНЬ ИЗОЛЯЦИИ SERIALIZABLE
- получить префикс из той же таблицы с помощью (nolock)где type = @ type и Terminalid = @ Terminalid
- Начало Tran
- ОБНОВЛЕНИЕ Нумерация с (сериализуемым) SET @ nextval = следующий номер, следующий номер = следующий номер + 1
- если @@rowcount = 0 insert
- Commit tran
- output Префикс формата + @ nextval
Примечание, Этот фрагмент кода не будетИдеально, так как я собирался перестроить это.Это только часть кода if if, где else имеет один и тот же блок, повторяющийся с различным условием where (для четырех разных сценариев).
ALTER PROCEDURE [dbo].[GetnextNumberTest]
@transType varchar(50), --
@terminalaname varchar(50)='', --will be empty if it is not terminal wise
@nextvalue varchar(10) output
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
declare @ResetBasedOn int =0
,@Prefix varchar(50)=''
,@nextvalint int=0
select @ResetBasedOn=RestartOn,
@Prefix=((SELECT Prefix FROM TerminalMaster(nolock) WHERE TerminalName=@terminalaname)+'/'+ prefix)
from NumberingSchemeTest (nolock)
where TRSType= @transType
and (TerminalName=@terminalaname or TerminalName='') and active=1
if(@ResetBasedOn=0) --daily
begin
Begin Tran
UPDATE Numberingschemetest with (serializable)
SET @nextvalint=nextnumber,
--
nextnumber = nextnumber + 1
WHERE TRSType= @transType
and (TerminalName=@terminalaname or TerminalName='')
and yearlydate =convert(varchar, GETDATE())
and active=1
if @@rowcount = 0
begin
UPDATE Numberingschemetest with (serializable)
set active=0
where TRSType= @transType
and (TerminalName=@terminalaname or TerminalName='')
and yearlydate =convert(varchar, GETDATE() -1)
and active=1
insert into Numberingschemetest (
TRSType,
Prefix,
TPrefix,
TerminalName,
RestartOn,
YearlyDate,
StartingFrom,
NextNumber,
active,PreparedBy
)
(select top 1
TRSType,
Prefix,
TPrefix,
TerminalName,
RestartOn,
convert(varchar, GETDATE()),
StartingFrom,
StartingFrom+1,
1 ,@terminalaname
from Numberingschemetest
where TRSType= @transType
and (TerminalName=@terminalaname or TerminalName='')
and active=0 )
End
Commit Tran
if(@nextvalint=0)
set @nextvalue=@Prefix+'0001'
else
set @nextvalue =@Prefix+RIGHT('000'+ CAST(@nextvalint AS VARCHAR(50)),Case when LEN(@nextvalint)>4 then LEN(@nextvalint) else 4 end)
End
Все это основано на нескольких похожих вопросах с этого сайта,На этом этапе я мог думать только о двух вещах.Один разделит префикс на отдельную таблицу, а другой - попробовать другой инструмент для проведения нагрузочного тестирования.
Я могу понять, что будет некоторый компромисс, но хочу узнать лучший путь вперед.