Андроид. Windows. Антивирусы. Гаджеты. Железо. Игры. Интернет. Операционные системы. Программы.

Что такое транзакция по банковской карте. Запрет операции. Управление транзакциями Начало и завершение

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

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

Свойства транзакций

Все транзакции должны обладать следующими четырьмя свойствами (известными как свойства АСИД):

Атомарность (Atomicity). Транзакция либо фиксирует результат своей операции, либо возвращает всё на место. Если транзакция выполняется успешно, результат транзакции фиксируется. Если по какой-то причине транзакция не удалась, объекты, над которыми осуществлялась операция, возвращаются в исходное состояние. Например, при переименовании объекта должно произойти стирание старого имени и установка нового, или имя объекта должно остаться неизменным.

Кстати, атомарность (взаимозависимость) является неотъемлемой частью нашей повседневной жизни. К примеру, священник во время проведения церемонии бракосочетания сначала спрашивает жениха и невесту: "Хочешь ли ты взять себе в супруги этого человека?". Только после того как и тот и другая ответят "Да", священник может сказать: "Объявляю вас мужем и женой", и таким образом зафиксировать переход из одного состояния в другое. Другими словами, в рамках транзакции несколько независимых друг от друга участников сделки должны прийти к общему для всех соглашению, прежде чем сделка будет заключена. Если одна из сторон будет против, каждый из участников остаётся при своих.

Согласованность (Consistency). Транзакция вызывает корректную трансформацию системы, при этом сохраняя её состояние. Например, в рамках транзактного добавления одного элемента в двусвязный список, все четыре указателя в ту и в другую сторону обновляются одновременно.

Изолированность (Isolation). Выполняющиеся одновременно транзакции изолированы от воздействия незавершившихся транзакций. Данная характеристика также именуется как сериализуемость (serializability). Например, транзакция, проходящая через двусвязный список, который в это время подвергается изменению предыдущей транзакцией, будет видеть только те изменения, которые уже осуществились до её инициализации. Изменения же, осуществляемые предыдущей транзакцией, после запуска этой транзакции, уже никак не могут повлиять на неё.

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

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

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

Свойство Д (долговечность) также не является абсолютными свойством, т.к. некоторые системы допускают вложенные транзакции. Если транзакция Б запущена внутри транзакции А, и для транзакции Б подана команда COMMIT WORK, то фиксация данных транзакции Б является условной, т.к. внешняя транзакция А может откатиться. Результаты работы внутренней транзакции Б будут окончательно зафиксированы, только если будет зафиксирована внешняя транзакция А.

Начало и завершение

Транзакция обычно начинается автоматически с момента присоединения пользователя к СУБД (обычно, но не всегда: например, Visual FoxPro требует подать явную команду BEGIN TRANSACTION для того, чтобы начать новую транзакцию) и продолжается до тех пор, пока не произойдет одно из следующих событий:

Подана команда COMMIT WORK (зафиксировать транзакцию).

Подана команда ROLLBACK WORK (откатить транзакцию).

Произошло отсоединение пользователя от СУБД.

Произошел сбой системы.

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

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

Параллельная работа

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

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

Каким образом транзакции различных пользователей могут мешать друг другу? Различают три основные проблемы параллелизма:

Проблема потери результатов обновления.

Проблема незафиксированной зависимости (чтение "грязных" данных, неаккуратное считывание).

Проблема несовместимого анализа.

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

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

W-W (Запись - Запись). Первая транзакция изменила объект и не закончилась. Вторая транзакция пытается изменить этот объект. Результат - потеря обновления.

R-W (Чтение - Запись). Первая транзакция прочитала объект и не закончилась. Вторая транзакция пытается изменить этот объект. Результат - несовместимый анализ (неповторяемое считывание).

W-R (Запись - Чтение). Первая транзакция изменила объект и не закончилась. Вторая транзакция пытается прочитать этот объект. Результат - чтение "грязных" данных.

Конфликты типа R-R (Чтение - Чтение) отсутствуют, т.к. данные при чтении не изменяются.

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

Решение проблем: блокировки

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

Монопольные блокировки (X-блокировки, eXclusive locks) - блокировки без взаимного доступа (блокировка записи). В отличие от них, разделяемые блокировки (S-блокировки, Shared locks) - блокировки с взаимным доступом (блокировка чтения). Если транзакция A блокирует объект при помощи X-блокировки, то всякий доступ к этому объекту со стороны других транзакций отвергается. Если транзакция A блокирует объект при помощи S-блокировки, то запросы со стороны других транзакций на X-блокировку этого объекта будут отвергнуты, запросы со стороны других транзакций на S-блокировку этого объекта будут приняты.

Тупики

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

Можно представить два принципиальных подхода к обнаружению тупиковой ситуации и выбору транзакции-жертвы: СУБД не следит за возникновением тупиков. Транзакции сами принимают решение, быть ли им жертвами. Этот подход характерен для так называемых настольных СУБД (FoxPro и т.п.). Этот метод является более простым и не требует дополнительных ресурсов системы. Для транзакций задается время ожидания (или число попыток), в течение которого транзакция пытается установить нужную блокировку. Если за указанное время (или после указанного числа попыток) блокировка не завершается успешно, то транзакция откатывается (или генерируется ошибочная ситуация). За простоту этого метода приходится платить тем, что транзакции-жертвы выбираются, вообще говоря, случайным образом. В результате, из-за одной простой транзакции может откатиться очень дорогая транзакция, на выполнение которой уже потрачено много времени и ресурсов системы.

Второй подход к обнаружению тупиков заключается в том, что за возникновением тупиковой ситуации следит сама СУБД, она же принимает решение, какой транзакцией пожертвовать. Этот способ характерен для промышленных СУБД (ORACLE, MS SQL Server и т.п.). В этом случае система сама следит за возникновением ситуации тупика путем построения (или постоянного поддержания) графа ожидания транзакций (ориентированный двудольный граф, в котором существует два типа вершин - вершины, соответствующие транзакциям, и вершины, соответствующие объектам захвата). Ситуация тупика возникает, если в графе ожидания транзакций имеется хотя бы один цикл. Одну из транзакций, попавших в цикл, необходимо откатить, причем, система сама может выбрать эту транзакцию в соответствии с некими стоимостными соображениями (например, самую короткую, или с минимальным приоритетом и т.п.).

Транзакции в приложениях промышленного масштаба

Транзакция является важнейшей концепцией построения приложения промышленного масштаба. Как уже было сказано, для пользователя, транзакция - это сигнал о том, что некое действие либо осуществилось, либо не осуществилось. С другой стороны, для разработчика, транзакция - это стиль программирования, который позволяет ему создавать самостоятельные модули, способные принимать участие в распределённых вычислениях. Например, клиенту нужно перевести часть денег со сберегательного счёта на текущий чековый счёт. Для данной операции наиболее важным пунктом будет одновременное изменение состояния обоих счетов в случае успешного осуществления транзакции, или сохранение состояния счетов в прежнем виде, если перевод денег не удался. Вряд ли вам понравится, когда с одного счёта деньги уйдут, а до другого не дойдут. И хотя это условие является само собой разумеющимся требованием к приложениям такого назначения, выполнение этой операции в распределённых системах без внедрения каких-либо форм управления и контроля над транзакциями представляется достаточно проблематичным - компьютеры могут выйти из строя, а сообщение где-нибудь потеряться.

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

