Informix Logo


Управление совместным доступом

Василий Шульженко
Преподаватель учебного центра компании SoftLine
vasilis@softline.kiev.ua


Типы совместного доступа

  • Совместный доступ по чтению

(Операторы SELECT)

  • Совместный доступ по изменению

(Операторы INSERT, DELETE и UPDATE)

Управление совместным доступом (Concurrency Control) влияет на то, как данные просматриваются и изменяются пользователями, которые одновременно обращаются к одной и той же информации. Например, хотите ли Вы, чтобы один пользователь мог просматривать заказ, изменяемый в настоящее время другим пользователем? Хотите ли Вы, чтобы заказ, просматриваемый одним пользователем, был доступен для изменения другому пользователю?

Существуют два класса управления совместным доступом:

  • В первый класс входит совместный доступ, возникающий при обращении к базе данных только по чтению, например, посредством операторов SELECT. Это часто называется уровнем изоляции (isolation level). Существует 4 уровня изоляции.
  • Второй класс - это совместный доступ, возникающий при изменении содержимого записей в базе данных, посредством, например, операторов INSERT, DELETE или UPDATE.

INFORMIX управляет совместным доступом используя блокировки. Существует три типа блокировок, которые могут быть использованы:

  • Исключительная блокировка (exclusive lock): Никакие другие блокировки не могут быть применены к данным, к которым применена исключительная блокировка.
  • Разделяемая (совместная) блокировка (shared lock): Такие блокировки применяются процессами, которые читают данные. Разделяемые блокировки не могут быть применены к данным, к которым применена исключительная блокировка. Допускается применение более одной разделяемой блокировки к одним и тем же данным.
  • Обновляемая (изменяемая) блокировка (update lock): Эти блокировки похожи на разделяемые, исключая то, что позже они могут быть переведены в исключительные.

Совместный доступ при чтении:
четыре уровня изоляции

Уровни изоляции при чтении:

  • DIRTY READ - "грязное" чтение (недостоверное чтение)
  • COMMITTED READ- подтвержденное (завершенное, достоверное) чтение
  • CURSOR STABILITY- стабильность (устойчивость) курсора
  • REPEATABLE READ- повторяемое чтение

INFORMIX-OnLine Dynamic Server обеспечивает перечисленные выше четыре уровня изоляции при чтении. (Базы данных INFORMIX-SE обеспечивают только DIRTY READ).

Для поддержания этих уровней INFORMIX-OnLine Dynamic Server использует разделяемые блокировки. Разделяемые блокировки позволяют другим процессам читать данные, но не позволяют обновлять их. Все эти уровни изоляции ниже рассматриваются подробнее.

DIRTY READ

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

В случае применения уровня изоляции DIRTY READ Ваш процесс вообще не изолируется. Никакие блокировки не используются и процесс не занимается проверкой наличия других блокировок перед чтением строки. Во время чтения данных Вы можете просматривать содержимое любых записей даже если они содержат неподтвержденные изменения. Такие данные называются "грязными" данными.

Важно: Строки, содержащие "грязные" данные, могут быть фантомными. Фантомная строка - это запись, которая была вставлена в базу данных во время выполнения транзакции, которая, в свою очередь, была до своего завершения откатана назад. Хотя фантомные строки никогда не существуют постоянно, они будут видны процессу, использующему уровень изоляции DIRTY READ.

DIRTY READ может быть полезным когда:

  • Таблица является статичной.
  • 100% точность является менее важной, чем скорость и отсутствие конкуренции.
  • Нет возможности ждать освобождения блокировок.
  • Вся база данных или читаемая таблица заблокирована Вами в исключительном режиме.

Примечание: Недостоверное чтение имеет наибольшую эффективность - никогда не ждет и не заставляет ждать других!

COMMITTED READ

Сервер базы данных производит чтение записей из базы данных после того, как проверит, что к строкам может быть применена блокировка

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

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

COMMITTED READ может быть полезным в следующих случаях:

  • просмотрах
  • запросах
  • отчетах, дающих общую информацию

