NHibernate - пессимистическая блокировка не работает - PullRequest
1 голос
/ 23 ноября 2010

Продолжение этого другого вопроса .

Я пытаюсь реализовать пессимистическую блокировку для проблемы параллелизма, как я описал в вопросе выше (пожалуйста, не стесняйтесь добавлять к этомуодин).Но это не работает для меня.

Я провожу очень простой тест: у меня работают два отдельных сайта, которые увеличивают счетчик в 500 раз.Я запускаю их одновременно.В конце концов, я ожидаю, что определенный столбец в моей таблице, как вы думаете, имеет значение 1000.

Вот код.Конечно, это не рабочий код, но тестовый код или нет, он все равно должен работать, верно?

for (int i = 0; i < 500; i++)
{
  var tx = this.userRepo.Session.BeginTransaction();
  var user = this.userRepo.GetById(42);
  user.Counter++;
  userRepo.Save(user);
  tx.Commit();
}

Метод GetById использует LockMode.Upgrade:

public T GetById(int id)
{
  T obj = Session.Get<T>(id, LockMode.Upgrade);
  return obj;
}

Теперь,используя NHProfiler, я вижу следующую инструкцию SQL:

SELECT Id FROM 'User' WHERE Id = 42 for update

, но в результате получается значение около 530 , так что примерно половина обновлений теряется из-запараллелизм.Что я делаю неправильно?Я отключил кэш второго уровня в этом тесте.Я использую неправильный режим блокировки?Должен ли я указать уровень изоляции?Что-нибудь еще?Заранее спасибо.

РЕДАКТИРОВАТЬ: Конфигурация FluentNhibernate:

Fluently.Configure()
.Database(MySQLConfiguration.Standard.ConnectionString(connectionstring))
.Mappings(m => assemblyTypes.Select(t => t.Assembly).ToList().ForEach(a => m.FluentMappings.AddFromAssembly(a)))
.ExposeConfiguration(c => c.Properties.Add("hbm2ddl.keywords", "none"));

1 Ответ

0 голосов
/ 23 ноября 2010

Чтобы LockMode.Upgrade работал, все транзакции должны быть включены в транзакцию, потому что LockMode.Upgrade блокирует ее в текущей транзакции.

Скорее всего, ваша проблема будет связана с утверждениямине включается в транзакцию.

Оптимистическая блокировка применяется не к одному оператору, а к нескольким транзакциям, которые отделены друг от друга.Пример:

  1. Начать транзакцию;

  2. Получить запись по Id = 42;

  3. Завершите транзакцию.

Затем, вне транзакции, увеличьте Counter.

После этого:

  1. Началотранзакция;

  2. Получить запись по Id = 42;

  3. Проверить, не изменился ли счетчик со значения, полученного в первой транзакции;

    а.Если он не изменился, обновите счетчик с увеличенным значением;

    b.Если оно изменилось, обработайте измененное значение.

  4. Завершение транзакции.

Оптимистическая блокировка означает, что вы "надеетесь" на Counterне изменился между двумя транзакциями и обработать случай, когда он изменился.С пессимистической блокировкой вы гарантируете, что все изменения сделаны в пределах одной транзакции с блокировкой всех необходимых записей.

Кстати: механизм проверки (изменилось ли Counter за это время) может автоматически обрабатываться NHibernate.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...