воскресенье, 6 января 2013 г.

17.4. Управление ресурсами ядра

Большая установка PostgreSQL может быстро исчерпать ресурсы вашей системы (на некоторых системах объём доступных ресурсов так мал, что для этого даже не нужна "большая" установка). Если и Вы столкнулись с этой проблемой - читайте дальше.

17.4.1 Разделяемая память и семафоры

Разделяемая память и семафоры относятся к "System V IPC" (так же как и очереди сообщений, которые не относятся к PostgreSQL). Почти все современные ОС поддерживают эти возможности, но в некоторых из них они не активированы по умолчанию или не имеют достаточного их количества; особенно это касается оперативной памяти. (На Windows PostgreSQL предоставляет свои собственные реализации этой функциональности, так что большая часть этой главы может быть пропущена.)
Полное отсутствие этих возможностей обычно проявляется в ошибках вроде Illegal system call при запуске сервера. В этом случае единственное, что можно сделать - переконфигурировать сервер. Без них PostgreSQL не работает. Но это достаточно редкая ситуация на современных ОС.
Когда потребности PostgreSQL превышают лимиты IPC, сервер тоже не запустится и оставит Вам сообщение, описывающее проблему и дающее совет, что стоит сделать (см раздел 17.3.1).  Нужные параметры ядра имеют одинаковые имена на разных системах; их обзор приведён в таблице 17-1. А вот методы для их установки отличаются на разных системах. Предположения для некоторых платформ высказаны ниже.
Таблица 17-1. Параметры System V IPC
Имя Описание Разумные значения
SHMMAXМаксимальное значение сегмента разделяемой памяти (байты)как минимум несколько мегабайт (см далее)
SHMMINМинимальное значение сегмента разделяемой памяти (байты)1
SHMALLОбщее количество доступной разделяемой памяти (байты или страницы)если байты - то же, что и SHMMAX; если страницы - ceil(SHMMAX/PAGE_SIZE)
SHMSEGМаксимальное количество сегментов разделяемой памяти на процесснужен только один сегмент, но значение по умолчанию значительно больше
SHMMNIМаксимальное количество сегментов разделяемой памяти в системеSHMSEG + объём для других приложений
SEMMNIМаксимальное количество идентификаторов семафоров (т.е. наборы (sets))как минимум ceil((max_connections + autovacuum_max_workers + 4) / 16)
SEMMNSМаксимальное количество семафоров на системуceil((max_connections + autovacuum_max_workers + 4) / 16) * 17 + объём для других приложений
SEMMSLМаксимальное количество семафоров на наборкак минимум 17
SEMMAPКоличество экземпляров в карте семафоровсм в тексте
SEMVMXМаксимальное количество семафоровкак минимум 1000 (Обычно значение по умолчанию 32767; не меняйте его, пока не требуется)