CURSOR STABILITY

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

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

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

Операторы SELECT, использующие уровень изоляции CURSOR STABILITY могут быть полезны при:

  • просмотре (поиске)
  • запросах
  • отчетах, дающих оперативную информацию

Например, операторы SELECT, использующие уровень изоляции CURSOR STABILITY, полезны при построении детализированных отчетов, таких как ценовые котировки или в системах слежения. Если используется уровень изоляции CURSOR STABILITY и курсоры не используются, CURSOR STABILITY ведет себя так же, как и COMMITTED READ (разделяемая блокировка в действительности не применяется).

REPEATABLE READ

Сервер базы данных применяет блокировки ко всем рассматриваемым
строкам, которые удовлетворяют запросу.

Уровень изоляции REPEATABLE READ применяет разделяемую блокировку ко всем записям, рассматриваемым сервером базы данных; эти блокировки удерживаются до тех пор, пока транзакция не будет завершена.

При использовании REPEATABLE READ вы имеете изоляцию высокого уровня. При явном проведении транзакций гарантируется, что строка будет существовать не только в то время, которое Вы ее просматриваете, но и тогда, когда позже ее потребуется прочитать повторно. Никакой другой процесс не сможет изменить (UPDATE или DELETE) эту запись, пока Ваша транзакция не будет полностью завершена. REPEATABLE READ может быть полезен тогда, когда Вы должны обрабатывать все читаемые строки как одну логическую единицу или гарантировать, что значения не будут изменены. Например:

  • критические, агрегирующие вычисления (например, подсчет бухгалтерского баланса)
  • координированный поиск по нескольким таблицам сразу (например, система резервирования билетов)

Внимание: Важно заметить, что в случае применения REPEATABLE READ блокируются все рассматриваемые строки; это включает в себя также строки, которые не удовлетворяют критерию отбора, но должны быть прочитаны для того, чтобы определить их непригодность. Например, если Вы используете уровень изоляции REPEATABLE READ в запросе, который требует проведения последовательного чтения таблицы (например, если индексы отсутствуют), то заблокированными окажутся все строки и эти блокировки будут удерживаться в течении всего времени проведения транзакции.

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

Совет: Используйте уровень изоляции REPEATABLE READ только в запросах, которые могут выполнять чтение по индексу.

Установка уровня изоляции

Примеры:

SET ISOLATION TO DIRTY READ;

SET ISOLATION TO COMMITTED READ;

SET ISOLATION TO CURSOR STABILITY;

SET ISOLATION TO REPEATABLE READ;

Чтобы использовать изоляцию процессов Ваша база данных должна поддерживать ведение журнала. Для выбора уровня изоляции используется оператор SET ISOLATION. Синтаксис оператора показан выше.

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

Будучи однажды установленным уровень изоляции действует все время Вашего сеанса работы. Он может быть переустановлен в другое значение во время того же сеанса работы и даже во время проведения (внутри) транзакции.

SET TRANSACTION

SET TRANSACTION

SET ISOLATION

Read Uncommitted Dirty Read
Read Committed Committed Read
Not Supported Cursor Stability
(ANSI) Repeatable Read (INFORMIX) Repeatable Read
Serializable (INFORMIX) Repeatable Read

 

Оператор SET TRANSACTION соответствует стандарту ANSI SQL-92. Этот оператор похож на оператор INFORMIX SET ISOLATION, однако, оператор SET ISOLATION не является ANSI- совместимым оператором и не обеспечивает режимов доступа.

Уровни изоляции, которые можно установить с помощью оператора SET TRANSACTION, являются почти параллельными тем, что устанавливаются оператором SET ISOLATION, как показано выше в таблице.

Другое отличие между операторами SET TRANSACTION и SET ISOLATION заключается в характере изменения уровней изоляции во время транзакции. Оператор SET TRANSACTION может быть выполнен для каждой транзакции только один раз. Посредством оператора SET ISOLATION можно изменять уровень изоляции несколько раз уже после того, как транзакция началась.

Уровни изоляции по умолчанию

