Россия, Москва |
Транзакции в базах данных
6.4.3 Блокирование
По степени разделяемости блокируемых ресурсов различают:
- Монопольные блокировки (eXclusive locks или X-locks), называемые еще блокировками записи. Они не разрешают другим транзакциям доступ к блокированному ресурсу.
- Разделяемые блокировки (Shared locks или S-locks) иначе блокировки чтения. Разрешают совместный доступ к блокированному ресурсу.
Виды блокировок
Блокировки различают еще по размерам блокируемого ресурса: поле записи, запись, отношение, страница (блок базы), группа отношений, вся база. Забегая вперед, отметим, что в современных СУБД используется два способа хранения таблиц — строчный и столбцовый. Чаще данные хранятся строками. В этом случае минимальный объем блокировки — строка. В столбцовых базах —поле. Выполняется свойство иерархичности. Если объект верхнего уровня обладает блокировкой, то такой же блокировкой обладает его подобъект нижнего уровня.
Взаимодействие блокировок:
- Имеется X-блокировка. Запросы на любые блокировки от других транзакций будут отменены.
- Имеется S-блокировка. Запрос на X-блокировку отвергается. Запрос на S-блокировку принимается.
Рассмотрим доступ по чтению и записи. Возможный протокол доступа к данным по чтению и записи с блокировками определяется следующими правилами:
- Перед чтением объекта базы транзакция должна наложить на него S-блокировку.
- Перед записью объекта базы транзакция должна наложить на него X-блокировку. Если перед этим транзакция выполняла S-блокировку этого объекта, то она заменяется X-блокировкой.
- Если объект уже заблокирован X-блокировкой другой транзакции, то любая другая блокировка отвергается и транзакция переводится в состояние ожидания до тех пор, пока мешающая блокировка не снимется.
- Если объект уже заблокирован S-блокировкой другой транзакции, то другая S-блокировка принимается, а X-блокировка отвергается.
- X-блокировки сохраняются до конца транзакции. S-блокировка снимается по завершении чтения.
Если транзакция B начинается позже транзакции A, то успешность блокирования объекта базы транзакцией B определяется следующей матрицей совместимости блокировок (таблица 6.11):
Транзакция A наложила блокировку | Транзакция B пытается наложить блокировку | |
S-блокировку | X-блокировку | |
S-блокировку | + | - (конфликт R-W) |
X-блокировку | - (конфликт W-R) | - (конфликт W-W) |
Транзакция-читатель мешает транзакции-писателю |
Сделаем важный вывод: при использовании разграничения доступа с помощью S- и X-блокировок транзакции-читатели могут мешать транзакциям-писателям. Транзакции-писатели всегда мешают другим транзакциям-писателям и транзакциям-читателям.
Как выполняются блокировки в транзакциях Cache ObjectScript? С помощью команды LOCK имеющей формат:
L[OCK] [+|-] список_имен_блокируемых_ресурсов
Пример: LOCK ^a(1) или, сокращенно, L ^а(1) блокирует узел ^а(1).
Формат | Действие |
LOCK | Отмена всех блокировок |
LOCK список_имен | Снимает все блокировки, затем блокирует по |
одному имени из списка | |
LOCK +имя | Инкрементальная блокировка - добавление |
блокировки к уже существующим блокировкам | |
LOCK -имя | Удаляет блокировку |
Команда LOCK ^а(1), ^b(3) эквивалентна LOCK ^а(1) LOCK +^b(3). Использование времени ожидания (для инкрементальных блокировок рекомендуется всегда): LOCK ^а(1):5
Попытка блокировать прерывается, если прошло 5 секунд, а блокировка не завершилась. При этом устанавливается значение $TEST=0. Просмотреть текущие блокировки можно двумя способами:
-
Программой ^LOCKTAB, запускаемой из терминала. Пример:
USER>LOCK ^a(0) USER>ZN "%SYS" %SYS>DO ^LOCKTAB
-
С помощью портала управления системой - рисунок 6.6
Результат выполнения последней команды:
Node Name: WS111 LOCK table entries at 11:10PM 11/28/2012 1176464 bytes usable, 1178528 bytes available. Entry Process X# S# Flg W# Item Locked 1) 1188 1 ^[ "^^c:\intersystems\trycache\mgr\"]%SYS("CSP","Daemon") 2) 3400 1 ^[ "^^c:\intersystems\trycache\mgr\"]TASKMGR 3) 2640 1 ^[ "^^c:\intersystems\trycache\mgr\user"]a Command=>
Любая СУБД блокирует как минимум свой словарь, поэтому вместо одной установленной нами блокировки на ресурс ^а(0) мы видим еще и другие блокировки.
Справку по ^LOCKTAB можно получить командой HELP, сокращенно H. Выход из программы осуществляет команда Q[UIT].
Блокировки распространяются в дереве на всех потомков и предков.
Пример:
Создадим глобал S ^a(1)=1, ^a(1,1)=11, ^a(2)=2, ^a(2,1)=21
Команда L ^a(1) блокирует не только ^а(1), но и ^а,^а(1,1). Обратите внимание на то, что блокируются и локалы и глобалы. При этом LOCK не проверяет существование узлов. Поэтому блокировка создается и для несуществующих узлов.
Рекомендация: Для удобства тестирования желательно, чтобы количество инкрементальных блокировок узла совпадало с количеством инкрементальных деблокировок.
Пример: Если выполнена команда L +(^a,^b,^c), а затем L ^b, то останется заблокированным только ^b.
6.4.4 Тупики (Clinch, Deadlock)
При использовании транзакций возникают побочные и очень неприятные явления. Это тупики. Возникают они, когда две или более транзакций пытаются блокировать монопольно одни и те же ресурсы. Не получая доступа к ресурсам, конфликтующие транзакции могут зависнуть на неопределенное время. В СУБД этого допускать нельзя. Нужно как-то разрешить конфликт. Например, через некоторое время после возникновения тупика конфликтующие транзакции откатывают, но затем их вновь запускают в случайно выбранные моменты времени, совсем как при разрешении конфликтов в сети Ethernet.
В транзакции могут исполняться следующие виды операций:
- БРi — блокирование ресурса i;
- РРi — разблокирование ресурса i;
- действие над ресурсом i. (Чтение или манипулирование данными).
Ситуация тупика возникает при попытке двух транзакций блокировать одни и те же ресурсы:
С момента времени T продолжение работы транзакций невозможно, если СУБД не применит какой-нибудь алгоритм разрешения конфликта.
Использование блокировок позволяет решать проблемы параллельного доступа. Пример использования блокировок для устранения чтения "грязных" данных — в таблице 6.13
Транзакция 1 | Время | Транзакция 2 |
S-блокировка Acc успешна | t1 | |
Чтение Acc | t2 | |
t3 | S-блокировка Acc успешна | |
t4 | Чтение Acc | |
Попытка записи Acc (X- | t5 | |
блокировка отвергается) | ||
Ожидание | t6 | Попытка записи Acc (X- |
блокировка отвергается) | ||
Ожидание | t7 | Ожидание |
X-блокировки отвергаются, так как уже установлены две S-блокировки. Обе транзакции ожидают завершения другой транзакции. Возникает тупик, зато феномен чтения "грязных" данных отсутствует. Если же S-блокировка транзакции 2 будет выполнена после успешной X-блокировки транзакции 1, то транзакция 2 будет ждать завершения транзакции 1.
Многоверсионные данные
Мы видели, что в СУБД с единственной версией данных транзакции-читатели могут мешать транзакциям-писателям (конфликты R-W).
В многоверсионных СУБД транзакциям-читателям предоставляются свои версии данных, получаемые откатом части схемы базы до последнего согласованного состояния. Такие транзакции не блокируют данных и потому не мешают транзакциям-писателям.
Например, многоверсионная СУБД Oracle создает и поддерживает номер изменения системы SCN (system change number). Каждая завершенная транзакция увеличивает его. Поэтому можно считать SCN уникальным идентификатором завершенной транзакции.
В заголовок блока данных записывается SCN завершившейся транзакции, которая изменяла блок последней.
При чтении результирующее множество запроса формируется следующим образом:
- Анализируется текущий SCN. Будем его называть SCN запроса.
- При считывании блока данных Oracle сравнивает SCN запроса с SCN из заголовка этого блока, чтобы определить, читать ли сам блок или воспользоваться сегментом отката, в который заносились все читаемые блоки, так что вносимые изменения в них не отражаются.
Возможны два варианта
- если SCN блока меньше или равен SCN запроса, то последняя изменявшая блок транзакция завершилась до начала чтения; в этом случае читается сам блок;
- если же SCN блока больше SCN запроса, то изменения блока завершились после начала чтения; в этом случае из сегмента отката читается нужный блок, сохраненный в исходном состоянии до начала чтения.
Если не используется многоверсионность и не применяются блокировки, возможно получение несогласованных данных.