Наиболее важный параметр разделяемой памяти - SHMMAX; максимальный размер, в байтах,  сегмента разделяемой памяти. Если Вы получаете сообщение об ошибке от shmget вроде "Invalid argument", то скорее всего Вы превысили лимит. Размер требуемого сегмента разделяемой памяти зависит от различных конфигурационных параметров, как показано в таблице 17-2 (см в конце раздела). (Любое сообщение об jib,rt6 которое Вы получите, будет содержать точное значение неудачного запроса.) Вы можете, в качестве временного решения, понизить некоторые из этих настроек, чтобы избежать падения сервера. Хотя и можно запустить PostgreSQL со значением SHMMAX меньшим, чем 2Мб, для приемлемой производительности Вам потребуется значительно больший объём. Рекомендуемое количество находится в интервале от ста мегабайт до нескольких гигабайт.
Некоторые системы содержат лимит на общее количество разделяемой памяти в системе (SHMALL). Убедитесь, что это значение достаточно велико, чтобы его хватило н PostgreSQL и другие приложения, использующие разделяемую память. Обратите внимание, что SHMALL на большинстве систем измеряется в страницах, а не в байтах.
Менее вероятно, что проблема возникнет с минимальным размером разделяемой памяти (SHMMIN), который должен быть где-то 500kB для PostgreSQL (обычно это лишь 1). Максимальное количество сегментов на систему (SHMMNI) или на процесс (SHMSEG) тоже маловероятно приведут к появлению проблемы, если они не равны 0.
PostgreSQL использует один семафор на разрешённое подключение (max_connections) и на позволенный рабочий процесс autovacuum (autovacuum_max_workers) в наборах по 16. Каждый такой набор так же содержит 17ый семафор, который содержит "магическое число", чтобы определять коллизии между наборами семафоров, которые используют другие приложения. Максимальное количество семафоров в системе устанавливается значением SEMMNS, которое следовательно должны быть равно как минимум max_xonnections + max_autovacuum_max плюс ещё по одному на каждые 16 разрешённых соединений и рабочих процессов autovacuum (см формулу в таблице 17-1). Параметр SEMMNI определяет предел набору семафоров, которые могут присутствовать в системе одновременно. Этот параметр должен быть равен как минимум ceil((max_connections + autovacuum_max_workers + 4) / 16). Уменьшение количества разрешённых подключений может временно решить проблему с запуском сервера, которая обычно звучит как "No space left on device" от semget.
В некоторых случаях может быть необходимо увеличить SEMMAP чтобы он был одного порядка, что и SEMMNS. Этот параметр определяет размер карты ресурсов семафоров, где каждый смежный доступный блок семафоров должен иметь своё отображение. Когда освобождается набор семафоров, то он либо добавляется к существующей единице, отражающей соседний свободный блок, или же регистрируется как новая единица. Если карта заполнена, то свободные семафоры теряются (до перезагрузки). Фрагментация пространства семафором может раньше времени уменьшить количество доступных семафоров.
Параметр SEMMSL, который определяет количество семафоров в наборе, для PostgreSQL должно быть как минимум 17.
Другие настройки, относящиеся к "semaphore undo", вроде SEMMNU и SEMUME, не влияют на PostgreSQL.
AIX
Как минимум с версии 5.1 для таких параметров, как SHMMAX не должно требоваться никакой настройки, так как он по умолчанию позволяет использовать всю память как разделяемую. Такой тип настройки обычно используется для других БД, таких как DB/2
Тем не менее может потребоваться изменить глобальную информацию ulimit в /etc/security/limits, так как значения лимитов по умолчанию для размеров файлов (fsize) и количества файлов (nofiles) может быть слишком маленьким.
BSD/OS
Разделяемая память. По умолчанию поддерживается всего 4Мб разделяемой памяти. Помните, что эта разделяемая память не делится на страницы, она залочена в RAM. Для того, чтобы увеличить количество разделяемой памяти, поддерживаемое вашей системой, добавьте что-то вроде этого в файл конфигурации ядра:
options "SHMALL=8192"
option "SHMMAX=\(SHMALL*PAGE_SIZE\)"
SHMALL измеряется в 4Кб страницах, так что значение 1024 означает 4Мб разделяемой памяти. Так что в нашем примере мы увеличили его до 32Мб. Тем, кто использует версии 4.3 и старше, скорее всего придётся задать значение KRENEL_VIRTUAL_MB большее, чем значение по умолчанию в 248. После того, как изменения внесены, перекомпилируйте ядро и перезагрузитесь.
Семафоры: Скорее всего Вы захотите увеличить число доступных семафоров, так как общее значение в 60 позволит только около 50 подключений PostgreSQL. Задайте желательное значение в файле конфигурации ядра:
options "SEMMNI=40"
options "SEMMNS=240"
FreeBSD
Значения по умолчанию подходят только для небольших установок (например, значение по умолчанию для SHMMAX - 32Мб). Изменения могут быть внесены либо через sysctl, либо через интерфейс loader. Эти параметры могут быть установлены при помощи sysctl:
$sysctl -w kern.ipc.shmall=32768
$sysctl -w kern.ipc.shmmax=134217728
$sysctl -w kern.ipc.semmap=256
Для того, чтобы эти настройки сохранились после перезагрузки, измените /etc/sysctl.conf
Остальные настройки семафоров доступны только для чтения, но могут быть изменены перед загрузкой при помощи loader:
(loader) set kern.ipc.semmni=256
(loader) set kern.ipc.semmns=512
(loader) set kern.ipc.semmnu=256
И они тоже могут быть сохранены в /boot/loader.conf
Кроме того, Вы можете захотеть сконфигурировать своё ядро так, чтобы оно хранило разделяемую память только в ОЗУ и не свопила её. Это можно сделать при помощи настройки sysctl kern.ipc.shm_use_phys
Если Вы запускаете сервер в тюрьме FreeBSD, то Вам надо активировать настройку sysctl security.jail.sysvipc_allowed; кроме того, сервера, запущенные в разных тюрьмах, должны быть запущенны от разных пользователей ОС. Это обеспечивает больший уровень безопасности, так как не позволяет не-суперпользователю получить доступ к общей памяти или семафорам в другой тюрьме и, кроме того, это позволяет корректно работать коду уборщика PostgreSQL IPC. (В FreeBSD 6.0 и более поздних код уборщика IPC не может корректно определять процессы в разных тюрьмах, что не позволяет запустить сервера на одном и том же порту в разных тюрьмах).
FreeBSD версии до 4.0 работает как NetBSD и OpenBSD (см ниже)
NetBSD
OpenBSD
Опции SYSVSHM и SYSVSEM должны быть активированы при компиляции ядра (так и есть по умолчанию). Максимальный размер разделяемой памяти определяется опцией SHMMAXPGS (в страницах). Вот пример настройки параметров на NetBSD (OpenBSD использует option вместо options):
options        SYSVSHM
options        SHMMAXPGS=4096
options        SHMSEG=256