Электронная коммерция: обеспечение безопасности транзакций

Операции безналичных расчетов в платежных системах называют транзакциями. Платежные системы поддерживают транзакции различных видов: покупка, снятие наличных в отделении банка, снятие наличных в банкомате, получение информации об остатке на счете клиента и другие.

Транзакции различаются также по способу представления информации о карте в платежную систему. Существуют электронные транзакции (информация о карте считывается с магнитной полосы/чипа) и транзакции голосовой авторизации (paper based).

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

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

Действительно, при совершении операции покупки в физическом магазине продавец имеет право рассмотреть предъявляемую для расчета пластиковую карту на предмет ее соответствия требованиям платежных систем (в частности, проверить наличие голограммы, специальных секретных символов, сверить подписи на панели и торговом чеке и т. п.). Кроме того, продавец может потребовать от покупателя документ, удостоверяющий его личность. Все это делает мошенничество по поддельной карте достаточно дорогим предприятием. В случае транзакции в электронной коммерции все, что требуется от мошенника, - знание реквизитов карты. Затрат, связанных с изготовлением поддельной физической карты, в этом случае не требуется.

Для пластиковых карт с магнитной полосой самым надежным способом защиты транзакции от мошенничества является использование PIN-кода для идентификации владельца карты его банком-эмитентом. Секретной информацией, которой обладает владелец карты, является PIN-код. Он представляет собой последовательность, состоящую из 4-12 цифр, известную только владельцу карты и его банку-эмитенту. PIN-код применяется всегда при проведении транзакции повышенного риска, например при выдаче владельцу карты наличных в банкоматах. Выдача наличных в банкоматах происходит без присутствия представителя обслуживающего банка (ситуация похожа на транзакцию электронной коммерции). Поэтому обычных реквизитов карты для защиты операции "снятия наличных в банкомате" недостаточно и используется секретная дополнительная информация - PIN-код.

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

Использование PIN-кода должно производиться таким образом, чтобы этот секретный параметр на всех этапах обработки транзакций оставался зашифрованным (он должен быть известен только владельцу карты и банку).

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

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

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

1. Аутентификация участников покупки (покупателя, торговой точки и ее обслуживающего банка). Под аутентификацией покупателя (продавца) понимается процедура, доказывающая (на уровне надежности известных криптоалгоритмов) факт того, что данный владелец карты действительно является клиентом некоего эмитента-участника (обслуживающего банка-участника) данной платежной системы. Аутентификация обслуживающего банка доказывает факт того, что банк является участником данной платежной системы.

2. Реквизиты платежной карты (номер карты, срок ее действия, CVC2/CVV2 и т. п.), используемой при проведении транзакции, должны быть конфиденциальными для торговой точки.

3. Невозможность отказа от транзакции для всех участников транзакции, то есть наличие у всех участников неоспоримого доказательства факта совершения покупки (заказа или оплаты).

4. Гарантирование магазину платежа за электронную покупку - наличие у торговой точки доказательства того, что заказ был выполнен.

Транзакции в InterBase

В заключение, я расскажу о двух средах, в которых "живут" транзакции. А именно, о реализации транзакций в InterBase и о сервисе "Java Transaction Service" технологии Enterprise JavaBeans.

Для управления транзакциями в InterBase имеется три выражения:

SET TRANSACTION - Начинает транзакцию и определяет ее поведение.

COMMIT - Сохраняет изменения, внесенные транзакцией, в базе данных и завершает транзакцию.

ROLLBACK - Отменяет изменения, внесенные транзакцией, и завершает транзакцию.

1. Запуск транзакции

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

SET TRANSACTION

Выражение "SET TRANSACTION"
равносильно выражению
"SET TRANSACTION READ WRITE WAIT ISOLATION LEVEL SNAPSHOT"

Access Mode - определяет тип доступа к данным. Может принимать два значения:

READ ONLY - указывает, что транзакция может только читать данные и не может модифицировать их.

READ WRITE - указывает, что транзакция может читать и модифицировать данные. Это значение принимается по умолчанию.

Isolation Level - определяет порядок взаимодействия данной транзакции с другими в данной базе. Может принимать значения:

SNAPSHOT - значение по умолчанию. Внутри транзакции будут доступны данные в том состоянии, в котором они находились на момент начала транзакции. Если по ходу дела в базе данных появились изменения, внесенные другими завершенными транзакциями, то данная транзакция их не увидит. При попытке модифицировать такие записи возникнет сообщение о конфликте.

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

READ COMMITTED - позволяет транзакции видеть текущее состояние базы.

Конфликты, связанные с блокировкой записей, происходят в двух случаях:

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

Транзакция пытается модифицировать таблицу, которая заблокирована другой транзакцией типа SNAPSHOT TABLE STABILITY.

Lock Resolution - определяет ход событий при обнаружении конфликта блокировки. Может принимать два значения:

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

NO WAIT - немедленно возвращает ошибку блокировки записи.

Table Reservation - позволяет транзакции получить гарантированный доступ необходимого уровня к указанным таблицам. Существует четыре уровня доступа:

PROTECTED READ - запрещает обновление таблицы другими транзакциями, но позволяет им выбирать данные из таблицы.

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

SHARED READ - самый либеральный уровень. Читать могут все, модифицировать - транзакции READ WRITE.

SHARED WRITE - транзакции SNAPSHOT или READ COMMITTED READ WRITE могут модифицировать таблицу, остальные - только выбирать данные.

2. Завершение транзакции

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

COMMIT - сохраняет внесенные транзакцией изменения в базу данных. Это означает, что транзакция завершена успешно.

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

Java Transaction Service

В качестве координатора транзакций в рамках архитектуры EJB (технология серверных компонентов, Enterprise JavaBeans) используется Java Transaction Service (JTS). В терминологии JTS этот координатор именуется как менеджер транзакций (transaction manager). Участники транзакции, реализующие транзактно-защищённые ресурсы типа релятивных баз данных, называются менеджерами ресурсов (resource managers). Когда приложение инициирует транзакцию, оно создаёт объект, который представляет эту транзакцию. Затем приложение обращается к менеджерам ресурсов, которые должны осуществить операцию. В процессе выполнения транзакции каждый из менеджеров транзакций отслеживает работу каждого из указанных в транзакции менеджеров ресурсов.

Первое обращение приложения к каждому из менеджеров ресурсов определяет текущую транзакцию. Например, если приложение использует релятивную базу данных, оно вызывает интерфейс JDBC (Java Database Connectivity), который связывает транзактный объект с базой данных. С этого момента все вызовы, осуществляющиеся через это соединение, будут выполняться от лица транзакции самой базы данных, до тех пор пока транзакция не завершится.

