Журнал транзакций. проблемы обработки параллельных транзакций

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

 

Рисунок Журнал транзакций

 

Когда пользователь выполняет запрос на изменение, СУБД автоматически вносит в журнал транзакций одну запись для каждой строки, измененной в процессе выполнения запроса. Эта запись содержит две копии строки. Одна копия представляет собой строку до изменения, а другая – после изменения. Только когда в журнале будет сделана запись, СУБД изменит физическую строку на диске. Затем, если пользователь выполняет инструкцию COMMIT, в журнале отмечается конец транзакции. Если пользователь выполняет инструкцию ROLLBACK, СУБД обращается к журналу и извлекает из него “исходные” копии строк, измененных во время транзакции. Используя эти копии, СУБД возвращает строки в прежнее состояние и таким образом отменяет изменения, внесенные в базу данных в ходе транзакции.

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

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

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

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

Рисунок Проблема пропавшего обновления

 

Перед вводом заказа программа по таблице PRODUCTS проверяют, имеется ли требуемое изделие в наличии. На приведенном рисунке Пользователь 1 начинает вводить заказ от своего клиента на 100 изделий Samsung C110. В то же время Пользователь 2 начинает вводить заказ от своего клиента на 125 тех же изделий. Обе программы для ввода заказов выполняют запрос к таблице PRODUCTS, и каждая из них выясняет, что на складе имеется 139 требуемых изделий – количество, более чем достаточное для выполнения заказа. Пользователь 1 просит клиента подтвердить заказ; затем его копия программы обновляет таблицу PRODUCTS, показывая, что в наличии осталось 39 изделий Samsung C110, и добавляет в таблицу ORDERS новый заказ на 100 изделий. Через несколько секунд Пользователь 2 просит своего клиента подтвердить заказ. Его копия программы обновляет таблицу PRODUCTS, показывая, что на складе осталось 14 изделий Samsung C110, и добавляет в таблицу ORDERS новый заказ на 125 изделий.

Очевидно, что обработка этих двух заказов привела к возникновению противоречия в базе данных. Первое из двух обновлений таблицы PRODUCTS пропало. Заказы от обоих клиентов приняты, но на складе нет достаточного количества изделий для удовлетворения обоих заказов. Более того, таблица PRODUCTS показывает, что в наличии осталось еще 14 изделий. Пример показывает, что проблема “пропавшего обновления” может возникнуть всякий раз, когда две программы извлекают из базы одни и те же данные, используют их для каких-либо расчетов, а затем пытаются обновить эти данные.

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

 

Рисунок Проблема промежуточных данных

 

На этот раз Пользователь 1 снова начинает принимать от клиента заказ на 100 изделий Samsung C110, его копия программы запрашивает таблицу PRODUCTS, выясняет, что в наличии имеется 139 изделий, и обновляет ее, показывая, что после принятия заказа в наличии осталось 39 изделий. Тем временем клиент Пользователя 2 пытается заказать 125 вышеупомянутых изделий. Его копия программы запрашивает таблицу PRODUCTS, выясняет, что в наличии имеется только 39 изделий, и отказывается принять заказ. А клиент Пользователя 1 решает отказаться от заказа, и программа выполняет инструкцию ROLLBACK для отмены транзакции, после выполнения, которой СУБД восстанавливает в таблице число 139. Такое противоречие в базе данных возникло из-за того, что информация, которую извлекла программа Пользователя 2, являлась промежуточной, так как еще не была подтверждена программой Пользователя 1.

3. Проблема несогласованных данных. На рисунке изображена еще одна схема работы программы для обработки заказов.

 

Рисунок Проблема несогласованных данных

 

Пользователь 1 начинает принимать от своего клиента заказ на 100 изделий Samsung C110. Вскоре после этого программа Пользователя 2 выясняет количество этих же изделий на складе. Затем программа Пользователя 2 выполняет запрос о наличии изделий Samsung C100. Тем временем Пользователь 1 принимает заказ на изделия Samsung C110, его программа обновляет соответствующую строку и выполняет инструкцию COMMIT, завершая транзакцию по приему заказа. После некоторых размышлений клиент Пользователя 2 решает заказать изделия Samsung C110, которые ему предлагались вначале. Его программа вновь запрашивает информацию об этих изделиях. Но новый запрос показывает, что в наличии имеется только 39 изделий вместо 139, показанных предыдущим запросом несколько секунд тому назад.

В данном примере, в отличие от двух предыдущих, состояние базы данных правильно отражает реальную ситуацию: в наличии осталось только 39 изделий. Из-за того, что Пользователь 2 увидел данные программы Пользователя 1, ничего особенного не произошло – заказ от Пользователя 1 был успешно принят. Однако с точки зрения Пользователя 2, база данных не была целостной в течение выполняемой им транзакции. В начале транзакции некоторая строка содержала одни данные, а позднее в той же самой транзакции – другие, поскольку “внешние события” нарушили целостное состояние данных. Такая несогласованность может привести к различным проблемам даже в том случае, если программа Пользователя 2 не будет обновлять базу данных, опираясь на результаты первого запроса. Например, если его программа накапливает итоговые суммы или собирает статистические данные, то нет гарантии, что она отражает информацию правильно. В стандарте эта проблема обозначена как “Р2”, или проблема “нестабильных результатов выборки”.

4. Проблема строк – призраков. На нижеследующем рисунке еще раз изображена схема работы программы для обработки заказов.

Рисунок Проблема строк – призраков

 

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

Здесь, как и в предыдущем примере, проблема заключается в несогласованности данных. Состояние базы данных соответствует реальной ситуации, и целостность данных не нарушена, но один и тот же запрос, выполненный дважды в течение одной транзакции, возвращает два различных результата. В предыдущих примерах запрос извлекал одну строку, и противоречивость данных была вызвана выполнением инструкции UPDATE. Выполнение инструкции DELETE могло бы вызвать ту же проблему. В данном примере проблема возникла в результате выполнения инструкции INSERT. В первом запросе дополнительной строки не было, и после выполнения второго запроса сложилось такое впечатление, что она появилась “из ниоткуда”. Проблема строк-призраков, как и проблема несогласованных данных, может привести к противоречивым и неправильным расчетам. В стандарте эта проблема обозначена как “РЗ”.

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

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

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

“Когда две транзакции, A и B, выполняются параллельно, СУБД гарантирует, что результаты их выполнения будут точно такими же, как если бы вначале выполнялась транзакция А, а затем транзакция B; или вначале выполнялась транзакция B, а затем транзакция А”.

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

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

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

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

 

 








Дата добавления: 2015-08-26; просмотров: 2602;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.009 сек.