Главное меню

EN | RU | UK

На главную

9. Трансакции

Наверх страницы
Лекция
Цель

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

9.1. Проблемы, возникающие при внесении изменений в БД

Для локальных СУБД (Paradox, dbase и т.д.) характерен подход немедленного отображения изменений. Отказаться от модификации данных в этом случае невозможно, поскольку изменения уже физически внесены в БД. Однако, удаленную запись можно ввести снова вручную. Или другой вариант: удаленые записи можно хранить в некотором промежуточном (временном) отношении БД. Если возникла необходимость отказаться от удаления записей, то их можно переместить из временного хранилища в то отношение, из которого они были изъяты.

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

Классическим примером перехода БД является бухгалтерская проводка: некоторая сумма средств S должна быть списана с одного счета К и зачислена на другой - D. Только успешное выполнение этих двух операций гарантирует целостность информации в БД. Но целостность будет нарушена, если в результате сбоя сумма S будет списана со счета К, но не будет зачислена на счет D или, наоборот, зачислена на D, но не списана с К. Поэтому в случае ошибки списания/зачисления суммы результаты предыдущей операции зачисления/списания должны быть отменены. Иначе говоря, бухгалтерская проводка состоит из группы элементарных операций: списание со счета К суммы средств S, зачисление суммы средств S на счет D.

Существуют механизмы отката изменений в БД, если условия успешного завершения всех элементарных операций, входящих в состав группы, не выполнены. Основным механизмов является обработка трансакций [2, 4, 6, 7]. Конечно обработка транзакций реализуется в промышленных БД. Однако ряд средств разработки приложений [5] позволяют управлять транзакциями и для таблиц локальных СУБД (Paradox, dbase). Кроме того, как для промышленных, так и локальных систем, предоставляется дополнительный механизм управления откатами изменений в БД - так называемые кэшированные изменения (cached updates, что чаще всего переводят как буферизированная изменения).

9.2. Определение и свойства транзакции

Трансакция - это действие или серия действий, выполняемых одним пользователем или приложением с целью доступа к данным или изменения содержимого БД [4].

Транзакция является логической единицей работы, выполняемой в БД. Она может быть представлена отдельной программой, быть частью алгоритма программы или даже отдельной командой (например, INSERT или UPDATE) и включать любое количество операций, выполняемых в БД. С точки зрения БД, выполнение приложения может расцениваться как серия трансакций, в промежутках между которыми обрабатываются данные за пределами БД.

Любая транзакция всегда должна переводить БД из одного согласованного состояния в другое, хотя предполагается, что согласованность ее состояния будет нарушаться в ходе выполнения транзакции. Поэтому, любая транзакция завершается одним из двух возможных способов. В случае успешного завершения ее результаты фиксируются (commit ) в БД, и она переходит в новое согласованное состояние. Если выполнение транзакции не увенчалось успехом, она отменяется (rollback). Тогда в БД должен быть восстановлено то согласованное состояние, в котором она находилась до начала данной транзакции. Этот процесс называется откатом (rollback) транзакции. Зафиксированная трансакция не может быть отменена. Если окажется, что зафиксирована транзакция была ошибочной, то нужно выполнить другую транзакцию, отменяющую её действия. Такую трансакцию называют компенсирующей. Следует отметить, что отменена трансакция может быть еще раз запущена позже и, в зависимости от причин предыдущего отказа, вполне успешно завершена и зафиксирована в БД.

Никакая СУБД не имеет внутренней возможности установить, какие именно изменения должны быть восприняты как единое целое, которое образует одну логическую операцию. Поэтому существует метод, позволяющий указывать извне границы каждой из транзакций, со стороны пользователя. В большинстве языков манипулирования данными для определения границ отдельных трансакций используются операторы BEGIN TRANSACTION, COMMIT и ROLLBACK (или их эквиваленты). Если они не были использованы, то все действия программы, которые выполняли изменения в БД, расцениваются как единственная транзакция. СУБД автоматически выполнит команду COMMIT, если программа успешно завершена. В противном случае СУБД автоматически выполняет команду ROLLBACK.

Существуют четыре основные свойства транзакции (ACID - аббревиатура, составленная из первых букв их английских названий).