Приложение фиксирует результат транзакции путём вызова метода xa_commit() и сообщает, что транзакция была успешно завершена. Если же по какой-либо причине приложение не может завершить транзакцию, оно вызывает метод xa_rollback(), отменяющий те изменения, которые были произведены. В случае, если приложение не в состоянии выполнить транзакцию, JTS снимает задачу. Когда транзактная операция завершается успешно, приложение обращается к JTS, чтобы сохранить результат. Затем JTS проходит через двухфазный протокол фиксации транзакций, чтобы передать задание указанным в транзакции менеджерам ресурсов.

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


Концепция транзакции лежит в основе реляционной парадигмы. Транзакция состоит из одной или нескольких DML команд и следующей командой или ROLLBACK или COMMIT. Возможно использовать команду SAVEPOINT для определённого управления внутри транзакции. Перед рассмотрением синтаксиса необходимо рассмотреть концепцию транзакций. Связанная с этой темой это тема согласованного чтения; это реализуется автоматически на уровне Oracle сервера, но некоторые программисты могут управлять им с помощью SELECT команд.

Механизм Oracle для обеспечения транзакционной целостности основан на сочетании сегментов отмены изменений и файла журнала логов: этот механизм бесспорно лучший из всех созданных на сегодняшний день и полностью удовлетворяет международным стандартам обработки данных. Производители других БД реализуют стандарт своими собственными другими способами. Вкратец, любая реляционная база данных должна удовлетворять тесту ACID: должны быть гарантированы атомарность (A – atomicity), согласованность (C – consistency), изолированность (I – isolation) и долговечность (D – durability).

A томарность

Принцип атомарности гласит что либо все части транзакции должны быть выполнены успешны либо ни одна из них. Например если бизнес-аналитик утвердил правило что при смене зарплаты сотрудника обязательно изменяется уровень сотрудника то ваша атомарная транзакция будет сосять из двух частей. БД должна гарантировать что будут применены либо оба изменения, либо ни одного. Если только одно изменения будет успешно то у вас появится сотрудник чья зарплата несовместима с его уровнем: повреждение данных в терминах бизнеса. Если что-нибудь (вообще что-нибудь) пошло не так до подтверждения транзакции, БД должна гарантировать что вся работа совершённая до этого момента от начала транзакции будет отменена: это должно работать автоматически. Несмотря на то что атомарность транзакции звучит как что-то маленькое – транзакции могут быть долгими и очень важными. Рассмотрим другой пример, в бухгалтерской книге не может быть данных на пол-месяца Августа и пол-месяца Сентября: закрытие месяца с точки зрения бизнеса одна атомарная транзакция, которая может обрабатывать миллионы строк и тысячи таблицы и работать несколько часов (или отменяться если что-то пошло не так). Отмена транзакции может быть ручной (выполнив команду ROLLBACK) но она должна быть автоматической и неотменяемой в случае ошибки.

Согласованность

Принцип согласованности данных гласит что результат запроса должен быть согласован с состояним базы данных на момент старта работы запроса. Преставим простой запрос которые считает среднее значение столбца в таблице. Если таблица большая, это займёт достаточно долгое время для прохода по всем строкам таблицы. Если другие пользователи в это время обновляют данные пока запрос выполняется, должен ли запрос брать новые значения или старые? Должен ли результат запроса учитывать строки которые были добавлены или не учитывать строки которые были удалены? Принцип согласованности требует чтобы БД гарантировала что любые изменения после старта запроса не были видны для этого запроса; запрос должен вернуть среднее значение столбца на момент когда запрос был запущен, вне зависимости от того как долго длился запрос и какие изменения были над данными. Оракл гарантирует что если запрос выполнен успешно – результат будет согласованным. Как бы там ни было, если администратор базы данных не настроил базу данных соотвествующим образом, запрос может не выполнится: возникнет знаменитая ошибка “ORA-1555 snapshot too old”. Раньше было очень сложно решить такие ошибки, но в последних версиях администратор легко может решать эти ситуации.

Изолированность

Принцип изолированности гласит что незаконченная (неподтверждённая транзакция) должна быть невидима для остального мира. Пока транзакция в процессе только сессия которая выполняет эту транзакцию видит зименения. Все остальные сессии должны видеть неизменённые данные. Почему так? Во первых, транзакция может целиком не выполниться до конца (помним про принцип атомарности и согласованности) и поэтому никто не должен видеть изменения которые могут быть отменены. Во вторых во время действия транзакции данные (в терминах бизнеса) бессвязные: для нашего примера обновления зарплаты будет существовать промежуток времени когда зарплата изменена, а уровень ещё нет. Изолированность транзакций требудет чтобы база данных прятала текущие транзакции от других пользователей: они будут видеть данные до изменений пока транзакция выполняется, а затем сразу будут видеть все изменения как согласованный набор данных. Oracle гарантирует изолированность транзакций: нет способа для сессии (отличной от той что делает изменения) увидеть неподтверждённые данные. Чтение неподтверждённых данных (известное как грязное чтение dirty read) не позволяется Oracle (несмотря на то что некоторые другие БД позволяют).

Долговечность

Принцип долговечности указывает на то, что если транзакция успешно завершена, то должно быть невозможно потерять эти данные. Во время работы транзакции принцип изолированности требует чтобы никто кроме сессии выполняющей изменения не видел их. Но как только транзакция успешно завершила работу, изменения должны стать доступны для всех и база данных должна гарантировать что они не будут потеряны. Oracle выполняет это требование путём записывания всех векторов изменений в файлы логов перед тем как изменения подтверждены. Применив этот логи изменений к резервным копиям, всегда возможно повторить любые изменения которые были выполнены в момент остановки или повреждения базы данных. Конечно данные могут быть потеряны из-за ошибок пользователей, таких как выполнение неверных DML запросов или удаление таблиц. Но с точки зрения Oracle и администратора базы данных, такие события тоже транзакции: согласно принципу долговечности их нельзя отменить.

Выполнение SQL запросов

Весь язык SQL состоит из около дюжины команд. Сейчас нас интересуют команды: SELECT, INSERT, UPDATE и DELETE.

Выполнение команды SELECT

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

Always remember that server processes read blocks from datafiles into the database buffer cache, DBWn writes blocks from the database buffer cache to the datafiles.

Когда блоки с нужными для выполнения запроса данными находятся в кэш буфере любые дополнительные процессы (такие как сортировка и аггрегирование) продолжаются в PGA сессии. Когда выполнение завершено, результат возвращается пользовательскому процессу.

Как это связано с тестом ACID? Для согласованности, если запрос обнаружит что блок данных изменился с момента старта запроса, серверный процесс найдёт сегмента отката (отмены изменений или сегмент undo) соответствующий этому изменению, найдёт старую версию данных и (для текущего запроса) отменит изменение. Таким образом изменения которые произошли после начала запроса будут не видны. Похожим образом гарантируется изолированность транзакций, несмотря на то что изолированность основана и на подтверждённых изменениях. Честно говоря, если данные необходимые для отмены изменений не существуют больше в сегменте отката – этот механизм не сработает. Отсюда и следует ошибка “snapshot too old”.

На рисунке 8-4 показан путь обработки запроса SELECT

