Нужно ли явно коммитить транзакцию, если в ней выполняются только SELECT-запросы?

«Нужно ли явно коммитить транзакцию, если в ней выполняются только SELECT-запросы?» — вопрос из категории Базы данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, явный коммит (COMMIT) для транзакции, содержащей только SELECT, обычно не требуется, так как запросы на чтение не изменяют состояние базы данных.

Однако транзакция может быть полезна для SELECT в следующих случаях:

  1. Обеспечение согласованности данных: Установка уровня изоляции (например, REPEATABLE READ или SERIALIZABLE) гарантирует, что в рамках транзакции вы будете видеть непротиворечивый снимок данных.
  2. Чтение в рамках бизнес-операции: Если несколько SELECT должны видеть одни и те же данные (без изменений от других транзакций).

Практический пример на JDBC:

try (Connection conn = dataSource.getConnection()) {
    // Отключаем auto-commit для управления транзакцией вручную
    conn.setAutoCommit(false);
    // Устанавливаем уровень изоляции для согласованного чтения
    conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);

    try (Statement stmt = conn.createStatement()) {
        ResultSet rs = stmt.executeQuery("SELECT balance FROM accounts WHERE user_id = 1");
        // Обработка результата...
    }
    // Явный коммит не обязателен, но может быть выполнен
    // conn.commit();
    // При закрытии соединения без коммита произойдет неявный rollback,
    // что для SELECT безопасно.
}

Вывод: Транзакция для SELECT используется для контроля изоляции, а не для фиксации изменений. Явный COMMIT в этом случае опционален.