Обработка транзакций

 

Транзакцией называются несколько последовательных операторов SQL, которые рассматриваются как единое целое. В транзакции каждый оператор решает часть общей задачи, но для того, чтобы задачу можно было считать решенной, требуется выполнить все эти операторы. Например, регистрация продажи товара может потребовать обновления таких полей разных таблиц, как общий доход, количество товара на складе, объем продаж определенного продавца и т. п. Операторы, входящие в транзакцию, рассматриваются как неделимое целое. Либо все операторы должны быть выполнены успешно, либо ни один из них не должен быть выполнен.

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

· COMMIT информирует СУБД о том, что транзакция успешно завершена и все изменения в БД должны быть зафиксированы;

· ROLLBACK (откат) сообщает о неуспешном окончании транзакции, и СУБД возвращает БД в состояние, в котором она находилась до выполнения транзакции.

По стандарту SQL транзакция автоматически начинается с выполнения первого оператора. Операторы COMMIT или ROLLBACK завершают текущую транзакцию. Новая транзакция начинается со следующего оператора. Успешное завершение программы эквивалентно выполнению оператора COMMIT, а неуспешное - оператора ROLLBACK.

Оператор ROLLBACK применяется в случае возвращения операторами SQL кодов ошибки либо при отказе пользователя от сделанных изменений.

В некоторых коммерческих СУБД предоставляют пользователям дополнительные возможности. Например, СУБД SQL Server позволяет создавать точки сохранения внутри транзакции и по оператору ROLLBACK возвращаться к указанной точке сохранения, что полезно в сложных транзакциях, состоящих из большого числа операторов. Такая возможность появилась и в стандарте SQL99.

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

В многопользовательском режиме транзакции могут нарушить целостность БД. Например, повторное чтение одной и той же записи может дать разные результаты, если эта запись была обновлена в промежуток времени между двумя обращениями к ней.

Основным механизмом обеспечения параллельной работы транзакций является блокировка. Существует два основных режима блокировки: разделяемая (SHARE) или монопольная (EXCLUSIVE). Разделяемая блокировка допускает парллельное чтение одних и тех же данных, но изменения запрещены. Монопольная блокировка позволяет приложению захватить блокируемую часть БД, не допуская доступ других приложений.

Блокировка может выполняться на уровне всей БД, таблицы, ее части и даже отдельных записей. В некоторых СУБД (DB2, SQL Server) пользователь может явно применять команды блокировки. В других СУБД и стандарте SQL блокировка выполняется автоматически, а пользователь может указать уровень изоляции транзакции, что позволяет обеспечить целостность данных и в то же время повысить производительность вычислений, не прибегая к полной блокировке БД или какой-либо ее таблицы.

Рассмотрим случаи нарушения целостности в многопользовательском режиме.

· Некорректное чтение.Допустим, что транзакция A обновила данные в некоторой строке, затем транзакция B считала эту строку, после чего бал выполнен откат транзакции A. В результате транзакция B будет работать с несуществующими данными.

· Неповторяемое чтение.Транзакция A считывает некоторую строку, затем транзакция B ее обновляет, после чего транзакция A снова считывает эту строку. В результае транзакция A считывает разные значения одной и той же строки.

· Чтение фантомов или строк-призраков.Транзакция A считывает множество строк по некоторому условию. Далее транзакция B вставляет новую строку, удовлетворяющую этому условию. Если транзакция A повторит выборку, то будет обнаружена ранее отсутствовавшая строка-фантом.

В SQL существуют четыре уровня изоляции транзакций, которые могут быть заданы оператором SET TRANSACTION

· SERIARIZABLE – полная изоляция транзакции от других;

· REPEATABLE READ – другие транзакции могут добавлять записи, но обновления запрещены;

· READ COMMITTED – текущей транзакции доступны окончательные результаты других транзакций, то есть другие транзакции могут добавлять и обновлять записи;

· READ UNCOMMITTED – текущей транзакции доступны как окончательные, так и промежуточные результаты других транзакций.

Уровень изоляции SERIARIZABLE защищает от всех трех возможностей нарушения целостности.

Уровень REPEATABLE READ реализуется путем установления блокировки на каждую считанную запись, допускает возможность некорректного чтения и подходит тогда, когда в пределах транзакции нет повторного многострочного чтения записей.

Уровень READ COMMITTED снимает блокировку на считанные записи, допускает возможности некорректного и неповторяемого чтения и используется тогда, когда в пределах транзакции нет повторного чтения одних и тех же записей.

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

По умолчанию в СУБД обычно устанавливается уровень изоляции SERIARIZABLE, а иногда уровень REPEATABLE READ.