Атомарность. Это свойство типа «все или ничего». Любая транзакция представляет собой неделимую единицу работы, которая может быть либо выполнена вся целиком, либо не выполнена совсем.

Согласованность. Каждая транзакция должна переводить БД из одного согласованного состояния в другое согласованное состояние.

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

Продолжительность. Результаты успешно завершенной (зафиксированной) транзакции должны храниться в БД постоянно и не должны быть утеряны в результате последующих сбоев.

9.3. Уровни изоляции транзакций: приложение клиента

9.3.1. Проблемы одновременного изменения данных

Проблемы одновременного изменения данных возникают при синхронной работе нескольких клиентов с одним отношением. Пусть пользователь А получил данные из отношения Books и впоследствии изменил их. В это время с той же строкой отношения Books работает пользователь В. Он также модифицировал данные в тойже же записи, что и А, и пытается подтвердить эти изменения. Пользователь С работает с отношением Books в режиме чтения. Сразу же возникает ряд вопросов: разрешать или не разрешать пользователю В изменять запись, если А еще не подтвердил свои изменения? Или позволить С видеть изменения, внесенные А и В? Может ли пользователь А видеть изменения, внесенные В, и наоборот?

Для решения указанных проблем существует несколько уровней изоляции (разграничения) трансакций: Dirty Read, Read Committed, Repeatable Read. Уровень изоляции транзакции определяет:

могут ли другие (конкурирующие) транзакции вносить изменения в данные, измененные текущей транзакцией;

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

9.3.2. Уровень изоляции транзакции Dirty Read

Уровень изоляции транзакции Dirty Read позволяет конкурирующим транзакциям видеть изменения, внесенные но неподтвержденные текущей транзакцией. Если текущая транзакция отменит сделанные изменения, другие транзакции будут видеть недостоверные данные. Этот уровень изоляции может привести к значительным ошибкам и применяется мало.

9.3.3. Уровень изоляции транзакции Read Committed

Уровень изоляции транзакции Read Committed позволяет конкурирующим транзакциям оперировать только подтвержденными изменениями, которые сделаны в текущей транзакции.

9.3.3.1. Чтение данных

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

Возможен и другой вариант. Пусть трансакция А вносит изменения в данные некоторого отношения и не подтверждает их. В это время стартует трансакция В в приложении, где открыто отношение, в котором транзакция А изменяет данные. Тогда попытка инициализации транзакции В будет отклонена. Открыть набор данных клиент сможет только после того, как транзакция А подтвердит сделанные изменения.

9.3.3.2. Изменение данных

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

9.3.4. Уровень изоляции транзакции Repeatable Read

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

9.3.4.1. Чтение данных

Пусть трансакция А открыла набор данных. После этого транзакция В внесла в те же данные изменения и не подтвердила их. Тогда при повторном открытии набора данных трансакция А получит данные в том состоянии, в котором они находились в момент ее старта. Однако «свои» изменения трансакция А видеть будет. Пусть трансакция В подтвердила сделанные ею изменения, а транзакция А вновь открыла набор данных. И в этом случае транзакция А получит данные в том состоянии, в котором они находились в момент ее старта.

9.3.4.2. Изменение данных

Пусть трансакция А внесла изменения в данные и не подтвердила их. Транзакция В после этого также внесла изменения в те же данные. Тогда попытка транзакции В подтвердить внесенные ею изменения будет отклонена.

9.3.5. Определение уровня изоляции транзакций

Определение уровня изоляции транзакций в приложении клиента зависит от среды разработки. Например, в приложениях, написанных в среде Delphi или C-Bilder, уровень изоляции транзакций определяется свойством компонента Tdatabase – property Translsolation: Ttranslsolation. Возможные значения: tiDirtyRead, tiReadCommitted, tiRepeatableRead. Различные серверы БД по-разному интерпретируют уровни изоляции транзакций, определенных в свойстве Translsolation (табл. 9.1).

Таблица 9.1

