Какими свойствами обязательно должна обладать транзакция

Транзакции

Транзакцией называется последовательность операций над данными имеющая начало и конец

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

Транзакции должны удовлетворять свойствам ACID

Атомарность. Транзакция либо выполняется полностью либо не выполняется вовсе.

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

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

Устойчивость. После фиксации изменения не должны быть утеряны.

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

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

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

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

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

Уровни изоляции

Чтение фиксированных данных (Read Committed)

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

Пример. Начальное значение баланса 0$. Т1 добавляет к балансу 50$. Т2 считывает значение баланса (50$). Т1 отменяет изменения и завершается. T2 продолжает выполнение располагая неверными данными о балансе.

Решением является чтение фиксированных данных (Read Committed) запрещающее читать данные, измененные транзакцией. Если транзакция A изменила некоторый набор данных, то транзакция B при обращении за этими данными вынуждена ожидать завершения транзакции A.

Повторяемое чтение (Repeatable Read)

Проблема потерянных изменений (Lost Updates). Т1 сохраняет изменения поверх изменений Т2.

Пример. Начальное значение баланса 0$ и две транзакции одновременно пополняют баланс. T1 и T2 читают баланс равный 0$. Затем T2 прибавляет 200$ к 0$ и сохраняет результат. T1 прибавляет 100$ к 0$ и сохраняет результат. Итоговый результат 100$ вместо 300$.

Проблема неповторяемого чтения (Unrepeatable read). Повторное чтение одних и тех же данных возвращает разные значения.

Пример. Т1 читает значение баланса равное 0$. Затем Т2 добавляет к балансу 50$ и завершается. Т1 повторно читает данные и обнаруживает несоответствие с предыдущим результатом.

Повторяемое чтение (Repeatable Read) гарантирует что повторное чтение вернет тот же результат. Данные прочитанные одной транзакцией запрещено менять в других до завершения транзакции. Если транзакция A прочла некоторый набор данных, то транзакция B при обращении за этими данными вынуждена ожидать завершения транзакции A.

Упорядоченное чтение (Serializable)

Проблема фантомного чтения (Phantom Reads). Два запроса выбирающие данные по некоему условию возвращают разные значения.

Пример. T1 запрашивает количество всех пользователей баланс которых больше 0$ но меньше 100$. T2 вычитает 1$ у пользователя с балансом 101$. T1 повторно выполняет запрос.

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

Читайте также:  Какими целебными свойствами обладает крапива и подорожник

Планировщик (Scheduler)

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

Обеспечивает заданный уровень изолированности. Если результат выполнения операций не зависит от их очередности, то такие операции коммутативны (Permutable). Коммутативны операции чтения и операции над разными данными. Операции чтения-записи и записи-записи не коммутативны. Задача планировщика чередовать операции выполняемые параллельными транзакциями так, чтобы результат выполнения был эквивалентен последовательному выполнению транзакций.

Механизмы контроля параллельных заданий (Concurrency Control)

Оптимистический основан на обнаружении и разрешении конфликтов, пессимистический на предотвращении возникновения конфликтов

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

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

Блокировка (Locking)

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

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

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

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

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

С определенной периодичностью производится поиск взаимоблокировок. Один из способов обнаружения — по времени, то есть считать что взаимоблокировка произошла если транзакция выполняется слишком долго. Когда взаимоблокировка найдена, то одна из транзакций откатывается, что дает возможность другим транзакциям участвующим во взаимоблокировке завершиться. Выбор жертвы может быть основан на стоимости транзакций или их старшинстве (Wait-Die и Wound-wait схемы).

Каждой транзакции T присваивается временная метка TS содержащая время начала выполнения транзакции.

Wait-Die.

Если TS(Ti) < TS(Tj), то Ti ждет, иначе Ti откатывается и начинается заново с той же временной меткой.

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

Wound-wait.

