Что такое транзакция в базах данных и как это важно для тестирования?

«Что такое транзакция в базах данных и как это важно для тестирования?» — вопрос из категории Базы данных и SQL, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Транзакция — это атомарная и изолированная последовательность операций с базой данных, которая либо выполняется полностью (commit), либо полностью откатывается (rollback). Для тестирования понимание транзакций критично при проверке целостности данных и конкурентных сценариев.

Базовый пример SQL-транзакции:

BEGIN TRANSACTION; -- Начало транзакции

UPDATE accounts SET balance = balance - 100.00 WHERE user_id = 123; -- Списание
UPDATE accounts SET balance = balance + 100.00 WHERE user_id = 456; -- Зачисление

-- Если оба UPDATE прошли успешно:
COMMIT; -- Фиксация изменений в БД

-- Если на любом этапе произошла ошибка (например, недостаточно средств):
-- ROLLBACK; -- Откат всех изменений в рамках этой транзакции

Свойства ACID и их влияние на тестирование:

  1. Атомарность (Atomicity): "Все или ничего".

    • Что тестировать: Сценарии сбоя (отключение сети, падение сервера) в середине транзакции. Убедиться, что данные не остаются в частично измененном состоянии.
  2. Согласованность (Consistency): Транзакция переводит БД из одного валидного состояния в другое.

    • Что тестировать: Соблюдение бизнес-правил (CHECK-ограничения, внешние ключи). Например, нельзя перевести сумму, превышающую баланс.
  3. Изолированность (Isolation): Параллельные транзакции не должны влиять друг на друга.

    • Что тестировать: Конкурентный доступ. Классические проблемы:
      • "Грязное" чтение (Dirty Read): Чтение незакоммиченных данных другой транзакции. Тест: запустить две транзакции параллельно и проверить, видит ли вторая незавершенные изменения первой.
      • Неповторяющееся чтение (Non-repeatable Read): Повторное чтение одних и тех же данных в рамках одной транзакции дает разные результаты. Тест: прочитать строку, затем после ее изменения другой транзакцией, прочитать снова.
  4. Долговечность (Durability): После commit изменения сохраняются даже при сбое системы.

    • Что тестировать: Восстановление БД после сбоя. Убедиться, что закоммиченные перед падением данные не потеряны.

Практика для QA: При написании интеграционных или E2E-тестов часто необходимо очищать БД между тестами. Это удобно делать, оборачивая каждый тест в транзакцию, которая в конце откатывается:

// Пример на Java с Spring и JUnit 5
@SpringBootTest
@Transactional // Каждый тест выполняется в транзакции, которая откатывается после его завершения
class UserServiceIntegrationTest {

    @Test
    void createUser_ShouldPersistInDatabase() {
        User user = new User("alice");
        userRepository.save(user);

        assertThat(userRepository.findById(user.getId())).isPresent();
        // После завершения теста все изменения (сохранение пользователя) будут откачены.
        // Следующий тест начнется с чистой БД.
    }
}

Видео-ответы