Продолжается подписка на наши издания! Вы не забыли подписаться?

Oracle latches – механизм последовательного доступа

Автор: к.ф.-м.н. Ю.Пудовченко
Открытые технологии

Источник: www.citforum.ru/database/oracle/latches/
Опубликовано: 18.04.2007

Введение и основные понятия

Экземпляр Oracle состоит из ряда процессов, обращающихся к общим сегментам памяти (SGA и другие общедоступные ресурсы). Поэтому они могут испортить информацию друг друга. Следовательно, во многих случаях требуется обеспечить механизм, который при использовании одним процессом общедоступных ресурсов (например, участки памяти) запрещает другим процессам изменять эти данные. Таким механизмом в СУБД Oracle являются блокировки, то есть специальные переменные, показывающие, занят или свободен некоторый ресурс.

Обычно под понятием “блокировки” в сервере Oracle понимаются две сущности:

В данной статье под блокировками будем понимать внутренние блокировки сервера и защелки.

В СУБД Oracle блокировки делятся на два непересекающихся класса: защелки (latch) и очереди (enqueues).

Защелки – это двоичные переменные, фактически – переключатели-триггеры, которые применяются на короткое время и защищают структуры памяти. Защелка имеет только два состояния – занята или свободна. Наиболее известные из защелок – shared pool latch, library cache pin, library cache lock, cache buffer chains, redo allocation latch, redo copy.

Защелки в СУБД Oracle могут запрашиваться в двух режимах: “willing-to-wait” и “no-wait” (= immediate). Если процесс имеет возможность продолжать работу, не получив запрашиваемую защелку, то это запрос no-wait (например, redo copy latch). Если процесс не может продолжать работу, не получив запрашиваемую блокировку, то это режим willing-to-wait.

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

  1. Если защелка свободна, то запрос на нее удовлетворяется. Конец.
  2. Если защелка занята, то процесс циклично повторяет запросы на защелку _spin_count раз. Если запрос удовлетворен, то Конец.
  3. Если запрос на защелку не удовлетворен, то процесс “засыпает” на 1/100 секунды, после чего переходит к п.2. Если запрос опять не удовлетворен, то в каждом следующем цикле длительность интервала удваивается, после чего следует переход к п.2.

В отличие от защелок, очереди запросов (enqueue) действительно образуют упорядоченную очередь FIFO. Каждый запрос в очереди, кроме порядкового номера, отражает еще и режим запроса (share, exclusive). Например, запросы на чтение могут выполняться одновременно, не блокируя друг друга. Если запрос на блокировку enqueue не может быть удовлетворен, то он ставится в очередь. Порядковые номера в очереди запрашиваются через системные вызовы ОС (семафоры).

С блокировками типов enqueues и latches всегда связана процедура, которая возвращает блокировку к предыдущему состоянию, если процесс, удерживающий блокировку, зависнет или аварийно завершится. В СУБД Oracle эту функцию выполняет процесс PMON.

Проблема

В общем случае блокировка – это некая булева переменная, которая показывает, что ресурс свободен или занят. Если значение переменной – 0 (false), то это означает, что блокировка свободна, и любой процесс может изменить ее значение на 1 (true), а затем обращаться к защищаемому ресурсу. Если значение блокировки true, то процессу следует подождать, поскольку кто-то еще пользуется этим ресурсом.

Вопрос: можно ли программным путем гарантированно заблокировать ресурс?

Ответ: нет, невозможно! Например, два процесса могут одновременно опросить одну и ту же переменную и, убедившись, что ее значение равно 0, установить ее значение в 1. Такой сценарий не редкость в многопроцессорных ЭВМ.

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

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

Механизмы блокирования

Искомое решение требует участия аппаратного обеспечения. Процессоры многопроцессорных ЭВМ имеют специальную команду, которая в разных источниках называется TSL (Test and Set Lock), CAS (Compare and Swap) или LL/SC (Load Link /Store Conditions).

Процессор, выполняющий эту команду, блокирует шину памяти так, чтобы остальные процессоры не могли обратиться к оперативной памяти, и затем выполняет команду ‘test’, читая соответствующую ячейку памяти. Если возвращаемое значение равно нулю (false), то это значит, что переменная свободна, и процессор выполняет команду ‘set’, которая записывает в эту переменную значение 1 (true). Шина памяти разблокируется. Освобождение блокировки выполняется путем записи 0 (false) в переменную блокировки.