Если TS(Ti) < TS(Tj), то Tj откатывается и начинается заново с той же временной меткой, иначе Ti ждет.

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

Пессимистическое решение проблемы взаимоблокировок не позволяет транзакции начать выполнение если есть риск возникновения взаимоблокировки

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

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

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

Двухфазный коммит обеспечивает выполнение коммита на всех репликах БД

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

Читайте также:  Какое свойство воздуха важно для человека

Метод временных меток

Более старая транзакция откатывается при попытке доступа к данным, задействованным более молодой транзакцией

Каждой транзакции назначается временная метка TS соответствующая времени начала выполнения. Если Ti старше Tj, то TS(Ti) < TS(Tj).

Когда транзакция откатывается, ей назначается новая временная метка. Каждый объект данных Q задействованный транзакцией помечается двумя метками. W-TS(Q) — временная метка самой молодой транзакции, успешно выполнившей запись над Q. R-TS(Q) — временная метка самой молодой транзакции, выполнившей запись чтения над Q.

Когда транзакция T запрашивает чтение данных Q возможны два варианта.

Если TS(T) < W-TS(Q), то есть данные были обновлены более молодой транзакцией, то транзакция T откатывается.Если TS(T) >= W-TS(Q), то чтение выполняется и R-TS(Q) становится MAX(R-TS(Q), TS(T)).

Когда транзакция T запрашивает изменение данных Q возможны два варианта.

Если TS(T) < R-TS(Q), то есть данные уже были прочитаны более молодой транзакцией и если произвести изменение, то возникнет конфликт. Транзакция T откатывается. Если TS(T) < W-TS(Q), то есть транзакция пытается перезаписать более новое значение, транзакция T откатывается. В остальных случаях изменение выполняется и W-TS(Q) становится равным TS(T).

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

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

Thomas write rule — вариация метода временных меток при которой данные обновленные более молодой транзакцией запрещено перезаписывать более старой

Транзакция T запрашивает изменение данных Q. Если TS(T) < W-TS(Q), то есть транзакция пытается перезаписать более новое значение, транзакция T не откатывается как в методе временных меток.

Источник

Управление транзакциями.

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

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

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

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

Приведем одну из возможных последовательностей действий, нужных для выполнения этой операции:

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

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

3. Уменьшить значение остатка на счете-источнике. Это операция модификации данных.

Читайте также:  Какие вещества проявляют восстановительные свойства

4. Увеличить значение остатка на счете-получателе. Это операция модификации данных.

5. Создать запись о проведенной операции в журнале операций. Это операция создания новой записи.

Можно предложить и другие варианты выполнения этой операции, но главным является то, что вся эта последовательность либо должна выполняться, либо ни одна из операций не должна быть выполнена. Очевидно, что если мы остановимся, скажем, на шаге 4, то средства со счета-источника просто исчезнут – будут списаны «в никуда». То есть, согласованность данных будет нарушена. Кроме того, необходимо гарантировать, что в процессе выполнения транзакции с задействованными в ней счетами не будут выполняться никакие другие операции. В самом деле, если после того, как мы проверили достаточность средств на счете-источнике, эти средства будут с него списаны другой операцией – мы опять-таки скорее всего столкнемся с нарушениями согласованности данных.

Разумеется, поддержка механизма транзакций технически может быть и очень сложной – при наличии десятков и сотен пользователей и тысяч обращений к данным обеспечить независимость этих обращений друг от друга, а также возможность отмены операций и возврата базы данных к исходному состоянию непросто. Для реализации этого механизма могут задействоваться различные средства, но есть свойства, которыми должны обладать транзакции и поддерживающая их система. Обычно для обозначения этих свойств используют аббревиатуру ACID – Atomicity, Consistency, Isolation, Durability. В переводе на русский – Атомарность, Согласованность, Изолированность и Долговечность. Рассмотрим эти свойства подробнее.

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

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

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

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

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

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

Источник