Новые правила для shared pool в версии 8
Новые правила для shared pool в версии 8.1
28 марта 2001 г.
New pool rules
Стив Адамс
Управление фрагментацией разделяемого пула (shared pool) в Oracle 8.1.
Источник: Новости от Ixora News, июль 2000 (http://www.ixora.com.au/newsletter/2000_07.htm#pool_rules)
Настройка буфера shared pool в Oracle – один из наиболее сложных видов настройки. К счастью, с нею приходится иметь дело далеко не всем. Большинство администраторов может себе позволить попросту выставить размер shared pool очень большим, так что риск столкнуться в результате этого со снижением производительности для них окажется невелик. Однако если вдруг на сервере в большом количестве выполняются фазы трансляции и исполнения SQL-запросов, к выставлению размера shared pool требуется отнестись с большой осторожностью: неудачный размер может привести к увеличению числа конкурирующих заявок на использование защелок (фиксаторов), которые регулируют работу библиотечного буфера и shared pool (library cache latches и shared pool latches).
Основная причина возникновения конкуренции за использование зашелок shared pool кроется в фрагментации свободной памяти. Если свободная память превращается в большой набор небольших кусков, то процесс, подыскивающий себе кусок по размеру, будет держать защелку shared pool долгое время. Степень фрагментированности свободной памяти очень легко посмотреть с помощью сценария shared_pool_free_lists фирмы Ixora. Для сокращения фрагментации ключевым является закрепление в библиотечном буфере попавших туда объектов, а также выставление размера shared pool в меру необходимого – и не более того.
К счастью, в своей борьбе с фрагментацией свободной памяти вы не одиноки. Фирма Oracle сама предлагает ряд возможностей для снижения фрагментации, а кроме того в самых последних версиях по этой части появились некоторые улучшения.
Сращивание “с передним”
Если кусок памяти освобождается, и следующий кусок тоже свободен, то Oracle соединит эти два свободных куска в один. Это называется сращиванием “с передним”. Такой метод эффективен, так как для проверки занятости системе достаточно заглянуть в 16-байтовый заголовок следующего куска. В том же заголовке хранятся указатели на предыдущий и следующий куски в свободном списке. Их наличие позволяет просто удалить в случае надобности этот кусок из списка свободных и ликвидировать возникшую в списке “дыру”.
По нашим наблюдениям в версии 8.1 Oracle при освобождении ранее занятого куска сращивает его теперь не с одним, как раньше, а со всеми следующими сразу после него смежными свободными кусками. Это приводит к тому, что “сбрасывать” вручную состояние shared pool командой flush для сращивания свободных кусков в один теперь нужно реже, чем это требовалось раньше. Соответственно, в таком ручном “сбросе” пользы теперь будет значительно меньше, особенно когда shared pool сформирована без запаса.
Резерв постоянной памяти
Резерв постоянной памяти – это участок свободной памяти, оставляемый при старте системы в shared pool “про запас”. Так, если параметр shared_pool_size выставлен в 10,000,000 байт и структуры постоянной (permanent) памяти требуют с самого старта 1,000,000 байт плюс к этому дополнительно, то общий размер shared pool будет 11,000,000 байт. В момент запуска системы, тем не менее, для использования будет выдано из shared pool 5,500,000 байт, а остальные 4,500,000 байт свободной памяти будет зарезервировано в виде куска постоянной основной памяти в “одну кассу” с 1,000,000 байт постоянной памяти. Резерв постоянной памяти освобождается по мере необходимости – всякий раз по 50% от имеющегося запаса.
Освобождаемые в процессе работы куски из резерва постоянной памяти оказываются фрагментированы намного менее своих “собратьев”, доступных для использования с самого начала. Однако в версии 7 выделение памяти из резерва осуществлялось неоправданно долго, так что нередко предпочтительнее оказывалось освободить давно неиспользуемые куски в соответствии с LRU-списком. В версии 8 освобождению “старых” кусков (по LRU-списку) всегда предшествует попытка найти место в резерве постоянной памяти.
Резервный пул
Резервный пул (а точнее – резервный список внутри shared pool) не следует путать с резервом постоянной памяти. Резервный пул имеет постоянное предназначение выдавать большие куски памяти, в то время как резерв постоянной памяти выступает в качестве временного резерва, на время старта системы, для предотвращения избыточной фрагментации. Тем не менее, размеры этих двух областей памяти связаны друг с другом. Размер резервного пула не может быть больше 20% shared pool; его наличие приводит к тому, что резерв постоянной памяти не будет освобождаться чересчур быстро и фрагментация уменьшится.
Однако начиная с версии 8.0, когда использование резервного пула стало обязательным, он нередко в процессе работы оставался нетронутым. Этому способствовали два обстоятельства. Во-первых, в последних версиях Oracle просто берет большие куски из shared pool, если находит в свободном списке кусок достаточно большого размера, не прибегая к просмотру LRU-списка в поисках кандидатов на освобождение памяти в компьютере. А во-вторых, Oracle теперь очень редко нуждается в кусках памяти, больше 5000 байт (значение параметра _shared_pool_reserved_min_alloc по умолчанию). Минимально допустимое значение для этого параметра доведено до 4000 байт, и использование этого значения позволяет вам более успешно справляться с фрагментацией памяти, уменьшая риск появления ошибки ORA-4031 и не требуя обращения к LRU-списку при необходимости размещения кусков в диапазоне от 4000 до 5000 байт.
Скрипт shared_pool_free_lists.sql
-------------------------------------------------------------------------------
--
-- Script: shared_pool_free_lists.sql
-- Purpose: to check the length of the shared pool free lists
-- For: 8.1.6 to 8.1.7
--
-- Copyright: (c) Ixora Pty Ltd
-- Author: Steve Adams
--
-------------------------------------------------------------------------------
@save_sqlplus_settings
select
decode(
sign(ksmchsiz - 812),
-1, (ksmchsiz - 16) / 4,
decode(
sign(ksmchsiz - 4012),
-1, trunc((ksmchsiz + 11924) / 64),
decode(
sign(ksmchsiz - 65548),
-1, trunc(1/log(ksmchsiz - 11, 2)) + 238,
254
)
)
) bucket,
sum(ksmchsiz) free_space,
count(*) free_chunks,
trunc(avg(ksmchsiz)) average_size,
max(ksmchsiz) biggest
from
sys.x_$ksmsp
where
inst_id = userenv('Instance') and
ksmchcls = 'free'
group by
decode(
sign(ksmchsiz - 812),
-1, (ksmchsiz - 16) / 4,
decode(
sign(ksmchsiz - 4012),
-1, trunc((ksmchsiz + 11924) / 64),
decode(
sign(ksmchsiz - 65548),
-1, trunc(1/log(ksmchsiz - 11, 2)) + 238,
254
)
)
)
/
@restore_sqlplus_settings
Вид выходного листинга
SQL> @shared_pool_free_lists
BUCKET FREE_SPACE FREE_CHUNKS AVERAGE_SIZE BIGGEST
---------- ---------- ----------- ------------ ----------
0 166344 3872 42 72
1 32208 374 86 96
4 928 1 928 928
6 11784 4 2946 3328
|