Шрифт:
Интервал:
Закладка:
В конце этой книги глава 40 представляет техническое описание наименее дружественной для пользователя утилиты Lock Print, а также подсистему блокировки ресурсов. Она включает объяснения связанных с блокировками установок в firebird.conf или isc config/ibconfig, которые иначе могли бы остаться для большинства из нас большой загадкой!
ГЛАВА 40. Менеджер блокировок.
Блокировки используются в многопользовательских средах для синхронизации работы и предотвращения разрушения целостности процессов работой других процессов. Firebird использует как средства блокировки операционной системы, так и собственный менеджер блокировок для координации доступа к базе данных.
Эта тема сложна для читателя, который является новичком в Firebird. Она погружает его в некоторые серьезные технические области, с которыми знакомят гуру[158] с блестящими глазами на конференциях. Пока утилиты Lock Print - довольно сырые сейчас- являются серьезным инструментом для сложных задач поиска ошибок при подходах, которые некоторые разработчики применяют в их интерфейсах приложений. В любом случае примите эту главу как возможный запасной вариант, который может спасти вас в один "прекрасный" день.
Вы можете спросить, почему мы должны интересоваться системой блокировки, которая ничего не блокирует? Параллельность и согласованность, видимые клиентам, основываются на транзакциях и управляются через версии записей. Однако ответ в том, что Firebird использует блокировки внутренне. Он поддерживает согласованность структуры на диске через блокировки и осторожную запись. В то же время он также использует сервисы блокировок операционной системы для управления доступом к файлам базы данных для предотвращения открытия Суперсервером дважды одного и того же файла под разными именами.
Блокировка, основанная на транзакциях, позволяет осуществлять блокировки в любой точке выполнения транзакции. Однако, однажды установленные, они могут быть сняты только в конце. Даже явная блокировка на уровне оператора, введенная в Firebird 1.5, не имеет "разблокирующего" оператора. Операторы выполняются в обычной транзакции; подтверждение или откат транзакции снимает блокировку как обычно.
Firebird остерегается двухфазной блокировки для своего первичного управления параллельностью, поскольку она не может обеспечить адекватных уровней параллельности и соответствия, Firebird использует блокировки в процессе изменений для предотвращения записи двумя транзакциями на одну и ту же страницу в одно и то же время. Внутренняя блокировка управляется самой системой. Объекты в системе - называемые "владельцами блокировки" или просто "владельцами" - состязаются в блокировке множества ресурсов. Не удивительно, что эти ресурсы включают в себя и страницы, содержащие записи, отмеченные для обновления.
Когда транзакция получает блокировку страницы, она сохраняет эту блокировку, пока Менеджер блокировок не попросит ее освободить страницу; следовательно, транзакция может выполнить множество изменений на одной странице без ее освобождения и повторного чтения.
Менеджер блокировок Firebird
В Суперсервере о Менеджере блокировок можно думать как об отдельном "управляющем центре", с которым договариваются транзакции о приобретении прав на выполнение запросов. Менеджер блокировок включает в себя фрагмент памяти и некоторые подпрограммы для обработки запросов. Его память разделена на различные блоки: блоки блокировок, которые ссылаются на ресурсы; другие блоки, которые представляют транзакции и другие объекты, запрашивающие блокировки, и блоки истории. Его подпрограммы ответственны за получение и управление запросами владельцев на блокировки ресурсов, выделение блоков и их освобождение. Суперсервер также управляет "защелками" для координации изменений в параллельных транзакциях.
Классический сервер проще: владельцы запрашивают получение контроля над таблицей блокировок, так что каждый код процесса управления блокировкой может запрашивать, предоставлять и освобождать блокировки для их владельцев.
Состояния блока
Каждая операционная система предоставляет некий вид механизма использования/освобождения для синхронизации событий ресурсов. Поскольку для Firebird нужен управляющий механизм с множеством состояний, он реализует свою собственную систему управления блокировками с семью состояниями. На рис. 40.1 показано решение уровней блокировок.
* 0 - свободно (no lock).
* 1 - пустая блокировка (null lock), что соответствует интересу объекта, не накладывающего ограничений в использовании другими. Запрос пустой блокировки позволяет транзакции читать заблокированные данные.
* 2 - разделяемое чтение (shared read), что позволяет записывать. Разделяемое чтение является обычным режимом для блокировки таблицы, когда транзакция изменяет некоторые части таблицы.
* 3 - защищенное чтение (protected read), что позволяет другим читать, но не писать. Защищенное чтение является обычным режимом для блокировки страницы базы данных, которая находится в кэше и не была изменена.
Рис. 40.1. Состояния внутренних блокировок Firebird
* 4 - совместно используемая запись (shared write), другой обычный режим блокировки таблицы. Совместно используемая запись совместима с разделяемым чтением и другими совместно используемыми записями, но не с любым защищенным режимом.
* 5 - защищенная запись (protected write), которая допускает разделяемое чтение и пустую блокировку и ничего больше. Защищенная запись используется при режиме CONSISTENCY и для такой блокировки базы данных, что обычные пользователи не могут получить к ней доступ.
* 6 - исключительный доступ (exclusive), используется для внутренних структур, когда параллельный доступ может повлиять на изменения или привести к тому, что вторая транзакция будет читать незавершенные изменения данных.
Таблица блокировок
Менеджер блокировок управляет таблицей блокировок для координации совместного использования ресурсов в клиентских потоках. Информация, предоставляемая здесь, может быть полезной при попытках исправить ситуации взаимных блокировок, например;
* все в настоящий момент заблокировано в системе в своем состоянии;
* глобальная статистика заголовков, такая как размер таблицы блокировок, множество свободных блокировок, множество взаимных блокировок и т.д.;
* флаги процессов, указывающие, была ли передана блокировка или она осуществляет ожидание.
Блокировки сохраняются в последовательностях, каждая последовательность идентифицируется номером в соответствии с типом блокируемого ресурса. Номера последовательностей объясняются в табл. 40.5.
Использование пустой блокировкиЗапущенная транзакция использует таблицу блокировок в качестве доски объявлений. Чтобы исключить сборку мусора версий записей, которые нужны другой транзакции, каждая транзакция должна знать самое старое действие, которое видит другая транзакция. Вот как это сделано:
1. При старте транзакция сохраняет в области данных собственного блока идентификатор старейшей транзакции, которая еще выполняется (активна).
2. Затем она устанавливает пустую блокировку на все параллельные транзакции. Когда будет получен каждый блок, ей возвращается содержимое области данных.
Новая транзакция проверяет блок каждой существующей транзакции для отыскания идентификатора старейшей транзакции, о которой знает каждая активная транзакция.
Свободные спискиСписки владельцев, ресурсов и запросов представлены в виде цепочки с возможностью проходить по ним вперед и назад. В начале каждого блока находится указатель на следующий блок. Списки указателей используются Менеджером блокировок, когда ему нужно разместить новый блок и постараться найти свободные блоки для повторного использования. Он выделит новый блок, только если не существует свободных блоков нужного типа и размера.
Свободные элементы содержат прямые и обратные указатели на первый и последний свободный блок соответственно.
Взаимные блокировкиВзаимная блокировка (deadlock) возникает, когда владелец А хочет блокировать ресурс 1, который заблокирован владельцем В, а владелец В хочет заблокировать ресурс 2, который заблокирован процессом А. Она также может появиться для одного ресурса, если два владельца начинают с блокировки чтения и запрашивают блокировки на запись.
Эту ситуацию владельцы не могут разрешить без постороннего вмешательства. Решение осуществляется, когда взаимная блокировка определяется последующим сканированием и Менеджер блокировок возвращает ошибку одному владельцу или другому. Интервал сканирования блокировок по умолчанию - параметр DeadiockTimeout в файле конфигурации- составляет 10 секунд. Этот интервал не используется при условиях, где присутствует WAIT. Ожидание является нормальным в системе, которая управляет параллельными изменениями, и не требует затрат на сканирование.
- Delphi. Учимся на примерах - Сергей Парижский - Программирование
- Сделай видеоигру один и не свихнись - Слава Грис - Программирование / Руководства
- Психбольница в руках пациентов - Алан Купер - Программирование