options        SYSVSEM
options        SEMMNI=256
options        SEMMNS=512
options        SEMMNU=256
options        SEMMAP=256
Кроме того, Вы можете захотеть сконфигурировать своё ядро так, чтобы оно хранило разделяемую память только в ОЗУ и не свопила её. Это можно сделать при помощи настройки sysctl kern.ipc.shm_use_phys
HP-UX
Значения по умолчанию подходят для нормальной установки. На HP-UX 10 значение по умолчанию для SEMMNS (равное 128) может быть недостаточным для больших БД.
Параметры IPC могут быть установлены в System Administration Manager (SAM) в Kernel Configuration -> Configurable Parametrs. Выберите Create A New Kernel после того, как закончите настройку.
Linux
Значение по умолчанию для максимального размера сегмента - 32Мб, что подходит только для очень небольших БД. Значение по умолчанию для общего количества - 2097152 страниц. Страница, почти всегда, это 4Кб, кроме случаев, когда ядро сконфигурировано с "huge pages" (для проверки этого используйте getconf PAGE_SIZE). Таким образом предел по умолчанию будет 8Gb, что зачастую достаточно, но не всегда.
Размер разделяемой памяти может быть изменён через sysctl. Например, для того, чтобы использовать 16Gb воспользуйтесь следующими командами:
$ sysctl -w kernel.shmmax=17179869184
$ sysctl -w kernel.shmall=4194304
Эти настройки могут быть сохранены в /etc/sysctl.conf для их сохранения после перезагрузки. Сделать это крайне рекомендуется.
В старых дистрибутивах может не быть программы sysctl, в таком случае внести изменения можно при помощи ФС /proc:
$ echo 17179869184 >/proc/sys/kernel/shmmax
$ echo 4194304 >/proc/sys/kernel/shmall
Остальные значения по умолчанию менять практически никогда не требуется.
Mac OS X
Рекомендуемый метод настройки разделяемой памяти в OS X - создать файл с именем /etc/sysclt.conf со следующим содержанием:
kern.sysv.shmmax=4194304
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=1024
Обратите внимание, что в некоторых версиях OS X, все пять параметров разделяемой памяти должны быть сохранены в /etc/sysctl.conf, иначе они могут быть проигнорированы.
Кроме того, последние релизы OS C игнорируют попытки задать значение SHMMAX, которое не делится на 4096.
SHMAL измеряется в страницах по 4Кб.
В старых версиях OS X Вам потребуется перезагрузка для того, чтобы параметры разделяемой памяти были применены. В 10.5 можно изменить все значения, кроме SHMMNI на лету при помощи sysctl. Но всё же лучше внести их в /etc/sysctl.conf, чтобы значения были сохранены после перезагрузки.
Файл /etc/sysctl.conf учитывается только в OS X 10.3.9 и позже. Если Вы используете более ранние версии релиза 10.3.х, то Вам нужно редактировать файл /etc/rc и изменить значения при помощи следующих команд:
sysctl -w kern.sysv.shmmax
sysctl -w kern.sysv.shmmin
sysctl -w kern.sysv.shmmni
sysctl -w kern.sysv.shmseg
sysctl -w kern.sysv.shmall
Обратите внимание, что /etc/rc обычно перезаписывается при обновлении OS X, так что будьте готовы повторить эти изменения после каждого обновления.
В OS X 10.2 и более ранних версиях, вместо этих команд отредактируйте файл /System/Library/StartupItems/SystemTunng/SystemTuning.
SCO OpenServer
В конфигурации по умолчанию доступно только 512Кб разделяемой памяти на сегмент. Для того, чтобы увеличить эти настройки, сначала перейдите в каталог /etc/conf/cf.d. Для того, что посмотреть текущее значение SHMMAX, выполните:
./configure -y SHMMAX
Для того, чтобы задать новое значение SHMMAX, выполните:
./configure SHMMAX=value
где value - новое значение (в байтах). После установки SHMMAX перестройте ядро:
./link_unix
и перезагрузитесь.
Solaris 2.6 - 2.9 (Solaris 6 - Solaris 9)
Значение по умолчанию для максимального размера сегмента разделяемой памяти слишком мал для PostgreSQL. Эти настройки могут быть изменены в /etc/system, например:
set shmsys:shminfo_shmmax=0x2000000
set shmsys:shminfo_shmmin=1
set shmsys:shminfo_shmmni=256
set shmsys:shminfo_shmseg=256