INFORMIX

ANSI

Описание

DIRTY READ READ UNCOMMITTED Уровень изоляции по умолчанию, устанавливаемый в базе данных без ведения журнала.
COMMITTED READ READ COMMITTED Уровень изоляции по умолчанию, устанавливаемый в несовместимой с ANSI базе данных с ведением журнала.
REPEATABLE READ SERIALIZABLE Уровень изоляции по умолчанию, устанавливаемый в ANSI совместимой базе данных.

 

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

Степень допустимого взаимного влияния

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

Описание

Dirty Read или Read Uncommitted Позволяет этому процессу видеть DIRTY данные.
Committed Read или Read Committed Не позволяет этому процессу видеть DIRTY данные.
Cursor Stability Не позволяет другим процессам изменять текущую запись.
(ANSI) Repeatable Read или Serializable Не позволяет другим процессам изменять любые строки, уже просмотренные текущим процессом, пока он не завершит работу с ними.

 

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

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

Уровни детализации блокировок:

  • Уровень базы данных
  • Уровень таблицы
  • Уровень страницы
  • Уровень строки
  • Уровень ключа

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

INFORMIX-OnLine обеспечивает пять различных уровней детализации блокировок, наиболее грубым из них является уровень базы данных; максимально точным - блокировка записей таблиц. Блокировка уровня ключа накладывается на элементы индексов.

Блокировка уровня базы данных

DATABASE STORES EXCLUSIVE;

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

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

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

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

Блокировка уровня таблицы

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

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

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

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

Блокировка таблиц системного каталога не допускается.

Если Ваша база данных работает с транзакциями, блокировка уровня таблицы может применяться только внутри транзакции. Таким образом, удостоверьтесь, что вы выполнили оператор BEGIN WORK перед тем, как пытаться заблокировать таблицу. Таблица будет автоматически разблокирована по окончании транзакции.

Блокировка таблицы в разделяемом режиме

LOCK TABLE customer IN SHARE MODE;

В случаях, когда желательно дать другим пользователям возможность чтения данных, однако запретить им изменение данных таблицы, следует использовать оператор LOCK TABLE совместно с операцией IN SHARE MODE.

Когда таблица заблокирована в режиме SHARE, другим пользователям разрешается пользоваться оператором SELECT для чтения данных из таблицы, однако они не будут иметь возможности выполнять операторы INSERT, DELETE или UPDATE над записями таблицы или оператор ALTER над самой таблицей.

Важно: Необходимо помнить, что блокировка таблицы в SHARE MODE не запрещает применять блокировки для выполнения операций обновления записей тем же процессом. Во избежание применения исключительных блокировок записей в дополнение к разделяемой блокировке таблицы необходимо использовать блокировку таблицы в EXCLUSIVE MODE.

Блокировка таблицы в исключительном режиме

LOCK TABLE orders IN EXCLUSIVE MODE;

Если является необходимым запретить другим пользователям обращаться к таблице каким бы то ни было образом, требуется применить к таблице блокировку EXCLUSIVE MODE.

В EXCLUSIVE MODE другие пользователи не будут иметь возможности пользоваться операторами SELECT (исключая случаи использования уровня изоляции DIRTY READ), INSERT, UPDATE и DELETE по отношению к записям таблицы до тех пор, пока таблица не будет разблокирована.

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

В случае если таблица содержит BLOB-объекты, которые содержатся в blobspace: если таблица заблокирована в EXCLUSIVE MODE, и выполнение изменений касается значений типа BLOB, на каждый BLOB-объект накладывается исключительная блокировка. Эти блокировки снимаются автоматически. На одну страницу blobspace используется две блокировки. Если BLOB'ы хранятся в таблице, дополнительные блокировки не применяются.

Разблокирование таблицы

UNLOCK TABLE customer

Оператор UNLOCK TABLE восстанавливает возможность обращения к заблокированной перед этим таблице. Этот оператор используется в случаях, когда необходимость в ограничении возможности доступа к таблице другим пользователям отпадает.

