NHibernate: выберите значение MAX одновременно

Предположим, мне нужно выбрать максимальное значение в качестве номера заказа. Таким образом, я выберу MAX(число), назначу номер заказу и сохраню изменения в базе данных. Тем не менее, как я могу помешать другим возиться с номером? Подойдут ли транзакции? Что-то вроде:

     ordersRepository.StartTransaction();
     order.Number = ordersRepository.GetMaxNumber() + 1;
     ordersRepository.Commit();

Будет ли приведенный выше код «блокировки» изменен, чтобы номера заказов читались/записывались только одним клиентом БД? Учитывая, что транзакции являются простыми NHibernate, а GetMaxNumber просто выполняет SELECT MAX(Number) FROM Orders.


person queen3    schedule 04.12.2009    source источник


Ответы (1)


Использование ITransaction с IsolationLevel.Serializable должно помочь. Однако будьте осторожны с разногласиями за столом. Если у вас есть высокочастотные обновления на столе, все может сильно замедлиться. Возможно, вы захотите профилировать попадание в базу данных при использовании GetMaxNumber().

Мне пришлось сделать что-то подобное, чтобы сгенерировать пользовательские идентификаторы для высокой степени параллелизма. Мое решение переместило генерацию идентификатора в базу данных и использовало отдельную таблицу Counter для хранения максимальных значений.

Использование отдельной таблицы Counter имеет несколько плюсов:

  • Удаляет конкуренцию за таблицу Order
  • Обычно это быстрее
  • Если он достаточно мал, его можно закрепить в памяти.

Я также использовал хранимую процедуру для возврата следующего доступного идентификатора:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
  UPDATE [COUNTER] SET Value = Value + 1 WHERE COUNTER_ID = @counterId
COMMIT TRAN

RETURN [NEW_VALUE]

Надеюсь, это поможет.

person Vijay Patel    schedule 05.12.2009