set semsys:seminfo_semmap=256
set semsys:seminfo_semmni=512
set semsys:seminfo_semmns=512
set semsys:seminfo_semmsl=32
Вам потребуется перезагрузка для того, чтобы эти изменения возымели действие. Смотрите так же http://sunsite.uakom.sk/sunworldonline/swol-09-1997/swol-09-insidesolaris.html, где говорится о разделяемой памяти на старых версиях Solaris.
Solaris 2.10 (Solaris 10)
OpenSolaris
В Solaris 10 и OpenSolaris значения по умолчанию для разделяемой памяти и семафоров вполне хороши для большинства PostgreSQL приложений. По умолчанию SHMMAX равен 1/4 ОЗУ. Если Вам нужно увеличить это значение, Вы должны использовать настройки проекта, связанные с пользователем postgres. Например, запустите от имени суперпользователя:
projadd -c "PostgreSQL DB User" -K "project.max-shm-memory=(privileged, 8GB, deny)" -U postgres -G postgres user.postgres
Эта команда добавляет проект user.postgres и увеличивает максимум разделяемой памяти для пользователя postgres до 8Gb и активируется после следующего раза, как пользователь входит в систему или когда Вы перезапустите PostgreSQL (не перезагрузите). Мы подразумеваем, что PostgreSQL запущен под пользователем postgres в группе postgres. Перезагрузка сервера не требуется.
Другие рекомендуемые настройки ядра нужны для серверов с большим количеством подключений:
project.max-shm-ids=(priv,32768,deny)
project.max-sem-ids=(priv,4096,deny)
project.max-msg-ids=(priv,4096,deny)
Кроме того, если Вы запускаете PostgreSQL в зоне, Вам может потребоваться увеличить лимит ресурсов зоны. Смотрите главу 2 "Projects and Tasks" в Solaris 10 System Administrator's Guide, где содержится более подробная информация об projects и prctl.
UnixWare
На UnixWare 7 максимальный размер сегмента разделяемой памяти всего 512 Кб в конфигурации по умолчанию. Для того, чтобы посмотреть текущее значение SHMMAX выполните:
/etc/conf/bin/idtune -g SHMMAX
что отобразит текущее значение, значение по умолчанию, минимальное и максимальное значения. Для того, чтобы задать новое значение SHMMAX выполните:
/etc/conf/bin/idtune SHMMAX value
где value - то значение, которые Вы хотите использовать (в байтах). После установки SHMMAX перестройте ядро:
/etc/conf/bin/idbuild -B
и перезагрузитесь.
Таблица 17-2. Использование разделяемой памяти PostgreSQL
ИспользованиеПриблизительное значение требуемой разделяемой памяти в байтах (как в 8.3)
Подключения(1800 + 270 * max_locks_per_transaction) * max_connections
Рабочие процессы autovacuum(1800 + 270 * max_locks_per_transaction) * autovacuum_max_workers
Подготовленные транзакции(770 + 270 * max_locks_per_transaction) * max_prepared_transactions
Разделяемые буферы дисков(block_size + 208) * shared_buffers
WAL буферы(wal_block_size + 8) * wal_buffers
Фиксированное требуемое значение770 kB

17.4.2 Лимиты ресурсов

Unix-подобные ОС используют различные лимиты ресурсов, которые могут вмешиваться в работу вашего PostgreSQL сервера. Наиболее важны лимиты на число процессов на пользователя, число открытых файлов на процесс и количество доступной памяти на процесс. Каждый из этих показателей имеет "жёсткий" и "мягкий" лимит. Мягкий лимит учитывается, но при этом пользователь может его изменить вплоть до жёсткого лимита. Жёсткий лимит может быть изменён только суперпользователем. Системный вызов setrlimit отвечает за настройку этих параметров. Встроенные команды оболочки ulimit (в оболочке Борна) или limit (csh) используются для контроля этих параметров из командной строки. На BSD системах файл /etc/login.conf управляет лимитами ресурсов на этапе входа в систему. Более подробно об этом можно узнать в документации к вашей ОС. Интересующие нас параметры - maxproc, openfiles и datasize. Например:
default:\
...
        :datasize-cur=256M:\
        :maxproc-cur=256:\
        :openfiles-cur=256:\
...
(-cur это мягкий лимит. Для жёсткого лимита используйте -max)
Ядра так же могут иметь системные ограничения на некоторые ресурсы.
На Linux /proc/sys/fs/file-max определяет максимальное число открытых файлов, которое будет поддерживать система. Оно может быть изменено записыванием другого числа в этот файл или присвоением в /etc/sysctl.conf. Максимальное число faqkjd на процесс фиксируется в ядре на момент компиляции; см /usr/src/linux/Documentation/proc.txt где это описано подробнее
Сервер PostgreSQL использует один процесс на соединение, так что у Вас должна быть возможность создавать так много процессов, сколько нужно подключений, кроме остальных процессов, которые Вам нужны. Обычно это не проблема, но если Вы запускаете несколько серверов на одной машине, это может создать для Вас проблему.
Лимит по умолчанию на открытые файлы зачастую имеют "дружественные" значения, что позволяет многим пользователям существовать на одной машине без использования неуместных системных ресурсов. Если Вы запускаете много серверов на машине, то, возможно, это то, что Вы хотите, но на выделенном сервере Вы можете захотеть повысить это ограничение.
С другой стороны, некоторые системы позволяют отдельным процессам открывать большое число файлов; но если так пытаются вести себя несколько процессов, то лимит системы может быть запросто исчерпан. Если Вы обнаружили, что это и произошло и Вы не хотите изменять лимиты системы, Вы можете настроить параметр конфигурации max_files_per_process, чтобы ограничить количество открытых файлов процессом.

