SQL Server — вставка нескольких процессов в таблицу

У меня есть несколько хранимых процедур (Добавить и удалить), которые выполняют выборку, вставку, удаление и обновление некоторых таблиц. Эти кажутся прекрасными.

Каждый из этих процессов использует ТРАНЗАКЦИЮ. Я начинаю транзакцию до того, как внесу какие-либо изменения в данные, и ближе к концу процесса я это делаю.

IF @@TRANSCCOUNT > 0
  COMMIT TRANSACTION @transName;

В процедурах добавления и удаления и в ТРАНЗАКЦИИ я вызываю другую хранимую процедуру (Adjust) для обновления таблицы, в которой хранится текущий итог значений. Я нахожу, что это выходит из синхронизации .....

Вот тело этого процесса....

  INSERT INTO L2(ProductId, LocationId, POId, StockMoveId, BasketId, OrderId, AdjusterValue, CurrentValue)
    SELECT TOP 1 
      @ProductId, @LocationId, null, null, @BasketId, null, @Value, (CurrentValue + @Value)
    FROM L2
    WHERE 1=1
      AND LocationId = @LocationId
      AND ProductId = @ProductId
    ORDER BY Id Desc

ProductId, LocationId, StockMoveId и OrderId — все это внешние ключи к соответствующим таблицам, но они допускают нули, поэтому только соответствующий ключ необходимо заполнить фактическим значением.

Вот изображение, показывающее пример того, где что-то идет не так.... Изображение, показывающее проблем

19 должны были быть добавлены к 324, чтобы получить новое общее количество 343, однако, как вы можете видеть, кажется, что оно было добавлено к 300, а 319 вставлено.

Вопросы... Действительно ли это в транзакции, которая была начата в вызывающей хранимой процедуре.

Как я могу предотвратить эту ситуацию?

Я пытался использовать MAX, чтобы получить правильную строку, чтобы попробовать и ускорить, но план выполнения для этого не так эффективен с точки зрения затрат, как простой TOP. ID, кстати, это столбец Identity и PKey.

Нужно ли мне заблокировать таблицу, и если я это сделаю с другим процессом, вызывающим Adjust, подождите, или они будут ошибаться.

Любая помощь высоко ценится.

Дополнительная информация.... Я экспериментировал, и, похоже, единственное решение, которое постоянно работает так, как хотелось бы, - это иметь столбец Id в качестве поля INT и просто увеличивать его самостоятельно при INSERT. Меня это не устраивает, так как мне не понятно, почему столбец IDENTITY n не справляется.

Я сам пробовал опубликованное решение столбца Identity, последовательности и увеличивающийся идентификатор.


person AntDC    schedule 10.12.2015    source источник


Ответы (1)


После долгих поисков и экспериментов мне кажется, что у меня есть решение, которое теперь очень надежно. Теперь у меня есть идентификатор в виде простого столбца INT, и я сам управляю идентификатором, получая MAX + 1 для каждой новой вставки.

Теперь я оборачиваю тело процедуры Adjust в свою собственную транзакцию и использую следующее, чтобы получить следующий идентификатор.....

  DECLARE @trxNam Varchar(10) = 'tranNextId';
  DECLARE @newId INT;
  DECLARE @currentLevelId INT;
  BEGIN TRANSACTION @trxNam;
  SELECT @newId = MAX(id) + 1 FROM L2 WITH(updlock,serializable);

Затем я делаю свою вставку, используя @newId, и СОВЕРШАЮ названную транзакцию. У меня есть сценарий, в котором у меня есть несколько Win32Apps, вызывающих мой API 100 раз, которые постоянно терпят неудачу из-за периодических нарушений PKEY. Теперь это не так.

Счастливые дни! Тем не менее, я смотрю, могу ли я просто снова иметь столбец идентификаторов и использовать транзакцию в процедуре настройки ... Я думаю, это было бы чище.

Эта статья привела меня к решению...

person AntDC    schedule 16.12.2015
comment
Нет, идентификация по-прежнему не синхронизируется, поэтому я придерживаюсь вышеизложенного, которое постоянно работает, как и ожидалось. Я просто нахожу все это немного странным, что Личность не может с этим справиться. - person AntDC; 16.12.2015