УРОВНИ ИЗОЛИРОВАННОСТИ ТРАНЗАКЦИЙ
Во многопользовательских системах с одной базой данных одновременно могут работать несколько пользователей или прикладных программ. Предельной задачей системы является обеспечение изолированности пользователей, т.е. создание достоверной и надежной иллюзии того, что каждый из пользователей работает с БД в одиночку.
В соответствии с требованиями сохранения целостности БД транзакции являются подходящими единицами изолированности пользователей. Действительно, если с каждым сеансом работы с базой данных ассоциируется одна или ряд транзакций то каждый пользователь начинает работу с согласованным (целостным) состоянием базы данных, т.е. с таким состоянием, в котором база данных могла бы находиться, даже если бы пользователь работал с ней в одиночку.
При соблюдении обязательного требования поддержания целостности базы данных возможны следующие нарушения (коллизии) изолированности пользователей и им соответствующие уровни изолированности транзакций
:•
Нулевой уровень - отсутствие потерянных изменений. Рассмотрим следующий сценарий совместного выполнения двух транзакций. Транзакция 1 изменяет объект базы данных A. До завершения транзакции 1 транзакция 2 также изменяет объект A. Транзакция 2 завершается оператором ROLLBACK (например, по причине нарушения ограничений целостности). Тогда при повторном чтении объекта A транзакция 1 не видит изменений этого объекта, произведенных ранее. Такая ситуация называется ситуацией потерянных изменений. Естественно, она противоречит требованию изолированности пользователей. Отсутствие потерянных изменений является минимальным требованием к СУБД по части синхронизации параллельно выполняемых транзакций.•Первый уровень - отсутствие чтения "грязных данных" (Dirty read). Рассмотрим следующий сценарий совместного выполнения транзакций 1 и 2. Транзакция 1 изменяет объект базы данных A. Параллельно с этим транзакция 2 читает объект A. Поскольку операция изменения еще не завершена, транзакция 2 видит несогласованные "грязные" данные (в частности, операция транзакции 1 может быть отвернута при проверке немедленно проверяемого ограничения целостности). Это тоже не соответствует требованию изолированности пользователей (каждый пользователь начинает свою транзакцию при согласованном состоянии базы данных и в праве ожидать видеть согласованные данные). Чтобы избежать ситуации чтения "грязных" данных, до завершения транзакции 1, изменившей объект A, никакая другая транзакция не должна читать объект A (минимальным требованием является блокировка чтения объекта A до завершения операции его изменения в транзакции 1).
•Второй уровень - отсутствие неповторяющихся чтений (Non-repetable read). Рассмотрим следующий сценарий. Транзакция 1 читает объект базы данных A. До завершения транзакции 1 транзакция 2 изменяет объект A и успешно завершается оператором COMMIT. Транзакция 1 повторно читает объект A и видит его измененное состояние.
Чтобы избежать потерянных изменений и неповторяющихся чтений, до завершения транзакции 1 никакая другая транзакция не должна изменять объект A. В большинстве систем это является максимальным требованием к синхронизации транзакций, хотя, как мы увидим немного позже, отсутствие неповторяющихся чтений еще не гарантирует реальной изолированности пользователей.
•К более тонким проблемам изолированности транзакций относится так называемая проблема кортежей-"фантомов" (Phanton row), вызывающая ситуации, которые также противоречат изолированности пользователей. Рассмотрим следующий сценарий. Транзакция 1 выполняет оператор A выборки кортежей отношения R с условием выборки S (т.е. выбирается часть кортежей отношения R, удовлетворяющих условию S). До завершения транзакции 1 транзакция 2 вставляет в отношение R новый кортеж r, удовлетворяющий условию S, и успешно завершается. Транзакция 1 повторно выполняет оператор A, и в результате появляется кортеж, который отсутствовал при первом выполнении оператора.
Конечно, такая ситуация противоречит идее изолированности
транзакций и может возникнуть даже на втором уровне изолированности транзакций. Чтобы избежать появления кортежей-фантомов, требуется более высокий "логический" уровень синхронизации транзакций. Идеи такой синхронизации (предикатные синхронизационные захваты) известны давно, но в большинстве систем не реализованы.В некоторых случаях коллизии, приведенные выше, не являются важными. Следовательно, нет необходимости запрещать все формы коллизий во всех случаях. Для этого разработчику клиентских приложений предоставлен контроль над уровнями блокировок.
Способ, по которому были сгруппированы команды SQL в транзакцию, может иметь значительное влияние на целостность данных. Если транзакция очень короткая и не содержит в себе полный логический блок, в базе данных могут возникнуть нарушения целостности. Если транзакция очень длинная и содержит в себе
несколько логических блоков, существует большая вероятность выполнения ROLLBACK. Также если транзакция очень длинная и блокирует большое количество данных, это может ограничить работу других транзакций.