Внимание: В тех случаях, когда таблица была заблокирована во время транзакции, выполнение оператора UNLOCK TABLE не допускается и возвращает ошибку, окончание транзакции (посредством операторов COMMIT или ROLLBACK) снимает блокировку автоматически.

Установка режима блокировки

SET LOCK MODE TO WAIT Ждать, пока блокировка не будет снята
SET LOCK MODE TO NOT WAIT Не ждать, пока блокировка будет снята
SET LOCK MODE TO WAIT 20 Ждать 20 секунд, пока блокировка не будет снята

Оператор SET MODE используется для определения, должен ли вызов, изменяющий или удаляющий строку в таблице, ожидать снятия блокировки этой строки.

Опция TO NOT WAIT заставляет оператор возвратить ошибку, если запись, которую требуется изменить или удалить (или выбрать для обновления (SELECT row FOR UPDATE)), заблокирована другим процессом. Этот режим устанавливается по умолчанию.

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

Блокировки уровня страницы и строки

  • Определяется во время создания таблицы
  • Блокировка уровня страницы блокирует всю страницу данных
  • Блокировка уровня строки блокирует только запись (строку таблицы)
  • Компромисс между совместным доступом и использованием ресурсов

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

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

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

  • количество блокировок превышает максимально допустимое
  • накладные расходы на управление блокировками становятся значительными

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

Доступ с использованием блокировок:
уровень строки/страницы

 

 

A (удерживает блокировки)

B

X

U

S

нет

Запрошено

X

нет

нет

нет

да

U

нет

нет

да

да

S

нет

да

да

да

Приведенная таблица показывает взаимодействие между уже наложенными блокировками и запрошенными блокировками, по отношению к одной и той же строки/странице двумя разными процессами. На горизонтальной оси показаны блокировки, которые могли бы быть наложены процессом A. На вертикальной оси показаны блокировки, запрошенные процессом B. Матрица показывает результат запроса на применение блокировки (да - блокировка разрешена, нет - блокировка запрещена).

Обнаружение тупиков

Когда множество процессов работают с одними и теми же записями таблицы, возможно возникновение мертвых точек (deadlock).

Процесс A заблокировал строка x. После этого он собирается заблокировать вторую запись, y. Однако строка y уже заблокирована другим пользователем, процессом B. Если процесс A ожидает снятия блокировки, он будет ждать, пока процесс B не разблокирует строка y. Тем временем процесс B удерживает заблокированной строка y, и собирается заблокировать строка x. Она уже заблокирована другим пользователем, и если процесс B ожидает снятия блокировки, он будет ждать, пока процесс A не снимет блокировку строки x. Другими словами, A ждет B и B ждет A. Это мертвая точка и оба процесса будут ждать вечно. Эта ситуация может также возникать и для большего количества пользователей. Мертвые точки являются серьезной проблемой, поскольку она могут заморозить большую часть активности базы данных. INFORMIX содержит механизм, позволяющий определять мертвые точки и предотвращать их возникновение. Следующий параграф описывает, как это делается.

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

The ISAM error code returned is: -143 ISAM error: deadlock detected

Блокировка значения ключа

Блокировка значения ключа - метод блокировки B+ дерева, в котором блокируется ключ, который обновляется, вставляется или удаляется.

значение
ключа
идентификатор
записи (rowid)
флаг удаления

   0 = не удален  1 = удален

INFORMIX-OnLine Dynamic Server использует метод блокировки B+ дерева, называемый блокировкой значения ключа. Для оператора DELETE, например, это означает, что OnLine в действительности блокирует только ключевое значение, которое удаляется в течение транзакции. Для того чтобы это сделать, OnLine не удаляет значение ключа в действительности, однако помечает его, как удаленное, путем установки системного флага удаления, который физически расположен в каждом элементе индекса.

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

Исключения

Блокировки значений ключей не выполняются в тех случаях, когда истинными являются следующие утверждения:

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

Блокировки значения ключа: Пример 1

Пользователь 1:

begin work;

delete from customer where lname = "Sadler";

 

Пользователь 2:

begin work;

insert into customer values(..,"Smith",..);

После удаления Sadler: После вставки Smith:

lname

Блокировка

Флаг удаления

lname

Блокировка

Флаг удаления

Sadler

X

1

Sadler

X

1

     

Smith

X

0

Vector

 

0

Vector

 

0

Приведенная таблица показывает пример того, как работает блокировка значения ключа.

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

Второй пользователь вставляет строку, содержащую фамилию Smith. Значение ключа, соответствующее вставленной строке, блокируется в исключительном режиме.

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

Блокировки значения ключа: Пример 2

Пользователь 1:

begin work;

insert into customer values(..,"Richards",..)

Пользователь 2:

begin work;

delete from customer where lname = "Pauli"

После вставки Richards: После удаления Pauli:

lname

Блокировка

Флаг удаления

lname

Блокировка

Флаг удаления

Pauli

 

0

Pauli

X

1

Richards

X

0

Richards

X

0

Sadler

 

0

Sadler

 

0

В приведенном выше примере первый пользователь вставляет, содержащую ключевое значение Richards, строку в таблицу customer. Ключевое значение блокируется в исключительном режиме.

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

Другие пользователи, читающие данные

Если другие пользователи читают ключи и обращаются к ключу, флаг удаления которого установлен в 1, такой пользователь обязан определить существование блокировки. Если блокировка существует, это означает, что удаление не было завершено и при этом генерируется ошибка (или начинается ожидание снятия блокировки, если использовано SET LOCK MODE TO WAIT). Если блокировка отсутствует, это означает, что транзакция была подтверждена и рассматриваемый ключ в действительности не существует. Ключ пропускается.

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

Repeatable Reads

Если пользователь выполняет INSERT при уровне изоляции REPEATABLE READ

Пользователь 1:

begin work;

set isolation to repeatable read;

select * from customer where customer_num >= 104

customer_num

Блокировка

Флаг удаления

103

 

0

105

SR

0

 

Пользователь 2 (этот оператор завершится неудачно):

insert into customer(customer_num) values(104);

INFORMIX-OnLine Dynamic Server использует два типа блокировок для управления уровнем изоляции REPEATABLE READ:

  • Оператор SELECT, выполняющий повторяемое чтение, применяет SR (Shared Repeatable read) блокировку к каждому рассмотренному им ключу.
  • Оператор DELETE применяет XR-блокировку к удаляемым им ключам.
  • Оператор INSERT применяет XR-блокировку к текущему ключевому элементу и проверяет блокировку примыкающего ключа.

Неудачи могут возникнуть только в тех случаях, когда примыкающий ключ заблокирован SR-блокировкой (это показывает, что к этой строке было применено разделяемое повторяемое чтение) или XR-блокировкой (это означает, что эта строка была вставлена или удалена при повторяющемся (REPEATABLE) чтении). Приведенный выше пример показывает такое чтение с SR-блокировкой, примененной к заказчику номер 105. Другой пользователь пытается добавить заказчика номер 104 и получает ошибку, потому что примыкающий ключ заблокирован SR-блокировкой. Вставка завершается неудачно, несмотря на ее уровень изоляции.

Эта специальная проверка на уровень изоляции REPEATABLE READ необходима, поскольку этот уровень должен защищать совокупность записей, которые он прочитал. Во всех других отношениях, XR-блокировка работает как X-блокировка и SR-блокировка работает как S-блокировка. Выполнение оператора вставки с уровнем изоляции REPEATABLE READ будет завершено успешно в том случае, когда к примыкающему ключу применена X-блокировка (но не XR).

Блокировки, при использовании которых применяется блокировка значений ключа

 

Операция

Блокировка текущего элемента

Блокировка следующего элемента

SELECT S блокировка (CS)

S проверка блокировки (CR)

SR блокировка (RR)

Нет

INSERT X блокировка

XR блокировка (RR)

Проверить наличие XR или SR блокировки

DELETE X блокировка

XR блокировка (RR)

Нет

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

CR Committed read
CS Cursor stability
RR Repeatable read

