Базы данных Oracle - статьи

         

Управление поведением


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

Документация по СУБД Oracle не дает информации о вычислении значения _spin_count. Для версий 8, 9 и 10 это значение равно 2000. Интересно, как получено это значение?

Методики анализа блокировок могут быть статическими (анализ кода), либо динамическими (анализ работы программы).

С точки зрения исследования исполняемого кода, если разработчики СУБД Oracle знают, что процесс, работающий под защитой блокировки, в среднем выполняет не более Х команд, то и параметр _spin_count можно было бы установить в значение, покрывающее этот промежуток. Однако реально сложно однозначно сказать, сколько времени займет выполнение 2000 команд. Команды процессора различаются по длительности, иногда довольно сильно, от нескольких тактов, например, инкремент – 1 такт, до нескольких десятков – деление требует 42 такта.

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

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

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

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

  • высокая загрузка сервера. Если процесс, завладевший защелкой, выполняется на загруженном процессоре и снимается с процессора, не освободив ее, то конкуренция за такую защелку будет весьма высокой.
  • продолжительный захват защелки. Чаще всего это происходит из-за того, что структура памяти (связный список), защищенный конкретной защелкой, стал слишком длинным. Пример – список свободных участков памяти внутри buffer cache, shared pool.


  • Содержание раздела