Глава 2. Механизмы поддержки транзакций в различных СУРБД

Oracle

Системный журнал транзакций в Oracle состоит из двух частей – оперативной и архивной. Оперативная часть, в свою очередь, содержит два журнала (для повышения надежности каждый из журналов обычно ведется в двух экземплярах). В каждый момент времени один из журналов заполняется информацией о транзакциях сервера, а другой в это время копируется в архивный журнал, который организован на отдельном носителе большого объема. Этот процесс схематически показан на рис. 2.

 

Рис. 2. Заполнение журнала транзакций в Oracle  

 

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

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

Рассмотрим кратко, как организованы блокировки в Oracle.

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

Во-вторых, поддерживается не только полная блокировка ресурса (эксклюзивная блокировка - обозначается как Х-блокировка), но и разделяемая (Shared) блокировка (обозначается как S-блокировка). Разделяемая блокировка позволяет нескольким транзакциям одновременно использовать ресурс, но пока не снята разделяемая блокировка, сервер не может наложить на этот ресурс эксклюзивную блокировку.


 

MS SQL Server

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

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

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

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

Для некоторых операций, таких как CREATE INDEX, Microsoft SQL Server не ведет протоколирование для каждой новой страницы. Вместо этого SQL Server записывает достаточно информации, чтобы определить, как CREATE INDEX отработал, и принять решение о том фиксировать изменения или сделать откат.

Если опция базы данных select into/bulkcopy установлены в TRUE, Microsoft SQL Server не записывает в журнал транзакций информацию о следующих операциях: операции массового копирования, Select into, WRITETEXT и UPDATETEXT. Поскольку эти операции не регистрируются в журнале транзакций, то SQL Server не сможет использовать восстановление журнала транзакций для отмены этих операций. Если же выполняется одно из этих действий, когда опции select into/bulkcopy установлены в TRUE, то необходимо убедиться в том, что резервная копия содержала изменения, сделанные этими операциями, в случае если потребуется последующее восстановление.

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

После того как Microsoft SQL Server заканчивает резервное копирование журнала транзакций, он усекает его неактивную часть, тем самым высвобождая место. SQL Server может повторно использовать высвобожденное место, т.к. журнал транзакций непрерывно растет и ему требуется свободное пространство. Активная часть журнала содержит изменения, которые были сделаны в базе и еще не зафиксированы на диске.

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

Microsoft SQL Server пытается запустить процесс контрольной точки всякий раз, когда журнал транзакций заполняется более чем на 70 процентов, или при получении ошибки переполнения журнала транзакций, а также при остановке SQL Server (если используется SHUTDOWN WITH NOWAIT).

 


PostgreSQL

В PostgreSQL используется механизм MVCC (Multi-Version Concurrency Control), позволяющий выполнять команды SQL в отложенных транзакционных блоках. Основная идея MVCC заключается в том, что в базе данных допускается существование нескольких «версий» одного и того же элемента данных. Это позволяет улучшить ряд характеристик СУБД, наиболее важных для приложений, относящихся к следующим категориям:

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

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

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

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

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

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


 

MySQL

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

Изначально MySQL работала без механизма транзакций. Транзакции появились сравнительно недавно, и только для таблиц расширенного типа: InnoDB, Berkeley DB, Gemini. Но прежде чем переходить на использование таблиц этих типов и отказываться от MyISAM, надо отметить, что применение транзакций не всегда оправдано. Во многих случаях табличных блокировок бывает вполне достаточно. Так что, в отличие от других СУБД, MySQL предоставляет возможность выбора: работать с более медленными таблицами, поддерживающими транзакции, или с более быстрыми, в которых транзакции не используются.

Теоретически СУБД должна обеспечивать полную изоляцию транзакций. На практике же вводится несколько уровней изоляции, самым высоким из которых является полная изоляция. В СУБД MySQL выбор уровня осуществляется с помощью инструкции SET TRANSACTION. В стандарте SQL определены четыре уровня изоляции: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ и SERIALIZABLE.

System R

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

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

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

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

Рассмотрим, как осуществляется в System R восстановление базы данных после мягкого сбоя.

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

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

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

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

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

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

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

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


Заключение

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

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


 

Список литературы

1. Полякова Л. Н. Основы SQL, 2004

2. Уорсли Дж., Дрейк Дж. PostgreSQL для профессионалов, 2003

3. Кузнецов С. SQL: язык реляционных баз данных, 2006

4. Горев А., Ахаян Р., Макашарипов С. Эффективная работа с СУБД, 2006

5. Кодд Дж. Базы данных, 2006

6. http://kharchuk.ru/Статьи/9-Прочее/53-mysql-transactions

7. http://doc.sumy.ua/db/osbd/glava_31.htm

8. http://wiki.mvtom.ru/index.php/Модели_транзакций

9. http://bd-sql-xml.org.ua/index.php/oracle/81-mekhanizmy-subd-oracle-dlya-podderzhki-tranzaktsij

10. http://all4study.ru/sql/upravlenie-tranzakciyami-v-sql.html

11. http://ru.wikipedia.org/wiki/SQL

12. http://www.sql.ru/articles/mssql/03090102transactionlogguidelines.shtml