Шаг 1 это передача пользовательского запроса от пользовательского процесса к серверному. Серверный процесс просматривает буфер кэш на наличие нужных блоков и если они в буфере то переходит к шагу4. Если нет то шаг 2 находит блоки в файлах данных и шаг 3 копирует данные в буфер. Шаг 4 передает данные сервеному процессу где может быть дополнительная обработка перед тем как шаг 5 вернёт результат запроса пользовательскому процессу.

Выполнение команды UPDATE

Для любой команды DML необходимо работать с блоками данных и блоками отката (undo blocks), а также создавать лог изменений (redo): A,C и I принципы теста ACIDS требуют создания данных отката; D требует создание данных повтора изменений (redo).

Undo не противоположна redo! Redo защищает все изменения блоков, вне зависимости это изменения блока таблицы, индекса или сегмента отката. Для redo — undo сегмент такой же сегмент как таблцы и все изменения должны быть долговечны (durable)

Первый шаг при выполнении DML команды такой же как и при выполнении команды SELECT: необходимые блоки должны быть найдены в кэф буфере или скопированы с файлов данных в буфер. Единственное отличие это то что дополнительно требуется пустой (или устаревший – expired) блок отката. Затем выполнение становится сложнее чем при команде SELECT.

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

Потом создаются данные redo: серверный процесс записывае в логи буфера вектора изменений которые будут применены к данным. Redo данные создаются и для изменений блока данных и для изменений блока отката: если столбец в строке будет обновлен то rowid и новое значение записывается в буфер лога (изменение которое будет применено к блоку таблицы), а также старое значение столбца (изменение для блока отката). Если столбец это часть ключа индекса – то изменения в индексе тоже будут записаны в буфер лога, вместе с изменениями которые будут сделаны в блоке отката для защиты изменений индекса.

После того как все redo данные созданы, обновляются данные в буфер кэше: блок данных обновляется на новую версию с измененным столбцом, а старая версия записывается в блок отката. С этого момента до подтверждения транзакции, все запросы от других сессий обращающиеся к этой строке будут перенаправлены на блок отката. Только сессия которая делает UPDATE будет видеть актуальную версию строки а блоке таблицы. Такой же принцип применяется для всех связанных индексов.

Выполнение команд INSERT и DELETE

Концептуально INSERT и DELETE управляются в той же манере как и UPDATE. Вначале происходит поиск нужных блоков в буфере и если их нет то они копируются в память.

Redo создается точно так же: все вектора изменений которые будут применены к данным и блокам отката вначале записываются в буфер лога. Для команды INSERT вектор изменений блока таблицы (и возможно блоков индекса) это байты которые составляют новую строку (и возможно новый ключ индекса). Вектор для блока отката это rowid новой строки. Для команды DELETE вектор для блока отката это вся строка.

Ключевым отличием между командами INSERT и UPDATE является количество данных для отката. Когда строка добавляется единственными данными для отката будет запись rowid в блок отката, потому что для отмены команды INSERT единственная информация нужная Oracle это rowid строки и может быть создана команда

delete from table_name where rowid=rowd_id_of_new_row;

Выполнение этой команды отменит изменение.

Для команды DELETE вся строка (которая может быть несколько килобайт) должна быть записана в блок undo, и тогда удаление может быть отменено при необходимости путём генерации запроса который заново добавил полностью строку в таблицу.

Начало и конец транзакции

Сессия начинает транзакция в момент когда она выполняет любую DML команду. Транзакция продолжается сколько угодно следующих DML команд пока сессия не выполнит команду ROLLBACK или COMMIT. Только подтвеждённые изменения станут гарантированными и будут доступны для других сессий. Невозможно начать транзакцию внутри транзакции. Стандарт SQL не разрешает пользователям начать транзакцию, а затем начать новую перед завершение первой. Это можно сделать используя PL/SQL (язык Oracle третьего поколеняи), но не стандартным SQL.

Командами управления транзакциями являются команды COMMIT, ROLLBACK и SAVEPOINT. Также могут возникнуть другие обстоятельства помимо явного вызовая команды COMMIT или ROLLBACK которые немедленно прекращают транзакцию

  • Выполнение DDL или DCL команды
  • Завершение польховательского процесса (к примеру пользователь вышел из программы SQL *Plus или SQL Developer)
  • Клиентская сессия «умерла»
  • Проблемы в системе

Если пользователь выполняет DDL команду (CREATE, ALTER или DROP) иди DCL команду (GRANT или REVOKE) то активная транзакция (если она сущесвтует) будет подтверждена. Так происходит потому что команды DDL и DCL сами являются транзакциями. Так как в SQL невозможно создать вложенные транзакции, если у пользователя уже выполнялась какая либо транзакция, все команды пользователя будут подтверждены вместе с командой DDL или DCL.

Если вы начали транзакцию выполнив DML запроса, а затем закрыли программу без явного указания COMMIT или ROLLBACK до выхода, транзакция будет прекращена – но прекращена с подтверждением или отменой целиком зависит от программы. У разных программ может быть разное поведение в зависимости от того как вы закончили работу в программе. Например в Windows обычно можно выйти из программы выбрав пункты меню File – Exit или нажав на крестик в правом верхнем углу. Программист мог обработать по разному эти способы завершения и в первом случае указать COMMIT, а во втором ROLLBACK. В любом случае это будет контролируемый выход.

Если клиентская сессия отказывает по какой-либо причине – база данных всагда отменит транзакцию. Такие отказы могут быть по разным причинам: пользовательский процесс мог быть «убит» диспетчером, проблемы с сетью или поломка пользовательской машины. В любом случае не было явно указана команда COMMIT или ROLLBACK и БД нужно решить что случилось. В таком случае сессия «убивается» и активная транзакция отменяется. И точно так-же база данных ведёт в себя в случае проблем на стороне сервера. Если база данных была закрыта аварийно то при следующем старте все транзакции которые были начаты но явно не завершены будут отменены.

Управление транзакциями: COMMIT, ROLLBACK, SAVEPOINT и SELECT FOR UPDATE

Oracle начинает транзакцию в момент запуска первой DML команды. Транзакция длится до вызова команды ROLLBACK или COMMIT. Команда SAVEPOINT не является частью SQL стандарта и в реальности является легким способом для программиста чтобы отменить изменения частично в обратном порядке.

Выполнение команды COMMIT это тот момент когда многие люди (и даже некоторые администраторы БД) показывают непонимание архитектуры Oracle. Когда вы выполняете COMMIT всё что происходит физически это LGWR записывает буфер логов на диск. DBWn не делает абсолютно ничего. Это одно из самых важных свойств Oracle для достижения высокой производительность БД.

Что делает DBWn в момент выполнения команды COMMIT? Ответ: абсолютно ничего

