Пакетное обновление: connection.commit () в самом конце, с setAutoCommit (false), но данные не откатываются - PullRequest
0 голосов
/ 27 февраля 2020

Мой Java JDB C вызов для Пакетного обновления структурирован как

conn.setAutoCommit(false);

for (int i = 0; i < items.size(); i++) {
    //...
    ps.addBatch();
}

ps.executeBatch();

// Suppose an exception happens right before a Commit
if (someCondition)
   throw new Exception("test");

conn.commit(); // Commit at the very end

Насколько я понимаю, когда это исключение случается, я никогда не достигал commit. Так что мои данные не должны быть сохранены, верно? Пока commit находится в самом конце и указывается setAutoCommit(false);, любые исключения не требуют отката?

Но я вижу, что данные действительно сохраняются , У меня вопрос почему? И мне нужен connection.rollback();? (Это с Postgres DB)

Ответы [ 2 ]

2 голосов
/ 27 февраля 2020

Пожалуйста, обратите внимание на уровни изоляции транзакций PostgreSQL:

https://www.postgresql.org/docs/9.5/transaction-iso.html

По умолчанию READ COMMITTED , который это хорошо для тебя.

Чтение «незафиксированных» изменений зависит от используемого вами соединения JDB C. Каждое соединение будет иметь различное «представление» данных в зависимости от уровня изоляции транзакции.

Рекомендуется при настройке

conn.setAutoCommit(false);

иметь успешный коммит и откат в Предложение catch:

conn.setAutoCommit(false);
try {
  ...
  ps.executeBatch();
  conn.commit();
} catch (Exception e) {
  conn.rollback();
}

Вызов ни фиксации, ни отката не оставит соединение открытым, а нагрузка на базу данных сохранится для сохранения незафиксированных изменений. Затем JVM через некоторое время закроет соединение, и база данных откатит все данные.

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

1 голос
/ 27 февраля 2020

Каждая транзакция должна быть завершена или завершена. Если у вас отключена автоматическая фиксация и вы не вызываете connection.commit(), тогда она не будет зафиксирована.

Любые исключения не требуют отката

Так что мои данные не должны не будет сохранено, верно?

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

Postgres использует многоверсионное управление параллелизмом, которое означает, что вставка, обновление и удаление по существу создают «версии» строк, а Postgres отслеживает в памяти, какие транзакции могут видеть, какие версии каких строк.

Так что же произойдет, если ваша транзакция не фиксирует и не прокручивает назад?

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

Всегда совершайте или откатывайте свои транзакции. Никогда не оставляйте их висящими.

Что произойдет, если вы никогда не совершите или не откатите транзакцию?

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

Всегда совершайте или откатывайте свои транзакции. Никогда не оставляйте их висящими.

Что это значит с точки зрения вашего кода?

Когда выбрасывается ваше исключение, стек вызовов раскручивается, перепрыгивая через коммит. Таким образом, ваша транзакция не будет зафиксирована. В зависимости от того, где вы ловите исключение, объект conn может находиться или не находиться в области видимости. Поймай это в объеме, чтобы ты мог откатиться. Почему? Потому что вы должны:

Всегда фиксировать или откатывать свои транзакции. Никогда не оставляйте их висящими.

...