Если другой процессор позже попытается запросить блокировку, то команда ‘test’ возвратит ему значение 1 (true), означающее, что блокировка уже установлена. В этом случае второму процессу придется подождать некоторое время, а затем снова запросить блокировку. При выполнении каждой TSL-команды происходит блокирование шины ЭВМ.

Таким образом, команда типа TSL аппаратно обеспечивает неделимость обращения к переменной блокировки, ибо процесс может быть снят с выполнения либо до начала команды, либо после ее окончания. В результате этого блокировки СУБД ORACLE спускаются на уровень аппаратного обеспечения и блокируют шину ЭВМ. Блокирование шины сервера означает, что во время выполнения команды TSL все остальные процессоры и процессы не могут получить доступ к оперативной памяти, и вынуждены ждать завершения операции (однако они могут обращаться к данным в своем локальном кэше).

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

Механизм разблокировки

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

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

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

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

Влияние на производительность

Механизм блокирования системной шины фактически замораживает функционирование сервера на короткий период времени. А это означает, что в результате блокирования шины сервер фактически функционирует не 3600 секунд в час, а 3599, 3598, … а, возможно, менее. То есть, слишком часто блокируемый сервер работает не все отведенное для работы время. Причем частота блокирования растет пропорционально количеству процессоров и процессов. В результате чего добавление очередного процессора может не приводить к увеличению производительности всего сервера в целом.

Блокировки используются в СУБД Oracle во многих случаях, например:

Для полноты картины попробуем численно оценить влияние блокировок на производительность сервера, для чего рассмотрим типичный отчет Statspack, секцию “Latch Activity for DB”. Понятно, что этот расчет довольно приблизительный, но, на мой взгляд, довольно показательный.

У меня в наличии есть подходящий отчет для 16-процессорного сервера, частота каждого процессора которого составляет 1200МГц. Из отчета Statspack для этого сервера следует, что СУБД Oracle выполняет более 650 тысяч блокировок в секунду (точное значение 651 801.9). По справочникам можно уточнить, что команды типа TSL для процессора UltraSparcIII – CASA и CASXA – требуют для своего выполнения 32 цикла. Тогда доля времени, в течение которого системная шина заблокирована, составит 651802*32/1200МГц = 0,0174, то есть 1,74% всего рабочего времени, другими словами 62,64 секунды в час.

<...>

Заключение

В процессе работы над этой статьей мне попало в руки исследование Лаборатории Компьютерных Архитектур университета Карнеги Мелон [8], в котором сравниваются СУБД Oracle и DB2 по активности блокировок, которая возникает в процессе работы. И в этом состязании СУБД Oracle показывает относительно неплохой результат: при одинаковой нагрузке в БД дополнительная активность, создаваемая блокировками в СУБД DB2, составляет 40% от системной (system) нагрузки и 18% от пользовательской (user), а в СУБД Oracle системное время выполнения только 20% и пользовательское время 12%.

Благодарности

Автор выражает благодарность сотруднику компании “Открытые технологии” Александру Иванову за внимание и полезные советы при подготовке данной статьи.

Автор будет признателен коллегам за разумные возражения и поправки относительно вопросов, затронутых в данной статье. Все мнения и замечания можно направлять автору на адрес ypudovchenko@ot.ru

Литература

  1. Настройка систем баз данных с помощью анализа событий ожидания http://www.oracle.com/global/ru/oramag/dec2004/admin_wait_events5.html
  2. Стив Адамс, “Отпечатки пальцев” http://www.oracle.com/global/ru/oramag/july2001/fingerprints.html
  3. Э.Таненбаум “Современные операционные системы”, СПб., Питер, 2006.
  4. Том Кайт, “Oracle для профессионалов”, Киев, Диасофт, 2004.
  5. J. Mauro, R. McDougal, Solaris Internals, Sun Microsystems Press, 2000.
  6. http://metalink.oracle.com, Note 22908.1, “What are Latches and What Causes Latch Contention”, 2004.
  7. http://gee.cs.oswego.edu/dl/jmm/cookbook.html, Doug Lea, “Cookbook for Compiler Writers”
  8. http://books.elsevier.com/companions/1558604286/appendices/Extension_1/survey.htm , David A. Patterson and John L. Hennessy, “Survey of RISC Architectures”
  9. http://www.princeton.edu/~psg/unix/Solaris/troubleshoot/lockcontend.html, Princeton University
  10. J. Kim, E. Nurvitadhi, E. Chung, “Opportunity of Hardaware-Based Optimistic Concurency in OLTP”, Computer Architecture Laboratory of Carnegie Mellon University.

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

Copyright © 1994-2016 ООО "К-Пресс"