Чтобы сделать транзакцию долговечной всё что нужно это записать изменения которые были сделаны в процессе транзакции на диск: нет необходимости в актуальных данных на диске. Если изменения записаны, в виде многих копий логов изменений на диске, то даже в случае повреждения базы все транзакции могут быт повторены восстановив резеврную копию данных до ошибки и применив изменения из логов. На данный момент надо понимать тот факт что COMMIT всего лишь очищает буфер лога на диск и помечает транзакцию как выполненную. Вот почему транзакции в которой были задействованы миллионы обновлений в тысячах файлов в течение нескольких часов могут подветрждаться за долю секунды. Так как LGWR записывает логи практически в режиме реального времени, то виртуально все изменения транзакции уже записаны на диск. Когда вы выполняете COMMIT, LGWR тут же записывает лог на диск: ваша сессия будет ожидать пока запись не закончится. Время задержки будет равно времени которое занимает запись последних данных из буфера логов, что обычно занимает несколько миллисекунд. Потом ваша сессия может продолжать работу и все остальные сессии не будут перенаправлятьяс на данные в сегменте отката при обращении к обновлённым данным, если только принцип согласованности не требует этого. Вектора изменений, записываемыe в лог повтора изменений, это все изменения: применяемых и к блокам данных (таблиц и индексов) и к блокам отката.

Лог redo включает все изменения: применяемые к сегментам данным и к сегментам undo для потдвержденных и неподтвержденных транзакций

Самое непонятное это то что redo записывается LGWR в файлы будет содержать и подтвержденные и неподтвержденные транзакции. Даже больше, в любой момент DBWn может записать а может и не записать измененные блоки сегментов данных или сегментов отката в файлы данных для подтверждённых и неподтверждённых транзакций. То есть ваша БД на диске противоречива: файлы данных могут хранить данные неподтверждённых транзакций и в них могут отсутствовать подтверждённые изменения. Но в любой момент, в случае проблемы, в файле логов на диске достаточно информации чтобы повторить подтверждённые транзакции которые пропущены в файлах данных (используя изменения для блоков данных) и восстановить сегменты отката (используя изменения блоков отката) нужные для отмены всех неподтверждённых транзакций которые записаны в файлы данных.

Лбая DDL команда, а также GRANT или REVOKE подтвердят текущую транзакцию

ROLLBACK

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

Синтаксис для отмены транзакции

ROLLBACK ;

Состояние данных перед отменой транзакции содержит изменения, но информация нужная для отмены этих изменений доступна. Эта информация используется другими сессиями для выполнения принципа изолированности. ROLLBACK транзакции отменит все изменения восстановив образ данных до начала транзакции: все добавленные строки будут удалены, все удалённые строки восстановлены, все строки в которых менялись значения вернутся к исходному состоянию. Другие сессии даже не будут знать что что-то происходило, они никогда не видели изменений. А сессия которая инициировала транзакцию после отмены будет видеть данные такими какими они были до начала транзакции.

SAVEPOINT

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

Синтаксис команды

SAVEPOINT savepoint

Такая команда создаёт точку в транзакции которая может быть использована в дальнейшем в команде ROLLBACK. На следующей таблице видно количество строк в таблице видимое разным сессиям во время работы транзакции в разные моменты времени. Используемая таблица назвается TAB и у неё один столбец

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

SELECT FOR UPDATE

Последняя команда для управления транзакциями это SELECT FOR UPDATE. Oracle, по умолчанию, предоставляет наивысший уровень параллелизма: чтение данных не блокирует запись, запись не блокирует изменение. Другими словами нет проблемы если одна сессия пытается считать данные которые другая сессия изменяет и наоборот. Но иногда вам может понадобиться изменить такое поведение и предотвратить возможность изменения данных которые считаны сессией.

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

Вот что увидит первый пользователь (прелположим что используется SQL *Plus)

Такой результат немного смущает пользователя. Чтобы решить эту проблему можно заблокировать строки которые вернул запрос

select * from regions for update;

Директива FOR UPDATE приведёт к блокировке таблиц которые возвращает запрос. Другие сессии не смогут изменить данные и таким образом последующие изменения будут успешны: другие сессии не смогут изменить данные. То есть у одной сессии будет согласованное чтение данных, но ценой за это будет то, что другие сессии «зависнут» если они попытаются изменить данные которые заблокированы (другие сессии могут читать эти данные).

Блокировка строк вызванная командой FOR UPDATE будет длиться пока сессия не выполнит команду COMMIT или ROLLBACK. Команду завершения транзакции необходимо выполнить даже если вы не запускали каких-либо DML команд.

Так называемый «авто-коммит»

Чтоб завершить обзор как обрабатывается управление транзакциями надо рассеять все сомнения о так называемом “auto-commit” или неявном подтверждении (implicit commit). Вы будете часто слышать что Oracle автоматически подтвердит. Первый случай это предыдущий случай когда вы выполнили команду DDL, другая ситуация когда пользователь вышел из программы такой как SQL *Plus.

На самом деле всё очень просто. Не существует такого понятия как авто-коммит. Когда вы выполняете DDL команду, то работает обычный COMMIT которые встроен в команду DDL. Но что проиходит когда вы выходите из программы? Если вы используете SQL Plus в Windows и выполняете команду DML а затем команду EXIT (EXIT это команду SQL *Plus а не SQL), ваша транзакция будет подтверждена. Это потому что разработчики SQL *Plus встроили вызов команды COMMIT в команду EXIT. Если же вы нажмёте на красный крест в правом верхнем углу – то произойдёт вызов команды ROLLBACK. Так происходит потому что опять же разработчики SQL *Plus запрограммировали такое поведение программы. В другой операционной системе поведение программы SQL Plus может быть другим, единственный способ узнать это – это протестировать программу (или прочитать исходный код что в случае программы SQL Plus невозможно если вы не работаете в Oracle надо этой программой).

В SQL *Plus есть команда SET AUTOCOMMIT ON. Вызов этой команды указывает SQL *Plus на то как обрабатывать пользовательские запросы: SQL *Plus добавит вызов команды COMMIT после любой DML команды. Таким образом все запросы будут подтверждаться как только они выполнены. Но опять же всё это происходит полностью на стороне пользовательского процесса; у базы данных нет никакого авто-коммита, и все долго-работающие изменения будут изолированы от других сессий пока запрос не выполнится успешно. Даже в таком случае если вы запустите долгий запрос на выполнение, потом к примеру завершите пользовательский процесс через диспетчер задач то PMON обнаружит сессию «призрак» и отменит транзакцию.

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

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

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

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

В выполнении операции задействованы три стороны:

  • банк-эквайер, обслуживающий выбранную торговую точку (именно его POS-терминал установлен в магазине);
  • банк-эмитент, обслуживающий платежную банковскую карту;
  • международная платежная система, являющаяся промежуточным звеном при проведении расчетных операций (Visa, MasterCard и т. д.).

Порядок онлайн-транзакций

Расчетная транзакция начинается с момента передачи платежной карты кассиру и считывания POS-терминалом данных, необходимых для оплаты (номера карты, периода ее действия, фамилии владельца и других сведений, зашифрованных на магнитной ленте). Считанная информация передается в банк-эквайер, обслуживающий POS-терминал (как правило, магазины заключают специальные договора на обслуживание терминалов, согласно которым с каждой транзакции взимаются комиссии).

Полученные данные передаются банком-эквайером в центр обработки данных (ЦОД) международной платежной системы, обслуживающей карту.

