Транзакции
Фиксируйте и отменяйте изменения
«Транзакции» — бесплатный урок Java Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.
Что такое транзакция
Транзакция объединяет несколько операций с базой данных в одну неделимую операцию, которая выполняется либо полностью, либо не выполняется вообще.
Либо каждый оператор завершается успешно, а изменения становятся постоянными (commit), либо происходит сбой и все изменения отменяются (rollback). Это сохраняет согласованность базы данных.
ACID за одну минуту
Транзакции обеспечивают гарантии ACID:
- Атомарность — всё или ничего.
- Согласованность — перевод базы данных из одного допустимого состояния в другое.
- Изоляция — параллельные транзакции не повреждают данные друг друга.
- Надёжность — после фиксации изменения сохраняются даже при сбое.
Режим автоматической фиксации
По умолчанию подключения JDBC работают в режиме автоматической фиксации: каждый оператор является отдельной транзакцией и фиксируется немедленно.
Для отдельных операторов это подходит, но бесполезно, когда несколько операций записи должны успешно выполниться вместе. Чтобы управлять транзакциями самостоятельно, отключите автоматическую фиксацию.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/bank";
try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
System.out.println("Default auto-commit: " + conn.getAutoCommit());
conn.setAutoCommit(false);
System.out.println("Now manual: " + conn.getAutoCommit());
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}Фиксация и откат
При отключённой автоматической фиксации Вы определяете границы транзакции:
conn.commit()делает все ожидающие изменения постоянными.conn.rollback()отменяет их.
Классический пример — перевод денег: со счёта нужно списать средства, а на другой счёт — зачислить. Должны произойти обе операции или ни одна.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/bank";
String debit = "UPDATE account SET balance = balance - ? WHERE id = ?";
String credit = "UPDATE account SET balance = balance + ? WHERE id = ?";
try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
conn.setAutoCommit(false);
try (PreparedStatement d = conn.prepareStatement(debit);
PreparedStatement c = conn.prepareStatement(credit)) {
d.setInt(1, 100); d.setInt(2, 1); d.executeUpdate();
c.setInt(1, 100); c.setInt(2, 2); c.executeUpdate();
conn.commit();
System.out.println("Transfer committed");
} catch (SQLException ex) {
conn.rollback();
System.out.println("Rolled back: " + ex.getMessage());
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}Шаблон отката при ошибке
Структура, которую нужно запомнить:
- Отключите автоматическую фиксацию.
- Выполните работу внутри вложенного блока
try. - При успехе вызовите
commit(). - В блоке
catchвызовитеrollback(), а затем повторно выбросьте исключение или запишите сведения в журнал.
Без отката сбой может оставить базу данных обновлённой лишь частично.
Моделирование атомарности
Вот как выглядит идея «всё или ничего», смоделированная на обычном Java, чтобы пример можно было запустить отдельно. Мы применяем два изменения к снимку состояния; если одно из них завершается ошибкой, восстанавливаем снимок.
public class Main {
public static void main(String[] args) {
int[] balances = {500, 300};
int[] backup = balances.clone();
try {
balances[0] -= 200;
if (balances[0] < 0) throw new IllegalStateException("insufficient funds");
balances[1] += 200;
System.out.println("Commit: " + balances[0] + ", " + balances[1]);
} catch (RuntimeException e) {
balances = backup;
System.out.println("Rollback: " + balances[0] + ", " + balances[1]);
}
}
}Точки сохранения
Точка сохранения — это маркер внутри транзакции. Вы можете выполнить откат к нему, не отменяя всю транзакцию.
Savepoint sp = conn.setSavepoint()conn.rollback(sp)отменяет только работу, выполненную после этой точки.
Это полезно для частичного восстановления в длинных транзакциях.
Уровни изоляции
Изоляция определяет, что одна транзакция видит из незаписанных изменений другой транзакции. JDBC задаёт уровни с помощью conn.setTransactionIsolation(...):
TRANSACTION_READ_COMMITTED— наиболее распространённый уровень по умолчанию.TRANSACTION_REPEATABLE_READTRANSACTION_SERIALIZABLE— самый строгий и самый медленный.
Более высокий уровень изоляции предотвращает аномалии, но снижает параллелизм.
Аномалии чтения
При более низком уровне изоляции возможны:
- Грязное чтение — просмотр незафиксированного изменения другой транзакции.
- Неповторяемое чтение — строка изменяется между двумя чтениями.
- Фантомное чтение — появляются новые строки, соответствующие предыдущему запросу.
Выбирайте минимальный уровень, который предотвращает аномалии, недопустимые для Вашей логики.
Восстановление автоматической фиксации
Если Вы взяли соединение из пула, восстановите его исходное состояние перед возвратом.
После ручной транзакции снова установите conn.setAutoCommit(true) (или верните значение, которое было получено при выдаче соединения), чтобы следующий пользователь не столкнулся с неожиданными настройками.
Делайте транзакции короткими
Транзакция удерживает блокировки до фиксации или отката. Длинные транзакции блокируют другую работу и повышают риск взаимной блокировки.
- Не выполняйте медленные сетевые вызовы и не запрашивайте действия пользователя внутри открытой транзакции.
- Сначала соберите данные, затем быстро откройте транзакцию, выполните запись и зафиксируйте изменения.
Короткие транзакции, посвящённые одной задаче, гораздо лучше масштабируются.
Быстрая проверка
Каков эффект вызова connection.rollback()?
Итоги
Транзакции обеспечивают безопасность по принципу «всё или ничего»:
- Отключайте автоматическую фиксацию с помощью
setAutoCommit(false). - При успехе вызывайте
commit(), а при ошибке —rollback(). - Используйте точки сохранения для частичного отката.
- Настраивайте уровни изоляции, чтобы уравновесить корректность и параллелизм.
- Восстанавливайте автоматическую фиксацию перед возвратом соединения в пул.
Часто задаваемые вопросы
Урок «Транзакции» бесплатный?
Да — полный текст урока «Транзакции» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.
Чему я научусь в уроке «Транзакции»?
Фиксируйте и отменяйте изменения Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Java Academy?
Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Транзакции»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Java Academy?
Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.