Интерпретация уровней изоляции транзакций, определенных в свойстве Translsolation
Сервер Уровень транзакции Интерпретируется как
Oracle tidirtyread
tireadcommitted
tirepeatableread
tireadcommitted
tireadcommitted
tirepeatableread (Только для чтения)
Sybase, MS-SQL tidirtyread
tireadcommitted
tirepeatableread
tireadcommitted
tireadcommitted
He поддерживается
DB2, Informix, Interbase tidirtyread
tireadcommitted
tirepeatableread
tidirtyread
tireadcommitted
tirepeatableread
Paradox, dbase tidirtyread
tireadcommitted
tirepeatableread
tidirtyread
He поддерживается
He поддерживается

9.4. Управление транзакциями на стороне SQL-сервера InterВase

InterВase управляет транзакциями с помощью SQL-операторов SET TRANSACTION (начать транзакцию), COMMIT (подтвердить транзакцию) и ROLLBACK, (откатить транзакцию). Оператор SET TRANSACTION имеет такой формат [10, 14, 15]:

SET TRANSACTION [READ WRITE | READ ONLY]

    [WAIT | NO WAIT]

    [[ISOLATION LEVEL] {SNAPSHOT [TABLE STABILITY] | READ COMMITTED [[NORECORD_VERSION]}]

    [RESERVING  <список таблиц>

    [FOR [SHARKD | PROTECTED] [READ | WRITE]], [<список таблиц> ...].

READ WRITE | READ ONLY устанавливает уровень доступа к данным (по умолчанию READ WRITE);

WAIT | NO WAIT определяет поведение SQL-сервер при возникновении конфликта восстановления записи данной трансакции с другой сделкой, ранее внесла изменение в том же записи: WAIT (по умолчанию) заставляет эту трансакцию ожидать завершения конкурирующей транзакции; NO WAIT определяет аварийное завершение данной сделки;

ISOLATION LEVEL определяет уровни изоляции транзакций на сервере (по умолчанию SNAPSHOT);

RESERVING в рамках данной транзакции обеспечивает монопольный доступ к таблицам, приведенным в одном или нескольких списках. В последнем случае каждому элементу списка таблиц соответствуют следующие параметры:

PROTECTED READ - конкурирующие транзакции могут читать данные, но не могут изменять их;

PROTECTED WRITE - читать данные могут только транзакции с уровнями SNAPSHOT или READ COMMITTED и никакая конкурирующая транзакция не может их менять.

Стандарт ISO включает определение модели транзакций, построенной на базе двух специальных операторов - COMMIT и ROLLBACK. Большинство коммерческих реализаций языка SQL, в том числе и InterВase, поддерживают эту модель, которая впервые была реализована в СУБД DB2 компанией IBM. В стандарте указывается, что в языке SQL транзакция автоматически запускается любым SQL-оператором или программой (например, SELECT, INSERT или UPDATE). Изменения, внесенные в БД при выполнении данной транзакции, будут недоступны любым другим транзакциям, которые выполняются параллельно, до тех пор, пока эта транзакция не будет явно завершена. Завершение транзакции может быть выполнено одним из способов.

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

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

3. При использовании SQL-операторов в тексте программы успешное завершение их работы автоматически вызовет завершение работы последней транзакции, запущенной программой для выполнения, даже если оператор COMМIT для нее не был введен явно.

4. При использовании SQL-операторов в тексте программы аврийное завершение их работы автоматически вызовет откат последней транзакции, которая выполнялась в рамках этой программы.

9.5. КОНТРОЛЬНЫЕ ВОПРОСЫ

  1. Какие проблемы способствовали созданию механизма транзакций в СУБД?
  2. Что такое транзакция?
  3. Как механизм транзакций обеспечивает целостность данных?
  4. Какие свойства трансакций Вам известны?
  5. Какие уровни изоляции транзакций Вам известны и что они определяют?
  6. В чем заключается основной недостаток уровня изоляции транзакции Dirty Read?
  7. Как работает уровень изоляции транзакции Read Committed при чтении и изменении данных?
  8. Как работает уровень изоляции транзакции Repeatable Read при чтении и изменении данных?
  9. Какими возможностями обладает оператор SET TRANSACTION?
  10. Какие способы завершения транзакции Вам известны?
Вывод

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

© Куваев Я.Г., 2005—2020.

Все права защищены.

Вся информация, размещенная на данном веб-сайте, предназначена только для персонального использования и не подлежит дальнейшему воспроизведению и/или распространению в какой-либо форме, иначе как с письменного разрешения Автора.