В ЦОД проводится проверка на наличие или отсутствие платежной карточки в стоп-листе (в стоп-листе могут оказаться карты, подозреваемые в мошенничестве), в результате чего операция одобряется или отклоняется.

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

Ответ банка-эмитента направляется обратно, через ЦОД, к банку-эквайеру и магазину. Реквизиты платежа выводятся на чек, который передается покупателю.

Особенности онлайн и оффлайн-операций

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

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

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

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

Запрет и отмена транзакций

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

Самые распространенные из них:

  • банковская карта была заблокирована;
  • на банковской карте отсутствует достаточное количество средств, необходимых для выполнения операции;
  • платежная карта имеет установленные ограничения по совершению платежей;
  • срок действия платежной карты истек;
  • допущена ошибка при введении PIN-кода;
  • банковская карта внесена в стоп-лист по подозрению в отмывке средств, мошенничестве и т. д.;
  • существуют технические проблемы (на сайте, с банкоматом и т. д.).

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

Проще всего отменить операцию в тот день, в который она совершалась.

Функция отмены операций есть в самих терминалах.

Если данные с терминалов уже были переданы в банк, обращаться следует в само финансовое учреждение.

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

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

Плоские, или традиционные, транзакции, характеризуются четырьмя классическими свойствами: атомарности, согласованности, изолированности, долговечности (прочности) - ACID (Atomicity, Consistency, Isolation, Durability). Иногда традиционные транзакции называют ACID-транзакциями. Упомянутые выше свойства означают следующее:

Свойство атомарности (Atomicity) выражается в том, что транзакция должна быть выполнена в целом или не выполнена вовсе.

Свойство согласованности (Consistency) гарантирует, что по мере выполнения транзакций данные переходят из одного согласованного состояния в другое - транзакция не разрушает взаимной согласованности данных.

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

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

Возможны два варианта завершения транзакции. Если все операторы выполне­ны успешно и в процессе выполнения транзакции не произошло никаких сбоев программного или аппаратного обеспечения, транзакция фиксируется.

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

До тех пор пока транзакция не зафиксирована, допустимо аннулирование этих изменений, восстановление базы данных в то состояние, в котором она была на момент начала транзакции. Фиксация транзакции означает, что все результаты выполнения транзакции становятся постоянными. Они станут видимыми дру­гим транзакциям только после того, как текущая транзакция будет зафиксиро­вана. До этого момента все данные, затрагиваемые транзакцией, будут «видны» пользователю в состоянии на начало текущей транзакции.

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



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

В стандарте ANSI/ISO SQL определены модель транзакций и функции операторов COMMIT и ROLLBACK. Стандарт определяет, что транзакция начинается с первого SQL-оператора, инициируемого пользователем или содержащегося в программе, изменяющего текущее состояние базы данных. Все последующие SQL-операто­ры составляют тело транзакции. Транзакция завершается одним из четырех возможных путей (рис. 11.1):

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

оператор ROLLBACK прерывает транзакцию, отменяя изменения, сделанные в базе данных в рамках этой транзакции; новая транзакция начинается непосредственно после использования ROLLBACK;

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

ошибочное завершение программы прерывает транзакцию (как будто был использован оператор ROLLBACK).

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

В первых версиях коммерческих СУБД была реализована модель транзакций ANSI/ISO. В дальнейшем в СУБД SYBASE была реализована расширенная мо­дель транзакций, которая включает еще ряд дополнительных операций. В моде­ли SYBASE используются следующие четыре оператора:

Оператор BEGIN TRANSACTION сообщает о начале транзакции. В отличие от мо­дели в стандарте ANSI/ISO, где начало транзакции неявно задается первым оператором модификации данных, в модели SYBASE начало транзакции за­дается явно с помощью оператора начала транзакции.

Оператор COMMIT TRANSACTION сообщает об успешном завершении транзакции. Он эквивалентен оператору COMMIT в модели стандарта ANSI/ISO. Этот опе­ратор, как и оператор COMMIT, фиксирует все изменения, которые производи­лись в БД в процессе выполнения транзакции.

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

Оператор ROLLBACK имеет две модификации. Если этот оператор используется без дополнительного параметра, то он интерпретируется как оператор отката всей транзакции, то есть в этом случае он эквивалентен оператору отката ROLLBACK в модели ANSI/ISO. Если же оператор отката имеет параметр и за­писан в виде ROLLBACK В, то он интерпретируется как оператор частичного от­ката транзакции в точку сохранения В.

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

Транзакция начинается явным оператором начала транзакции, который имеет в нашей схеме номер 1. Далее идет оператор 2, который является оператором поиска и не меняет текущее состояние БД, а следующие за ним операторы 3 и 4 переводят базу данных уже в новое состояние. Оператор 5 сохраняет это новое промежуточное состояние БД и помечает его как промежуточное состояние в точке А. Далее следуют операторы 6 и 7, которые переводят базу данных в но­вое состояние. А оператор 8 сохраняет это состояние как промежуточное со­стояние в точке В. Оператор 9 выполняет ввод новых данных, а оператор 10 проводит некоторую проверку условия 1; если условие 1 выполнено, то выполняется оператор 11, который проводит откат транзакции в промежуточное со­стояние В Это означает, что последствия действий оператора 9 как бы стирают­ся и база данных снова возвращается в промежуточное состояние В, хотя после выполнения оператора 9 она уже находилась в новом состоянии И после отката транзакции вместо оператора 9, который выполнялся раньше из состояния В БД, выполняется оператор 13 ввода новых данных, и далее управление переда­ется оператору 14 Оператор 14 снова проверяет условие, но уже некоторое но­вое условие 2, если условие выполнено, то управление передается оператору 15, который выполняет откат транзакции в промежуточное состояние А, то есть все операторы, которые изменяли БД, начиная с 6 и заканчивая 13, считаются не­выполненными, то есть результаты их выполнения исчезли и мы снова нахо­димся в состоянии А, как после выполнения оператора 4 Далее управление передается оператору 17, который обновляет содержимое БД, после этого управление передается оператору 18, который связан с проверкой условия 3 Проверка заканчивается либо передачей управления оператору 20, который фик­сирует транзакцию, и БД переходит в новое устойчивое состояние, и изменить его в рамках текущей транзакции невозможно Либо, если управление передано оператору 19, то транзакция откатывается к началу и БД возвращается в свое начальное состояние, а все промежуточные состояния здесь уже проверены, и выполнить операцию отката в эти промежуточные состояния после выполнения оператора 19 невозможно

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

1. Транзакции и блокировки

2. Понятие транзакции

При работе с базами данных не исключены ошибки и сбои. Они могут быть вызваны ошибками пользователей, взаимодействующих с СУБД, или неустойчивой работой компьютеров. Поэтому в СУБД применяют специальные способы отмены действий, вызвавших такие ошибки. Команда SQL, оказывающая действие на содержание и структуру БД, не является необратимой. Пользователь может установить, что произойдет после окончания ее действий: останутся ли внесенные изменения БД или они будут проигнорированы. Для этого последовательность операций над базой данных объединяют в группы - транзакции.

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

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

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

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

3. Свойства транзакций. Способы завершения транзакций

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

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

