Найти тему

Что такое транзакция в базе данных? Как её правильно использовать?

Оглавление

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

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

Основное свойство транзакции заключается в том, что она либо выполняется полностью, либо не выполняется вовсе. Это означает, что если какая-то часть транзакции не может быть выполнена из-за ошибки или сбоя, все изменения, сделанные этой транзакцией, должны быть отменены. Это гарантирует, что данные в базе данных остаются в согласованном состоянии.

Ключевые свойства транзакций (ACID)

Для объяснения работы транзакций часто используется модель ACID, которая описывает четыре основные характеристики транзакций:

1. Atomicity (Атомарность):Транзакция должна быть выполнена полностью или не выполнена вообще. Если в процессе выполнения транзакции возникает ошибка, все изменения, которые были внесены этой транзакцией, отменяются (через механизм «отката», или rollback).
Пример: если вы переводите деньги с одного банковского счета на другой, то либо оба счета будут изменены (списание с одного и зачисление на другой), либо ни одно изменение не будет выполнено.

2. Consistency (Согласованность):Транзакция должна переводить базу данных из одного согласованного состояния в другое согласованное состояние. Это означает, что после завершения транзакции все правила целостности данных должны соблюдаться.
Пример: если транзакция переводит деньги с одного счета на другой, то после завершения транзакции сумма денег на обоих счетах должна быть корректной, и общий баланс должен оставаться неизменным.

3. Isolation (Изолированность):Транзакции, выполняющиеся параллельно, не должны влиять друг на друга. Каждая транзакция должна быть изолирована от других до тех пор, пока она не завершится. Это предотвращает ситуации, когда одна транзакция видит промежуточные (и, возможно, некорректные) результаты другой транзакции.
Пример: если два клиента одновременно снимают деньги с одного и того же банковского счета, изолированность транзакций гарантирует, что оба клиента не смогут одновременно изменить данные таким образом, чтобы баланс оказался некорректным.

4. Durability (Долговечность):После успешного завершения транзакции ее результаты должны быть постоянными, даже если происходит сбой системы. Это означает, что после выполнения команды commit (подтверждение транзакции) изменения сохраняются в базе данных навсегда.
Пример: если вы успешно завершили транзакцию по оплате товара в интернет-магазине, то даже в случае сбоя сервера после этого, данные о транзакции не будут потеряны.

Как работают транзакции?

Основные этапы транзакции:

1. Начало транзакции: Выполняется команда для старта транзакции. Она обозначает набор операций, который должен быть выполнен как единое целое.

2. Выполнение операций: Транзакция выполняет одну или несколько операций с базой данных (вставка, обновление, удаление и другие).

3. Подтверждение транзакции (Commit): Если все операции выполнены успешно, транзакция фиксируется, и все изменения становятся постоянными.

4. Откат транзакции (Rollback): Если в процессе выполнения транзакции возникает ошибка или сбой, все изменения, сделанные в рамках этой транзакции, отменяются, и база данных возвращается в исходное состояние.

Пример использования транзакции

Предположим, у нас есть банковская система, в которой происходит перевод денег с одного счета на другой. Этот процесс включает два этапа:

1. Списание денег с одного счета.

2. Зачисление денег на другой счет.

Правильное использование транзакции:

Что происходит при сбое?

Предположим, что после того, как с аккаунта 1 было списано 1000, произошел сбой перед зачислением этих денег на аккаунт 2. Если бы транзакция не использовалась, результат был бы некорректным — с одного аккаунта деньги уже списались, а на другой они не поступили. Однако, если вы используете транзакции, то в случае сбоя будет выполнен rollback, и оба аккаунта вернутся к исходному состоянию.

Пример отката:

-2

После выполнения команды ROLLBACK, деньги остаются на месте, и база данных возвращается в состояние, как будто транзакция не выполнялась.

Когда использовать транзакции?

Транзакции используются в следующих ситуациях:

1. Манипуляции с несколькими таблицами или несколькими строками данных: Транзакции гарантируют, что изменения будут выполнены только если все операции завершились успешно. Например, при перемещении данных между таблицами или при выполнении сложных обновлений в нескольких строках.

2. Критически важные операции: В системах, где данные имеют большое значение (например, банковские системы, системы учета и управления), транзакции обеспечивают целостность и согласованность данных.

3. Многопользовательские системы: В системах, где несколько пользователей могут одновременно модифицировать данные, транзакции предотвращают проблемы, связанные с конкурентным доступом (например, когда два пользователя пытаются изменить одну и ту же строку данных одновременно).

Заключение

Транзакции — это важный механизм обеспечения целостности и надежности данных в реляционных базах данных. Они позволяют гарантировать, что все операции, выполняемые в рамках одной транзакции, будут выполнены либо полностью, либо не будут выполнены вовсе. Это особенно важно в системах с высокой степенью параллелизма и критически важными данными.

После заключения. Инфо со звездочкой *.(Тестировщикам до уровня middle включительно можно не читать).

Уровни изоляции транзакций

Уровень изоляции транзакции определяет, насколько "изолированы" транзакции друг от друга при одновременной работе. В зависимости от уровня изоляции можно контролировать, какие данные одна транзакция может увидеть, пока другая транзакция не завершится. Это важно для предотвращения таких проблем, как "грязное чтение" (получение данных, которые еще не были зафиксированы), "неповторяющееся чтение" и "фантомные чтения".

