Кубанский государственный университет
Опубликован: 24.12.2013 | Доступ: свободный | Студентов: 681 / 8 | Длительность: 24:28:00
Лекция 6:

Транзакции в базах данных

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >
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):

Таблица 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).

Таблица 6.12. Форматы команды LOCK
Формат Действие
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

     Список блокировок в портале управления системой

    увеличить изображение
    Рис. 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. (Чтение или манипулирование данными).

Ситуация тупика возникает при попытке двух транзакций блокировать одни и те же ресурсы:

 Ситуация тупика

Рис. 6.7. Ситуация тупика

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

Использование блокировок позволяет решать проблемы параллельного доступа. Пример использования блокировок для устранения чтения "грязных" данных — в таблице 6.13

Таблица 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 завершившейся транзакции, которая изменяла блок последней.

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

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

Возможны два варианта

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

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

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >