Чрезмерное потребление памяти процессом

Nitro_Junkie
Дата: 09.12.2014 17:34:53
У нескольких заказчиков появляется странная ситуация когда отдельные процессы забирают себе много памяти, и не отдают назад долгое время (через пару часов например).

Если посмотреть top'ом:

SWAP PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4.0g 4471 postgres 20 0 5623m 1.1g 909m S 0.0 14.2 63:13.43 postmaster

Причем work_mem = 32MB, temp_buffers = 32MB, shared_buffers = 1024MB, fsync = off (у них там облако с высокой доступностью), все остальное вроде default.

Если посмотреть через smaps, то там единственный большой entry не deleted :

00cd0000-10f3e6000 rw-p 00000000 00:00 0
Size: 4430936 kB
Rss: 204484 kB
Pss: 204484 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 100 kB
Private_Dirty: 204384 kB
Referenced: 155568 kB
Anonymous: 204484 kB
AnonHugePages: 165888 kB
Swap: 4140400 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB

То есть это явно не shared buffers, да и не понятно что им делать в свопе.

По идее это могут быть временные таблицы, но :

SELECT
pg_size_pretty(SUM(pg_relation_size(C.oid)))
FROM pg_class C
WHERE nspname LIKE ('pg_temp%');
pg_size_pretty
----------------
23 MB
(1 row)

Это не могут быть temp_buffers, они хоть и живут всю жизнь:
Temp buffers, once used within a particular backend process, are kept
for the life of that process.
Но по идее не могут превысить 32Mb

Work_mem теоретически может превысить: (далее цитаты Tom Lane'а)
Keep in mind that work_mem is the max per sort or hash operation, so a
complex query could consume a multiple of that.
То есть при очень большом сложном запросе, можно и 4 гига сожрать, если не угадать со статистикой, но :
Memory consumed for work_mem will be
released back to libc at the end of the query. The net effect of that
is platform-dependent --- my experience is that glibc on Linux is able
to give memory back to the OS, but on other platforms the process memory
size doesn't shrink.
А в нашем случае речь идет о centos, и никакого активного процесса в pg_stat_activity нет, а этот своп держится очень долго (несколько часов например)

Версии:
# cat /proc/version
Linux version 2.6.32-504.1.3.el6.x86_64 (mockbuild@c6b9.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC) ) #1 SMP Tue Nov 11 17:57:25 UTC 2014
# cat /etc/redhat-release
CentOS release 6.6 (Final)

Как узнать почему именно жрется память? И кстати есть ли способ work_mem как то адаптировать под сложные запросы, то есть как-то ограничить work_mem для всего запроса, а не отдельной sort / hash операции. (тут правда стоит отметить что мы иногда enable_nestloop используем, когда postgresql сильно не угадывает со статистикой, и тогда у него не остается выбора кроме как жрать память, без этой опции за такое ограничение сверху может отвечать стоимость плана).
Maxim Boguk
Дата: 10.12.2014 07:00:48
Nitro_Junkie
У нескольких заказчиков появляется странная ситуация когда отдельные процессы забирают себе много памяти, и не отдают назад долгое время (через пару часов например).

Если посмотреть top'ом:

SWAP PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4.0g 4471 postgres 20 0 5623m 1.1g 909m S 0.0 14.2 63:13.43 postmaster

Причем work_mem = 32MB, temp_buffers = 32MB, shared_buffers = 1024MB, fsync = off (у них там облако с высокой доступностью), все остальное вроде default.

Если посмотреть через smaps, то там единственный большой entry не deleted :

00cd0000-10f3e6000 rw-p 00000000 00:00 0
Size: 4430936 kB
Rss: 204484 kB
Pss: 204484 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 100 kB
Private_Dirty: 204384 kB
Referenced: 155568 kB
Anonymous: 204484 kB
AnonHugePages: 165888 kB
Swap: 4140400 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB

То есть это явно не shared buffers, да и не понятно что им делать в свопе.

По идее это могут быть временные таблицы, но :

SELECT
pg_size_pretty(SUM(pg_relation_size(C.oid)))
FROM pg_class C
WHERE nspname LIKE ('pg_temp%');
pg_size_pretty
----------------
23 MB
(1 row)

Это не могут быть temp_buffers, они хоть и живут всю жизнь:
Temp buffers, once used within a particular backend process, are kept
for the life of that process.
Но по идее не могут превысить 32Mb

Work_mem теоретически может превысить: (далее цитаты Tom Lane'а)
Keep in mind that work_mem is the max per sort or hash operation, so a
complex query could consume a multiple of that.
То есть при очень большом сложном запросе, можно и 4 гига сожрать, если не угадать со статистикой, но :
Memory consumed for work_mem will be
released back to libc at the end of the query. The net effect of that
is platform-dependent --- my experience is that glibc on Linux is able
to give memory back to the OS, but on other platforms the process memory
size doesn't shrink.
А в нашем случае речь идет о centos, и никакого активного процесса в pg_stat_activity нет, а этот своп держится очень долго (несколько часов например)

Версии:
# cat /proc/version
Linux version 2.6.32-504.1.3.el6.x86_64 (mockbuild@c6b9.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC) ) #1 SMP Tue Nov 11 17:57:25 UTC 2014
# cat /etc/redhat-release
CentOS release 6.6 (Final)

Как узнать почему именно жрется память? И кстати есть ли способ work_mem как то адаптировать под сложные запросы, то есть как-то ограничить work_mem для всего запроса, а не отдельной sort / hash операции. (тут правда стоит отметить что мы иногда enable_nestloop используем, когда postgresql сильно не угадывает со статистикой, и тогда у него не остается выбора кроме как жрать память, без этой опции за такое ограничение сверху может отвечать стоимость плана).


попробуйте вот так вот сделать
https://wiki.postgresql.org/wiki/Developer_FAQ#Examining_backend_memory_use
и пришлите что у вас получилось...
бывают паталогические случаи когда память жрется...
ну и проверьте что у вас ПОСЛЕДНЯЯ доступная минорная версия базы работает а не нечто 2х летней давности (чтобы не искать давно исправленные баги).


--Maxim Boguk
www.postgresql-consulting.ru
Nitro_Junkie
Дата: 10.12.2014 10:01:17
Maxim Boguk,

Версия вроде одна из последних:

PostgreSQL 9.3.5 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.4.7 20120
313 (Red Hat 4.4.7-4), 64-bit
(1 row)

gdb попробую при возможности...