Плоские транзакции характеризуются классическими свойствами: атомарности, согласованности, изолированности и долговечности.

· Свойство атомарности выражается в том, что транзакция должна быть выполнена в целом или не выполнена вовсе.

· Свойство согласованности гарантирует, что по мере выполнения транзакции данные переходят из одного согласованного состояния в другое согласованное состояние - транзакция не разрушает взаимной согласованности данных.

· Свойство изолированности означает, что конкурирующие за доступ к БД транзакции физически обрабатываются последовательно, изолированно друг от друга, но для пользователей это выглядит так, как будто они выполняются параллельно.

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

Возможны 2 варианта завершения транзакции:

· если все операторы выполнены успешно и в процессе транзакции не произошло никаких сбоев программного или аппаратного обеспечения, транзакция фиксируется. (Фиксация – это запись на диск изменений в БД, которые были сделаны в процессе выполнения транзакции). До тех пор, пока транзакция не зафиксирована, эти изменения могут быть аннулированы и база данных может быть возвращена в то состояние, в котором она была на момент начала транзакции. Фиксация транзакции означает, что все результаты выполнения транзакции становятся постоянными. Они станут видимы другим транзакциям только после того, как текущая транзакция будет зафиксирована.

· Если в процессе выполнения транзакции произошел сбой, БД должна быть возвращена в исходное состояние. Откат транзакции – это действие, обеспечивающее аннулирование всех изменений данных, которые были сделаны операторами SQL в теле текущей незавершенной транзакции.

4. Операторы Transact SQL для работы с транзакциями

В стандарте ANSI / ISO определены операторы СOMMIT и ROLLBACK, в стандарте начало транзакции неявно задается первым оператором модификации данных; Оператор COMMIT означает успешное завершение транзакции, результаты транзакции фиксируются во внешней памяти; при завершении транзакции оператором ROLLBACK результаты транзакции отменяются. Успешное завершение программы, в которой была инициирована транзакция, означает успешное завершение транзакции (как если бы был использован оператор COMMIT ), неуспешное завершение – прерывает транзакцию (как будто был использован оператор ROLLBACK ). В этой модели каждый оператор, изменяющий состояние данных, рассматривается как транзакция. Такая модель была реализована в первых версиях коммерческих СУБД. В дальнейшем в СУБД SYBASE была реализована расширенная модель транзакций.

В расширенной модели транзакций (например, в СУБД SQL SERVER) предусмотрен ряд дополнительных операций:

· оператор BEGIN TRANSACTION сообщает о начале транзакции;

· оператор COMMIT TRANSACTION сообщает об успешном завершении транзакции. Этот оператор, также как и COMMIT в модели стандарта ANSI/ISO, фиксирует все изменения, которые производились в БД в процессе выполнения транзакции;

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

· оператор ROLLBACK имеет 2 модификации. Если он используется без дополнительного параметра, то он интерпретируется как оператор отката всей транзакции, если же он имеет параметр ROLLBACK n , то он интерпретируется как оператор частичного отката транзакции в точку сохранения n.

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

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

SET AUTOCOMMIT ON ;

а возврат к обычной диалоговой обработке запросов:

SET AUTOCOMMIT OFF ;

Кроме того, имеется возможность установки AUTOCOMMIT , которую СУБД выполнит автоматически при регистрации, Если сеанс пользователя завершился аварийно, – например, произошел сбой системы, то текущая транзакция выполнит автоматический откат изменений. Не рекомендуется организовывать работу так, чтобы одиночные транзакции содержали много команд, тем более не связанных между собой. Это может привести к тому, что при отмене изменений будет выполнено слишком много действий, в том числе и тех, которые являются нужными и ошибки не вызвали. Лучший вариант, когда транзакция состоит из одной команды или нескольких тесно связанных команд.

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

Пример транзакции :

BEGIN TRAN

UPDATE account

SET balance= balance- 100

If @@ error=0

BEGIN

ROLLBACK TRAN

RETURN

END

UPDATE card_account

SET balance=balance+100

WHERE account_number=@s_account

If @@ error=0

BEGIN

ROLLBACK TRAN

RETURN

END

COMMIT TRAN

Команда BEGIN TRAN сообщает серверу о начале транзакции. Это значит, что до получения сервером команды COMMIT TRAN все изменения являются временными. Следовательно, если на сервере произойдет сбой после первого обновления, произойдет откат транзакции. Никакой процесс не сможет получить доступ к данным до тех пор, пока не будет завершена транзакция.

5. Журнал транзакций.

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

· результаты зафиксированных транзакций должны быть сохранены в восстановленном состоянии БД;

· результаты незафиксированных транзакций не должны присутствовать в восстановленном состоянии БД.

Это означает, что восстанавливается последнее по времени согласованное состояние БД.

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

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

· Восстановление после поломки основного внешнего носителя БД (жесткий сбой).

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

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

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

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

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

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

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

Имеется 2 варианта ведения журнала транзакций: протокол с отложенными обновлениями и протокол с немедленными обновлениями.

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

1. Когда транзакция Т1 начинается, в протокол заносится запись

Т1 Begin Transaction

2. На протяжении выполнения транзакции в протоколе для каждой изменяемой записи записывается новое значение

Т1. ID _ RECORD , атрибут, новое значение

(ID _ RECORD – уникальный номер записи)

3. Если все действия, из которых состоит транзакция, успешно выполнены, то транзакции частично фиксируется и в протокол заносится:

T 1 COMMT

4. После того, как транзакция зафиксирована, записи протокола, относящиеся к Т1, используются для внесения изменений в БД.

5. Если происходит сбой, то СУБД просматривает протокол и выясняет, какие транзакции необходимо переделать. Транзакцию Т1 необходимо переделать, если протокол содержит обе записи Т1 Begin Transaction и T 1 COMMT . БД может находиться в несогласованном состоянии, однако все новые значения измененных элементов данных содержатся в протоколе, и это требует повторного выполнения транзакции. Для этого используется системная процедура REDO (), которая заменяет все значения элементов данных на новые, просматривая протокол в прямом порядке.

6. Если в протоколе не содержится команда фиксации транзакции С OMMIT , то никаких действий проводить не требуется, а транзакция запускается заново.

Альтернативный механизм с немедленным выполнением предусматривает внесение изменений сразу в БД, а в протокол заносятся не только новые, но и все старые значения изменяемых атрибутов, поэтому каждая запись выглядит так:

Т1. ID _ RECORD , атрибут, новое значение старое значение

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

При откате транзакции выполняется системная процедура UNDO() , которая возвращает все старые значения в отмененной транзакции, последовательно проходя по протоколу, начиная с команды BEGIN TRANSACTION.

Для восстановления при сбое используется следующий механизм:

· Если транзакция содержит команду начала транзакции, но не содержит команду фиксации с подтверждением ее выполнения, то выполняется последовательность действий как при откате транзакции, то есть восстанавливаются старые значения.

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

6. Блокировки.

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

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

