Уровень изоляции транзакции - PullRequest
6 голосов
/ 08 июля 2011

Я попытаюсь описать мою проблему в уровнях изоляции транзакций JPA.

Структура базы данных:

  • Table1 -> с PK, определенным как дата ('ddMMyyyy')
  • Table2 -> с FK в Table1

JPA (уровень изоляции :: read_commited) - код:

    Query query = em.createQuery("from Table1 trd where trd.id = :d");
    query.setParameter("d", date);

    Table1 t = null;
    try{
        t = (Table1) query.getSingleResult();
    }catch(javax.persistence.NoResultException e){
        t = null;
    }

    if(t==null){
        t=new Table1 (date);
        em.persist(trd);
    }

    for(Table2 q:tables2){
        q.setTable1(t);
        em.merge(q);
    }

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

  • Поток 1: Проверьте, существует ли сущность, представленная по дате, в базе данных
  • Поток 2: Сделайте точно так же

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

Есть ли возможность сохранить такую ​​ситуацию, кроме изменения уровня изоляции на SERIALIZABLE?

Ответы [ 2 ]

3 голосов
/ 08 июля 2011

Да, в целом уровень изоляции = SERIALIZABLE должен решить вашу проблему.Не стоит недооценивать побочные эффекты при изменении уровня изоляции на наиболее жесткий вариант.Это может повлиять на использование базы данных, а также на пропускную способность запроса.Может быть, вы можете явно зафиксировать свой TRX после создания T1, а затем открыть другой TRX: EntityManager.getTransaction (). Commit ()

Вам все еще нужно перехватить исключение дублирующегося ключа.

1 голос
/ 08 июля 2011

Это одна из самых сложных проблем, которые необходимо решить с базами данных в среде с высокой степенью параллелизма.В конце концов, ваше единственное реальное решение - поймать исключение и правильно с ним справиться.

Трудно сказать, что это может быть, основываясь на предоставленном вами коде.Если это веб-приложение, скорее всего, вы захотите перехватить исключение дубликата ключа и отобразить полезное сообщение для конечного пользователя.Например, «Эта запись уже создана» или что-то в этом роде.

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