Спящий режим и несколько потоков, синхронизация изменений между несколькими пользователями

Я использую Hibernate в приложении Eclipse RAP. У меня есть таблицы базы данных, сопоставленные с классами с помощью Hibernate, и эти классы имеют свойства, которые извлекаются лениво (если бы они не извлекались лениво, я, вероятно, в конечном итоге загрузил бы всю базу данных в память при первом запросе). Я не синхронизирую доступ к базе данных, поэтому для пользователей существует несколько Hibernate Sessions, и пусть СУБД выполняет изоляцию транзакций. Это означает, что разные экземпляры извлеченных данных будут принадлежать разным пользователям. Есть вещи, которые, если пользователь изменит эти вещи, я хотел бы обновить их для нескольких пользователей. В настоящее время я думаю об использовании Hibernate session.refresh(object) в этих случаях для обновления данных, но я не уверен, как это повлияет на производительность при обновлении нескольких объектов и правильно ли это.

Надеюсь, моя проблема ясна. В порядке ли мой подход к проблеме, или он в корне ошибочен, или я что-то упускаю? Есть ли общее решение для такой проблемы?

Буду признателен за любые комментарии по этому поводу.


person SolidSun    schedule 20.11.2011    source источник


Ответы (2)


Общее решение

  • чтобы транзакции были как можно короче
  • чтобы связать жизненный цикл сеанса с жизненным циклом транзакции (по умолчанию: сеанс закрывается, когда транзакция фиксируется или откатывается)
  • использовать оптимистичный параллелизм блокировки, чтобы избежать одновременного обновления одного и того же объекта двумя транзакциями.

Если каждая транзакция очень короткая и транзакция A обновляет какой-либо объект с O на O', то параллельная транзакция B будет видеть только O, пока не зафиксирует или не откатится, а любая другая транзакция, начатая после A, увидит O', потому что начинается новый сеанс с транзакцией.

person JB Nizet    schedule 21.11.2011

Мы поддерживаем приложение, которое делает именно то, что вы пытаетесь выполнить. Да, каждый сеанс session.refresh() будет обращаться к базе данных, но поскольку все сеансы будут обновлять одну и ту же строку одновременно, сервер БД будет отвечать на все эти запросы из памяти.

Единственное, что вам еще нужно решить, это как распространить информацию о том, что что-то изменилось и требует перезагрузки, на все остальные сеансы, возможно, даже на сеансы на другом хосте.

Для нашего приложения у нас есть около 30 пользователей на RCP и 10-100 пользователей на экземплярах RAP, которые все подключаются к одному и тому же серверу БД (хотя и через pgpool). Мы используем небольшую сетевую службу, к которой подключается каждая среда выполнения; когда транзакция фиксируется, приложение сообщает этой службе изменений, что «идентификатор строки X таблицы T» изменился, и затем это распространяется на всех других «подписчиков на изменения», даже между JVM.

Но: убедитесь, что session.refresh() вызывается в потоке, принадлежащем этому сеансу, возможно, в потоке RAP-Display. Не вызывайте refresh() из Jobs или других несвязанных потоков.

Пока у вас нет большого количества пользователей, обновляющих большое количество строк за короткое время, я думаю, вам не придется беспокоиться о производительности.

person Hannes Erven    schedule 15.01.2013