Что происходит после DELETE?

Постольку оператор DELETE не удаляет связанные ключи из индекса, должен существовать некий механизм, периодически проводящий удаление ключей. Этот механизм известен как btcleaner thread.

Когда элемент удаляется, взводится флаг удаления. Во время подтверждения транзакции в специальную область памяти общего пользования (называемую btree cleaner pool) помещается запрос на удаление элемента. Запрос представляет собой 20 байтовую структуру, содержащую номер tblspace, номер страницы и номер удаляемого ключа. Btree cleaner pool может содержать только один запрос на удаление для одной и той же страницы. Начальный размер btree cleaner pool равен 1 килобайту, однако, если btree cleaner pool заполнен, к нему добавляется еще 1 килобайт для размещения новых запросов и так далее.

Каждую минуту или каждый раз, когда количество запросов в btree cleaner pool превысит 100, btcleaner thread <просыпается> и считывает запросы из btree cleaner pool. Для каждого запроса btcleaner thread находит страницу и удаляет ключ, помеченный как удаленный. Однако перед удалением btcleaner thread удостоверяется в том, что строка была подтверждена, проверяя ее на наличие блокировки.

Как другие процессы видят удаленные ключи

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

UPDATE STATISTICS

Оператор UPDATE STATISTICS обычно просматривает листовые страницы btree для сбора статистики для оптимизатора запросов. Кроме того, оператор UPDATE STATISTICS просматривает также страницы, которые имеют взведенный флаг удаления в заголовке таблицы. Если ключи найдены, страница помещается в btree cleaner pool для очистки.

Оператор UPDATE STATISTICS действует, как запасной вариант для нормальных механизмов, которые удаляют элементы, предназначенные для удаления. Например, если аварийная остановка системы приведет к потере данных из btree cleaner pool (поскольку он находится в памяти общего доступа), ключи не будут удалены. Когда нормальная работа системы будет восстановлена, все будет работать нормально, а предназначенные для удаления ключи будут просто занимать место, которое невозможно будет немедленно повторно использовать. Чтобы удалить такие элементы можно запустить оператор UPDATE STATISTICS.

Упражнение

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

Сеанс A - введите:

    begin work;

    update manufact set lead_time = "2"

    where manu_code = "ANZ";

Сеанс B - введите:

select * from manufact

where manu_code = "HRO";

Что происходит и почему?

Сеанс A - введите:

    rollback work;

    alter table manufact lock mode(row);

    begin work; update manufact set lead_time = "2"

    where manu_code = "ANZ";

Сеанс B - введите:

    select * from manufact

    where manu_code = "HRO";

    Каким образом этот оператор получает доступ к данным? Какова разница между результатами шага ?4 и ?2?

Сеанс B - введите:

select * from manufact;

Что происходит и почему?

Сеанс B - введите:

set isolation to dirty read;

select * from manufact

Что произошло иначе и почему?

Сеанс B - введите:

set isolation to committed read;

set lock mode to wait;

select * from manufact;

Что происходит и почему?

Сеанс A - введите:

    commit work;

    Что произошло в сеансе B после выполнения этого оператора и почему?

Сеанс A - введите:

    set isolation to repeatable read;

    begin work;

    update manufact set lead_time = "2"

    where manu_name = "Husky";

    Каким образом происходит обращение к данным оператором UPDATE - последовательно или по индексу? Какие типы блокировок создаются во время выполнения оператора UPDATE?

Сеанс B - введите:

    set lock mode to not wait;

    update manufact set lead_time = "2"

    where manu_code = "ANZ";

    Как происходит обращение к данным во время выполнения этого оператора? Что происходит и почему?

Сеанс B - введите:

select * from manufact

where manu_code = "ANZ";

Какой уровень изоляции имеет этот оператор? Как Вы думаете, были ли созданы во время его выполнения какие-либо блокировки? Что происходит и почему?

 

Украинская баннерная сеть
 

[Home]

Сайт поддерживается группой пользователей Информикс на Украине.

Hosted by NO-more.