§ Пропавшие изменения . Эта ситуация возникает в тех случаях, когда 2 транзакции одновременно изменяют одну и ту же запись в БД. Например, работают 2 оператора на приеме заказов, первый оператор принял заказ на 30 мониторов. Когда он обращался на склад, то там числилось 40 мониторов, и он, получив подтверждение от клиента, оформил продажу 30 мониторов из 40. Параллельно с ним работает второй оператор, который принимает заказ на 20 таких же мониторов, и в свою очередь, обратившись на склад, он получает то же значение 40, и оформляет заказ для своего клиента. Заканчивая работу с данными, он выполняет команду Обновить, которая заносит 20 как остаток мониторов на складе. После этого первый оператор заканчивает работу со своим заказчиком и тоже выполняет команду Обновить , которая заносит остаток 10 как число мониторов, имеющихся на складе. В общей сложности они продали 50 мониторов при имеющихся 40, и при этом на складе будет числиться 10 мониторов.

§ Проблемы промежуточных данных . Связано с возможностью доступа к промежуточным данным. Допустим первый оператор, ведя переговоры со своим заказчиком, ввел заказанные 30 мониторов, но перед окончательным оформлением заказа клиент захотел выяснить еще некоторые характеристики товара. Приложение, с которым работает 1-й оператор, уже изменило остаток мониторов на складе, и там сейчас хранится информация о 10 оставшихся мониторах. В это время второй оператор пытается принять заказ от своего заказчика заказ на 20 мониторов, но его приложение показывает, что на складе осталось всего 10 мониторов и оператор вынужден отказать своему заказчику. В это время заказчик первого оператора принимает решение не покупать мониторы, оператор делает откат транзакции и на складе снова оказывается 40 мониторов. Такая ситуация стала возможной потому, что приложение второго оператора имело доступ к промежуточным данным, которые сформировало первое приложение.

§ Проблемы несогласованных данных. Связана с возможностью изменения данны x , уже прочитаны x другим приложением. Оба оператора начинают работать практически одновременно, получают начальное состояние склада 40 мониторов, а затем первый оператор продает своему заказчику 30 мониторов. Он завершает работу своего приложения, и оно выполняет команду фиксации транзакции COMMIT. Состояние БД непротиворечивое. В этот момент заказчик второго оператора решает сделать заказ и второй оператор, обращаясь повторно к данным, видит, что количество мониторов изменилось. Второй оператор считает, что нарушена целостность транзакции, т.к. в течение выполнения одной работы он получил 2 различных состояния склада. Эта ситуация возникла потому, что приложение 1-го оператора смогло изменить кортеж с данными, который уже прочитало приложение второго оператора.

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

· W-W – транзакция 2 пытается изменить объект, измененный не закончившейся транзакцией 1;

· R-W – транзакция 2 пытается изменить объект, прочитанный не закончившейся транзакцией 1;

· W-R транзакция 2 пытается читать объект, измененный не закончившейся транзакцией 1;

7. Сериалиация транзакций

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

1. В ходе выполнения транзакции пользователь видит только согласованные данные. Пользователь не должен видеть несогласованные промежуточные данные.

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

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

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

Итак, блокировки, называемые также синхронизационными захватами объектов, могут быть применены к разному типу объектов. Наибольшим объектом блокировки может быть вся БД, однако этот вид блокировки сделает БД недоступной для всех других приложений, которые работают с данной БД. Следующий тип объекта блокировки – таблицы. Транзакция, которая работает с таблицей, блокирует ее на все время выполнения транзакции. Этот вид блокировки предпочтительнее предыдущего, потому что позволяет параллельно выполнять транзакции, которые работают с другими таблицами.

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

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

8. Переопределение блокировок на уровне запроса. Типы блокировок

Если после имени таблицы в предложении FROM следует одно из перечисленных ключевых слов, запрос вмешивается в работу диспетчера блокировок и применяется заданный тип блокировки:

· NOLOCK- разрешает грязное чтение;

· PAGLOCK- блокировка на уровне страниц;

· ROWLOCK- блокировка на уровне записей;

· TABLOCK-разделяемая блокировка таблицы;

· TABLOCKX- монопольная блокировка таблицы

В настоящее время проблема блокировок является предметом большого числа исследований.

Различают два базовых типа блокировок (синхронизационных захватов):

Разделяемые (нежесткие) блокировки – это режим означает разделяемый захват объекта и используется для выполнения операции чтения объекта. Объекты, заблокированные таким образом, не изменяются в ходе выполнения транзакции и доступны другим транзакциям, но только в режиме чтения;

Монопольные (жесткие) блокировки – не позволяют вообще никому, кроме владельца этой блокировки, обращаться к данным. Эти блокировки используются для команд, которые изменяют содержание или структуру таблицы и действуют до конца транзакции.

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

Однако применение разных типов блокировок приводит к проблеме тупиков. Проблема тупиков возникла при рассмотрении выполнения параллельных процессов в операционных средах и также была связана с управлением разделяемыми (совместно используемыми) объектами. Пример тупика: Пусть транзакция А жестко блокирует таблицу 1, а затем жестко блокирует таблицу 2. Транзакция В, наоборот жестко блокирует таблицу 2, а затем жестко блокирует таблицу 1.

Если обе эти транзакции начали работу одновременно, то после выполнения операций модификации первой таблицы они обе окажутся в бесконечном ожидании: транзакция А будет ждать завершения работы транзакции В и разблокировки таблицы 2, а транзакция В будет безрезультатно ждать завершения работы транзакции А и разблокировки таблицы 1.

Ситуации могут быть гораздо более сложными. Количество взаимно заблокированных транзакций может оказаться гораздо больше. Эту ситуацию каждая транзакция обнаружить самостоятельно не может. Ее должна разрешить СУБД. В большинстве коммерческих СУБД существует механизм обнаружения таких тупиковых ситуаций.

Основой обнаружения тупиковых ситуаций является построение (или постоянное поддержание) графа ожидания транзакций. Граф ожидания может представлять собой направленный граф, в вершинах которого расположены имена транзакций. Если транзакция Т1 ждет окончания транзакции Т2, то из вершины Т1 в вершину Т2 идет стрелка. Дополнительно стрелки могут быть помечены именами заблокированных объектов и типом блокировки.

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

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

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

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

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

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

1. Дайте определение транзакции. Приведите примеры транзакций.

2. Перечислите и охарактеризуйте свойства транзакций.

3. Какие возможны варианты завершения транзакций.

4. Какие операторы языка SQL служат для работы с транзакциями в расширенной модели транзакций?

5. Можно ли в триггерах использовать команды управления транзакциями?

6. Для чего предназначен журнал транзакций?

7. В каких случаях выполняется восстановление БД по журналу транзакций?

8. Какие варианты ведения журналов транзакций существуют?

9. В чем заключаются различия вариантов ведения журнала транзакций: протокола с отложенными обновлениями и протокола с немедленными обновлениями.

10. Какие проблемы возникают при параллельной работе пользователей с БД?

11. Какие объекты БД могут быть заблокированы для реализации принципа изолированности пользователей?

12. Возможно ли задание вида блокировки в запросах?

13. Какие виды захвата объектов несколькими транзакциями существуют? Какие из них являются совместимыми?

14. В чем заключается проблема тупиков?

Похожие публикации