В Oracle 11g появилась система AMM (Automatic Memory Management) и свойство MEMORY_TARGET, и казалось бы вот он - способ регулировать потребление памяти Oracle. Однако структура потребления памяти инстансом Oracle несколько сложнее. Его можно выразить подобной диаграммой Венна:
Расмотрим ее на примере Oracle 11g + Solaris 10.
С точки зрения Oracle
Идентифицировать потребление памяти со стороны Oracle выполняется с помощью служебных view V$PROCESS и V$PROCESS_MEMORY - по процессам, V$SGASTAT и V$PGASTAT - кумулятивно для SGA и PGA соответственно.
SQL> SET linesize 80;
COLUMN pid FORMAT 999999;
COLUMN spid FORMAT a7;
COLUMN program FORMAT a25;
SELECT pid, spid, program, pga_used_mem, pga_alloc_mem, pga_max_mem FROM v$process;
PID SPID PROGRAM PGA_USED_MEM PGA_ALLOC_MEM PGA_MAX_MEM
------- ------- ------------------------- ------------ ------------- -----------
1 PSEUDO 0 0 0
2 5370 oracle@oracle (PMON) 742968 826392 826392
3 5372 oracle@oracle (PSP0) 724800 809976 809976
4 5374 oracle@oracle (VKTM) 721552 809976 809976
<...>
25 6046 oracle@oracle 9447644 11688952 49568760
26 6316 oracle@oracle 3643596 5200888 7560184
27 6318 oracle@oracle 2509260 3759096 3759096
28 6243 oracle@oracle 1706816 2776056 4348920
<...>
В колонке PROGRAM мы видим имя запущенной программы, в случае (PMON) это например фоновый процесс монитора процессов, если же оно не указано, значит этот процесс обслуживает клиентское соединение. В колонках pga_used_mem, pga_alloc_mem, pga_max_mem (pga_freeable_mem не показана) - соответственно выделенная программой память из сегмента PGA. Отметим, что это верно только для конфигурации с Dedicated Process - в случае для общих пулов (Shared Pool Process) память выделяется процессами из SGA.
Память PGA делится на 4 категории: "SQL", "PL/SQL", "OLAP" и "JAVA". Посмотреть разделение по категориям можно в view V$PROCESS_MEMORY для процесса с PID 25 можно так:
SQL> select category, used, allocated from v$process_memory where pid = 25;
CATEGORY USED ALLOCATED
--------------- ---------- ----------
SQL 17496 103912
PL/SQL 298336 796184
Freeable 0 1376256
Other 9412600
Как видим, большая часть памяти отведена под категорию Other.
Суммарный объем потребляемой памяти можно получить например так:
COLUMN component FORMAT A30
SELECT component, current_size, min_size, max_size
FROM v$memory_dynamic_components;
Solaris уполномочен заявить
Потребление памяти с точки зрения операционной системы (и соответственно меня как ее системного администратора) выглядит несколько иначе. Тут можно выделить такие факторы:
-
При выделении памяти она только резервируется в пространстве swap (оно включает в себя как доступную оперативную память минус DISM-сегменты, ядро, и зарезервированные железом области, так и дисковый своп) - это называется Virtual Size (VSZ), тогда как реальное выделение физической оперативной происходит при первом обращении к ней - это называется Resident Set Size (RSS).
-
Некоторые типы сегментов, такие как сегмент кода разделяемой библиотеки, или DISM-сегменты, используемые СУБД под SGA разделяются, то есть одна и та же физическая память отображается в разные процессы, и поэтому простое суммирование полей SZ и RSS вывода утилиты ps бесполезно.
-
Кроме собственно PGA, серверные процессы Oracle могут использовать память внутри стандартной библиотеки C, кроме того требуется для каждой разделяемой библиотеки создавать собственный сегмент данных, для потоков держать стеки. Все это создает дополнительные, неучтенные расходы.
Подробный анализ потребляемой памяти со стороны Solaris выполняется посредством утилиты pmap. Собрать pmap для всех процессов Oracle, можно например так (потребуется оболочка bash, так как она поддерживает [[]] и оператор =~):
( ps -eo pid,rss,vsz,comm |
while read PID RSS VSZ COMM
do
if [[ $COMM =~ "ora" ]]; then
echo --
echo $PID $VSZ $RSS
pmap -x $PID;
fi
done ) > /tmp/pmap-collect.out
Для каждого из процессов она соберет карту его сегментов и выразит потребляемую ими память в килобайтах. Чтобы просуммировать показатели по множеству процессов, я реализовал утилиту pmapsummary:
pmapsummary.py {-r|-v} [-s no|only|once|all] [-c COL1,COL2] [-S SORTCOL] [pmap-collect.out]
pmapsummary.py -h
-r для RSS (Resident Set Size)
-v для VSZ (Virtual Size)
-s - как считать общую память (no - игнорировать, only - показывать только ее,
once - считать для одного процесса, all - считать для всех процессов )
-c - какие колонки показывать
-S - по какой колонке сортировать
Колонки:
ANON - анонимная память
HEAP - куча
DISM - intimated shared memory (SHM)
MMAP - устройства и файлы, отображенные с помощью mmap
CODE - программный код бинарного файла и разделяемых библиотек
DATA - сегменты данных бинарного файла и разделяемых библиотек
STK - стеки потоков
TOTAL - все вместе
Кто прав?
Сравним вывод pmapsummary (первая строка соответственно RSS, а вторая VSZ) и служебных view СУБД для одного процесса:
PID SPID PROGRAM PGA_USED_MEM PGA_ALLOC_MEM PGA_MAX_MEM
------- ------- ------------------------- ------------ ------------- -----------
34 9167 oracle@oracle 2992524 4414456 5200888
PID ANON HEAP DISM MMAP CODE DATA STK TOTAL NAME
9167 4080 840 516096 8 199448 1912 160 722544 oracleorcl (LOCAL=NO)
9167 4584 848 790528 8 229992 2880 1184 1030024 oracleorcl (LOCAL=NO)
И для всего сервера:
COMPONENT CURRENT_SIZE MIN_SIZE MAX_SIZE
------------------------------ ------------ ---------- ----------
shared pool 301989888 289406976 301989888
large pool 4194304 4194304 4194304
java pool 4194304 4194304 4194304
streams pool 4194304 4194304 4194304
SGA Target 524288000 524288000 524288000
DEFAULT buffer cache 201326592 201326592 213909504
<...>
PGA Target 281018368 281018368 281018368
ASM Buffer Cache 0 0 0
NAME VALUE UNIT
---------------------------------------- ---------- ------------
aggregate PGA target parameter 281018368 bytes
aggregate PGA auto target 185757696 bytes
global memory bound 56203264 bytes
total PGA inuse 74612736 bytes
total PGA allocated 108959744 bytes
maximum PGA allocated 205782016 bytes
<...>
PID ANON HEAP DISM MMAP CODE DATA STK TOTAL NAME
---> 88704 40200 516096 408 199448 62792 4512 912160 <--- total
---> 115984 40504 790528 408 229992 95016 38304 1310736 <--- total
Как видим, SGA target и размеры DISM не совпадают, а вот размер "total PGA allocated" в целом соответствует лишь анонимной памяти, выделенной процессами Oracle. Ну и никак не учитываются кучи и сегменты данных процессов, использующие немалые объемы памяти. Для систем со большим количеством процессов это может приводить к значительным накладным расходам, а значит желательно конфигурировать СУБД в режиме Shared Process Pool.
pmapsummary.py