Стандартные уровни изоляции (по стандарту SQL):

1. Read Uncommitted (Чтение неподтвержденных данных):

Наименее строгий уровень. Транзакция может видеть изменения, сделанные другими транзакциями, даже если те не завершены. Это может привести к "грязным чтениям".
Пример: Транзакция A обновляет строку, но не завершает изменения. Транзакция B читает это изменение, хотя оно еще не зафиксировано. Если транзакция A выполнит откат, то данные, которые прочитала транзакция B, окажутся недействительными.

2. Read Committed (Чтение подтвержденных данных):

Транзакция может видеть только те изменения, которые были зафиксированы другими транзакциями. Здесь исключены грязные чтения, но все еще возможны "неповторяющиеся чтения" — когда повторное чтение тех же данных в рамках одной транзакции может вернуть разные результаты.

3. Repeatable Read (Повторяемое чтение):

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

4. Serializable (Сериализуемость):

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

Пример проблемы "фантомного чтения":

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

Версионность и блокировки

Версионность (MVCC — Multi-Version Concurrency Control)

Некоторые СУБД, такие как PostgreSQL и Oracle, используют механизм MVCC (Multi-Version Concurrency Control) для управления параллелизмом. В отличие от блокировок, MVCC позволяет транзакциям работать с "версиями" данных, что увеличивает производительность при многопользовательских операциях.

  • Как работает MVCC:

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

  • Преимущества MVCC:

Чтение данных не блокируется, что повышает производительность при параллельной работе пользователей.
Чтения не мешают записям, и наоборот.

  • Недостатки MVCC:

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

Блокировки (Locking)

Другие СУБД, такие как MySQL (InnoDB) или Microsoft SQL Server, активно используют блокировки для управления параллельным доступом к данным. Существует два основных типа блокировок:

1. Блокировка на чтение (Shared Lock):Позволяет нескольким транзакциям одновременно читать данные, но запрещает изменять их до завершения чтения.

2. Блокировка на запись (Exclusive Lock):Запрещает другим транзакциям читать или изменять данные, пока транзакция, установившая блокировку, не завершится.

Пример блокировки:

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

Пример: Бэкап базы данных при параллельной работе пользователей

Теперь давай рассмотрим пример, который был упомянут в комментарии: бэкап базы данных при параллельной работе пользователей.

Для создания резервных копий базы данных без остановки работы системы используются механизмы снимков (snapshots) и логов изменений (WAL — Write-Ahead Logging).

Пример с PostgreSQL (MVCC):

  • В PostgreSQL бэкап можно создавать без остановки системы благодаря MVCC. Во время выполнения бэкапа транзакции продолжают работать, и база данных поддерживает "снимок" данных на момент начала бэкапа. Все изменения, сделанные после этого момента, не будут включены в бэкап, но будут зафиксированы в WAL (журнале изменений).Это гарантирует, что после восстановления из бэкапа база данных будет иметь целостное и согласованное состояние.

Пример с MySQL (InnoDB):

  • В MySQL (с использованием InnoDB) для создания бэкапа можно использовать специальные команды, такие как FLUSH TABLES WITH READ LOCK, которые блокируют доступ к таблицам для записи на время создания бэкапа. Однако это может привести к снижению производительности, если система активно используется.

Как правильно использовать транзакции?

Теперь давай ответим на главный вопрос: Как правильно использовать транзакции?

Ответ зависит от типа СУБД, требований к целостности данных и уровня изоляции, который нужен для конкретной задачи.

1. Выбор уровня изоляции:

Если ваша система требует максимальной производительности и может терпеть небольшие расхождения в данных, можно выбрать более низкий уровень изоляции, например Read Committed.
Если же критично избегать любых расхождений, используйте
Repeatable Read или Serializable, но будьте готовы к снижению производительности.

2. Работа с версионными СУБД:

В системах с MVCC (например, PostgreSQL), транзакции могут использовать версии данных, что минимизирует блокировки при параллельной работе. Однако важно учитывать, что MVCC может увеличивать использование диска, поэтому требуется регулярная очистка (в PostgreSQL это называется VACUUM).

3. Использование блокировок:

В системах, основанных на блокировках (например, MySQL InnoDB), важно контролировать продолжительность транзакций, чтобы избежать долгих блокировок, которые могут привести к снижению производительности при параллельной работе.

4. Резервное копирование:

Для создания резервных копий без остановки работы системы используйте механизмы снимков (например, в PostgreSQL) или журналы изменений (WAL). Это позволяет поддерживать целостность данных, даже если система активно используется.

Заключение 2

Транзакции — это мощный инструмент для обеспечения целостности данных, но их правильное использование зависит от конкретной СУБД, уровня изоляции, который вы выбираете, и требований вашей системы. Знание различий между механизмами версионности и блокировок, а также понимание разных уровней изоляции поможет вам эффективно управлять конкурентным доступом к данным и избежать проблем с целостностью и производительностью.

-3

Вместо оглавления. Что вы найдете на канале QA Helper - справочник тестировщика?

Не забудьте подписаться на канал, чтобы не пропустить полезную информацию: QA Helper - справочник тестировщика

Пишите в комментариях какой пункт было бы интересно рассмотреть более подробно.

Обязательно прочитайте: Что должен знать и уметь тестировщик

Также будет интересно почитать: Вопросы которые задают на собеседовании тестировщикам