17.4.3 Linux Memory Overcommit

В Linux 2.4 и более поздних версиях поведение виртуальной памяти не оптимально для PostgreSQL. Из-за того, как ядро реализует распределение памяти, ядро может прервать процесс сервера PostgreSQL (мастер-процесс сервера) если память, требуемая другим процессом исчерпывает объём виртуальной памяти.
Если это происходит, то Вы увидите сообщение ядра, которое будет выглядеть вроде этого (посмотрите в документацию вашей системы и в настройки конфигурации где искать это сообщение):
Out of Memory: Killed process 12345 (postgres).
Это означает, что процесс postgres был прерван из-за проблем с памятью. Уже существующие соединения БД будут работать нормально, но новые соединения не будут установлены. Для того, чтобы восстановить нормальную работу нужно перезапустить PostgreSQL.
Один из способов избежать эту проблему - запустить PostgreSQL на машине, где Вы можете быть уверены, что другой процесс не потратит всё память машины. Если на машине туго с памятью, то можно увеличить пространство свопирования ОС, так как out-of-memory (OOM) убийца срабатывает только когда исчерпывается физическая и своп память.
На Linux 2.6 и более поздних версиях возможно изменить поведение ядра, так что такой проблемы не возникнет. Хотя эти настройки не предотвращают запуск OOM убийцы, но они существенно снижают шансы на это и потому возможно более разумное поведение системы. Это делается установкой режима strict overcommit посредством sysctl:
sysctl -w vm.overcommit_memory=2
или размещением соответствующей записи в /etc/sysctl.conf. Кроме того, Вы можете захотеть изменить  связанную настройку vm.overcommit_ratio. Более подробно смотрите в документации файла Documentation/vm/overcommit-accounting.
Другой подход, который можно использовать с или без изменения vm.overcommit_memory, это задать процесс-специфичное значение oom_adj для процесса postmaster равным -17, что гарантирует, что он не будет целью OOM убийцы. Самый простой способ добиться этого:
echo -17 > /proc/self/oom_adj
в скрипте запуска postmaster прямо перед тем, как будет запущен сам postmaster. Обратите внимание, что выполнить это действие нужно из под суперпользователя или это не будет иметь никакого эффекта; так что суперпользовательский скрипт запуска самое лучшее для этого место. Если Вы так и поступите, то, наверно, Вы захотите собрать PostgreSQL c -DLINUX_OOM_ADJ=0, добавленным к CFLAGS. В этом случае дочерние процессы postmaster ,elen запущены со значением oom_adj = 0, так что OOM убийца всё ещё может использовать их как цели при необходимости.
Обратите внимание: некоторые ядра Linux 2.4 могут иметь ранние версии параметра sysctl версии 2.6. Но, если Вы установите vm.overcommit_memory = 2 на ядре 2.4, которое не имеет нужного кода, это лишь ухудшит ситуацию, не улучшит её. Так что рекомендуется проверить исходники ядра (смотрите функцию vm_enough_memory в mm/mmap.c) чтобы убедиться, что эта опция поддерживает нужную Вам функциональность перед тем, как Вы её попробуете. Наличие файла документации overcommit-accounting не должно быть расценено как указание на поддержку этой возможности. Если есть сомнения - проконсультируйтесь со знатоками ядра или поставщиком ядра.

Комментариев нет:

Отправить комментарий