Вложенные транзакции - сценарий отката - PullRequest
9 голосов
/ 24 сентября 2010
A(){
    con.begin;
    .........
    .........
    B();
    ........
    ........(con.rollback;)
    con.commit;
    }

    B{
    con.begin;
    .......
    .......
    con.commit;
    }

В приведенном выше коде я начинаю новую транзакцию БД в точке A ().Он выполняет некоторые транзакции успешно.После этого B () начинает выполнение, а также успешно выполняет некоторую транзакцию, и теперь управление возвращается к A ().На этом этапе происходит какое-то исключение, и я делаю откат.Я хотел бы знать, будет ли откат транзакции, которая преуспела в B (), или нет.

Ответы [ 4 ]

11 голосов
/ 24 сентября 2010

Краткий ответ, нет. Длинный ответ выглядит следующим образом.

Поддержка вложенных транзакций в Java зависит от различных переменных в игре.

Поддержка вложенных транзакций в JTA

Прежде всего, если вы используете JTA, дело за Менеджером транзакций для поддержки вложенных транзакций. Любая попытка начать транзакцию может привести к возникновению исключения NotSupportedException диспетчером транзакций (который не поддерживает вложенные транзакции), если попытка запустить новую транзакцию в потоке, который уже связан с транзакцией.

Из спецификации Java Transaction API 1.1:

3.2.1 Начало транзакции

Запускается метод TransactionManager.begin глобальная транзакция и партнеры контекст транзакции с вызывающая тема. Если сделка Менеджер реализации не поддержка вложенных транзакций, TransactionManager.begin метод Throwsthe NotSupportedException когда вызывающий поток уже связанный с транзакцией.

Поддержка вложенных транзакций в JDBC

JDBC 3.0 представляет класс Savepoint , который более или менее похож на концепцию точек сохранения в базе данных. Точки сохранения должны быть инициализированы с использованием метода Connection.setSavepoint () , который возвращает экземпляр точки сохранения. Откат к этой точке сохранения можно выполнить позднее, используя метод Connection.rollback (Savepoint svpt) . Все это, конечно, зависит от того, используете ли вы драйвер, совместимый с JDBC 3.0, который поддерживает установку точек сохранения и откат к ним.

Влияние автоматической фиксации

По умолчанию все полученные подключения устанавливаются на автоматическую фиксацию, если только драйвер JDBC не обнаружил явного отклонения на этом фронте. Если эта функция включена, она автоматически исключает объем вложенных транзакций, поскольку все изменения, внесенные в базу данных через соединение, автоматически фиксируются при выполнении.

Если отключить функцию автоматической фиксации и выбрать явную фиксацию и откат транзакций, то фиксация транзакции всегда фиксирует все изменения, выполненные соединением, до этого момента времени. Обратите внимание, что изменения, выбранные для фиксации, не могут быть определены программистом - все изменения до этого момента выбираются для фиксации, независимо от того, были ли они выполнены тем или иным способом. Единственный выход - определить точки сохранения или взломать свой путь мимо драйвера JDBC - драйвер обычно фиксирует все изменения, выполненные соединением, связанным с потоком, поэтому запуск нового потока (это плохо) и получение нового соединения в нем часто дает новый контекст транзакции.

Возможно, вы также захотите проверить, как ваша платформа предлагает поддержку вложенных транзакций, особенно если вы изолированы от JDBC API или от запуска новых транзакций JTA самостоятельно.


На основании приведенного выше описания того, как поддержка вложенных транзакций может быть достигнута в различных сценариях, представляется, что откат в вашем коде откатит все изменения, связанные с объектом Connection.

0 голосов
/ 03 мая 2012

Вы можете использовать встроенную в Java.SQL функцию SavePoint в Postgres 8 и выше.

Connection conn = null;
Savepoint save = null;
DatabaseManager mgr = DatabaseManager.getInstance();
try {
    conn = mgr.getConnection();
    proc = conn.prepareCall("{ call writeStuff(?, ?) }");

    //Set DB parameters
    proc.setInt(1, stuffToSave);
    proc.setString(2, moreStuff);

    //Set savepoint here:
    save = conn.setSavepoint();

    //Try to execute the query
    proc.execute();

    //Release the savepoint, otherwise buffer memory will be eaten
    conn.releaseSavepoint(save);

} catch (SQLException e) {
    //You may want to log the first one only.
    //This block will attempt to rollback
    try {
        //Rollback to the Savepoint of prior transaction:
        conn.rollback(save);
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}

Когда возникает исключение SQL, текущая транзакция откатывается до SavePoint, а остальныетранзакции могут произойти.Без отката последующие транзакции не будут выполнены.

0 голосов
/ 24 сентября 2010

Согласно вашему коду, в A () вы начинаете транзакцию. Затем перейдите к B (), где вы снова начинаете транзакцию, которая, в свою очередь, передаст все предыдущие транзакции. Затем в конце B () транзакция явно фиксируется. На данный момент весь ваш код зафиксирован. Теперь код возвращается к A () и остальной код обрабатывается. В случае исключения будет выполнен откат только этой части после вызова B ().

0 голосов
/ 24 сентября 2010

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


A()
{
 //business code A
 B();
 //more business code A
}

B()
{
  //business code B
}

DoA()
{
  try
  {
     con.begin();
     A();
     con.commit();
  }
  catch(Exception e)
  {
     con.rollback();
  }
}

DoB()
{
  try
  {
     con.begin();
     B();
     con.commit();
  }
  catch(Exception e)
  {
     con.rollback();
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...