16.5. Gerência dos recursos do núcleo

Uma instalação grande do PostgreSQL pode exaurir, rapidamente, vários limites de recurso do sistema operacional (Em alguns sistemas, o padrão de distribuição é tão baixo que, na verdade, nem é necessária uma instalação "grande" para exaurir os recursos). Caso tenha deparado com este tipo de problema, prossiga a leitura.

16.5.1. Memória compartilhada e semáforos

A memória compartilhada e os semáforos são referenciados coletivamente como "System V IPC" [1] (junto com as filas de mensagens, que não são relevantes para o PostgreSQL). Quase todo sistema operacional moderno fornece estas funcionalidades, mas nem todos as têm ativas ou com tamanho suficiente por padrão, especialmente os sistemas herdados do BSD (Para os ports para o QNX e para o BeOS, o PostgreSQL fornece sua própria implementação de substituição destas funcionalidades).

A completa falta destas funcionalidades é geralmente manifestada por um erro de "Chamada de sistema ilegal" na inicialização do servidor. Neste caso, não existe nada a ser feito além de reconfigurar o núcleo. O PostgreSQL não funciona sem estas funcionalidades.

Quando o PostgreSQL excede um dos vários limites rígidos do IPC, o servidor se recusa a inicializar, e deve deixar uma mensagem de erro instrutiva descrevendo o problema encontrado e o que fazer sobre o mesmo (Também deve ser consultada a Seção 16.3.1.) Os parâmetros relevantes do núcleo possuem nomes consistentes entre sistemas diferentes; A Tabela 16-2 mostra uma visão geral. Entretanto, os métodos para defini-los variam. Abaixo são fornecidas sugestões para algumas plataformas. Não se deve esquecer que geralmente é necessário reinicializar o computador e até, possivelmente, recompilar o núcleo para alterar estas definições.

Tabela 16-2. Parâmetros do IPC do System V

Nome Descrição Valores razoáveis
SHMMAX Tamanho máximo de um segmento de memória compartilhada (bytes) [a] 250 kB + 8.2 kB * shared_buffers + 14.2 kB * max_connections até o infinito
SHMMIN Tamanho mínimo de um segmento de memória compartilhada (bytes) 1
SHMALL Quantidade total de memória compartilhada disponível (bytes ou páginas) se em bytes, o mesmo que SHMMAX; se em páginas, ceil(SHMMAX/PAGE_SIZE)
SHMSEG Número máximo de segmentos de memória compartilhada por processo somente 1 segmento é necessário, mas o padrão é muito maior
SHMMNI Número máximo de segmentos de memória compartilhada para todo o sistema como SHMSEG mais espaço para outras aplicações
SEMMNI Número máximo de identificadores de semáforos (ou seja, conjuntos) pelo menos ceil(max_connections / 16)
SEMMNS Número máximo de semáforos para todo o sistema ceil(max_connections / 16) * 17 mais espaço para outras aplicações
SEMMSL Número máximo de semáforos por conjunto pelo menos 17
SEMMAP Número de entradas no mapa de semáforos [b] consulte o texto
SEMVMX Valor máximo de um semáforo pelo menos 1000 (O padrão é geralmente 32767; não mude a não ser quando for obrigado a fazê-lo)
Notas:
a. A função shmget () é utilizada para obter acesso a um segmento de memória compartilhada. Esta função falha se o valor do tamanho for menor que SHMMIN ou maior do que SHMMAX. Sun Product Documentation (N. do T.)
b. SEMMAP deve ser definido como o produto de SEMMNI e SEMMSL: (SEMMAP = SEMMNI * SEMMSL). Setting our sights on semaphores (N. do T.)

O parâmetro de memória compartilhada mais importante é SHMMAX, o tamanho máximo, em bytes, de um segmento de memória compartilhada. Se for recebida uma mensagem de erro da função shmget como "Argumento inválido", é provável que este limite tenha sido excedido. O tamanho do segmento de memória compartilhada requerido varia tanto com o número de buffers requisitados (opção -B) quanto com o número de conexões permitidas (opção -N), embora esta última seja mais significativa (É possível, como uma solução temporária, diminuir estas definições para eliminar o problema). Como uma aproximação grosseira, o tamanho de segmento requerido pode ser estimado conforme sugerido em Tabela 16-2. Toda mensagem de erro que vier a ser recebida conterá o tamanho da alocação requerida que falhou.

Alguns sistemas também possuem um limite para a quantidade total de memória compartilhada do sistema (SHMALL). Deve-se ter certeza que é grande o suficiente para o PostgreSQL mais as outras aplicações que utilizam segmentos de memória compartilhada. (Cuidado: em muitos sistemas SHMALL é medido em páginas, e não em bytes).

Menos provável de causar problema é o tamanho mínimo para os segmentos de memória compartilhada (SHMMIN), que deve ser no máximo aproximadamente 256 kB para o PostgreSQL (geralmente é apenas 1). O número máximo de segmentos para todo o sistema (SHMMNI) ou por processo (SHMSEG) não devem causar problema a menos que o sistema os tenha definido como zero.

O PostgreSQL utiliza um semáforo por conexão permitida (opção -N), em conjuntos de 16. Cada um destes conjuntos também contém um 17º semáforo contendo um "número mágico", para detectar colisões com conjuntos de semáforos utilizados por outras aplicações. O número máximo de semáforos no sistema é definido por SEMMNS que, conseqüentemente, deve ser pelo menos tão alto quanto max_connections mais um adicional para cada 16 conexões permitidas (veja a fórmula na Tabela 16-2). O parâmetro SEMMNI determina o limite do número de conjuntos de semáforos que podem existir no sistema de uma vez. Portanto, este parâmetro deve ser pelo menos igual a ceil(max_connections / 16). Diminuir o número de conexões permitidas é um recurso temporário para evitar falhas, geralmente informadas pela mensagem "Nenhum espaço disponível na unidade" emitida pela função semget, que confunde.

Em alguns casos também pode ser necessário aumentar SEMMAP, para que fique pelo menos na ordem de grandeza de SEMMNS. Este parâmetro define o tamanho do mapa de recursos de semáforos, no qual cada bloco contíguo de semáforos disponíveis precisa de uma entrada. Quando um conjunto de semáforos é liberado, este conjunto é adicionado a uma entrada existente adjacente ao bloco liberado, ou é registrado sob uma nova entrada no mapa. Se o mapa estiver cheio, os semáforos liberados serão perdidos (até a reinicialização do servidor). A fragmentação do espaço de semáforos pode, ao longo do tempo, fazer com que haja menos semáforos disponíveis do que deveria haver.

O parâmetro SEMMSL, que determina quantos semáforos podem existir em um conjunto, deve ser pelo menos igual a 17 para o PostgreSQL.

Várias outras definições relacionadas com "desfazer semáforo", como SEMMNU e SEMUME, não são de interesse do PostgreSQL.

BSD/OS

Memória compartilhada. Por padrão, são suportados somente 4 MB de memória compartilhada. Deve-se ter em mente que a memória compartilhada não é paginável; fica bloqueada na RAM. Para aumentar a quantidade de memória compartilhada suportada pelo sistema, deve ser adicionado algo parecido com as linhas mostradas abaixo ao arquivo de configuração do núcleo.

options "SHMALL=8192"
options "SHMMAX=\(SHMALL*PAGE_SIZE\)"

SHMALL é medido em páginas de 4KB, portanto um valor igual a 1024 representa 4 MB de memória compartilhada. Desta forma, as linhas acima aumentam para 32 MB o máximo de área de memória compartilhada. Para os usuários da versão 4.3 ou posterior, provavelmente será necessário aumentar KERNEL_VIRTUAL_MB para um valor acima do valor padrão de 248. Uma vez que as alterações tenham sido efetuadas, o núcleo deve ser recompilado e o sistema reinicializado.

Os usuários da versão 4.0, ou anterior, devem utilizar bpatch para descobrir o valor de sysptsize do núcleo corrente. Este valor é computado dinamicamente durante a inicialização do sistema operacional.

$ bpatch -r sysptsize
0x9 = 9

Em seguida, deve ser adicionado SYSPTSIZE com um valor fixo no arquivo de configuração do núcleo. O valor encontrado utilizando bpatch deve ser aumentado; deve ser adicionado 1 para cada 4 MB adicionais de memória compartilhada desejada.

options "SYSPTSIZE=16"

sysptsize não pode ser mudado por sysctl.

Semáforos. Provavelmente vai ser necessário aumentar o número de semáforos também; o valor total padrão do sistema, igual a 60, permite apenas em torno de 50 conexões do PostgreSQL Os valores desejados devem ser definidos no arquivo de configuração do núcleo como, por exemplo:

options "SEMMNI=40"
options "SEMMNS=240"
FreeBSD
NetBSD
OpenBSD

As opções SYSVSHM e SYSVSEM precisam estar ativadas quando o núcleo é compilado (Estão por padrão). O tamanho máximo da memória compartilhada é determinado pela opção SHMMAXPGS (em páginas). A seguir está mostrado um exemplo de como definir os vários parâmetros:

options         SYSVSHM
options         SHMMAXPGS=4096
options         SHMSEG=256

options         SYSVSEM
options         SEMMNI=256
options         SEMMNS=512
options         SEMMNU=256
options         SEMMAP=256

(No NetBSD e no OpenBSD a palavra chave é, na verdade, option, no singular).

Também pode-se querer configurar o núcleo para que bloqueie a memória compartilhada na RAM, impedindo que seja paginada para a área de troca (swap). Deve ser utilizada a definição kern.ipc.shm_use_phys do sysctl.

HP-UX

A definição padrão costuma ser suficiente para as instalações normais. No HP-UX 10, o padrão de fábrica para SEMMNS é 128, que pode ser muito baixo para servidores de banco de dados grandes.

Os parâmetros do IPC podem ser definidos no System Administration Manager (SAM), sob Kernel Configuration->Configurable Parameters. Quando tiver acabado clique em Create A New Kernel.

Linux

O limite padrão de memória compartilhada (tanto SHMMAX quanto SHMALL) é de 32 MB nos núcleos 2.2, mas pode ser modificado no arquivo de sistema proc (sem reinicializar o Linux). Por exemplo, para permitir 128 MB:

$ echo 134217728 >/proc/sys/kernel/shmall
$ echo 134217728 >/proc/sys/kernel/shmmax

Estes comandos podem ser colocados em um script executado durante a inicialização.

Como alternativa, pode ser utilizado sysctl, se estiver disponível, para controlar estes parâmetros. Deve-se procurar pelo arquivo chamado /etc/sysctl.conf e adicionar linhas como as mostradas abaixo ao arquivo:

kernel.shmall = 134217728
kernel.shmmax = 134217728

Este arquivo geralmente é processado durante a inicialização, mas sysctl também pode ser chamada explicitamente posteriormente.

Os outros parâmetros possuem tamanho suficiente para qualquer aplicação. Se quiser ver por si próprio, olhe em /usr/src/linux/include/asm-xxx/shmparam.h e /usr/src/linux/include/linux/sem.h.

MacOS X

No OS X 10.2, e anteriores, deve ser editado o arquivo /System/Library/StartupItems/SystemTuning/SystemTuning e modificados os valores nos seguintes comandos:

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

No OS X 10.3 estes comandos foram movidos para /etc/rc devendo ser editados neste local. É necessário reinicializar o computador para que as alterações passem a valer. Deve ser observado que /etc/rc geralmente é sobrescrito pelas atualizações do OS X (como 10.3.6 para 10.3.7), portanto é esperado que seja necessário refazer a edição a cada atualização.

Nesta plataforma SHMALL é medido em páginas de 4KB.

SCO OpenServer

Na configuração padrão, somente são permitidos 512 kB de memória compartilhada por segmento, suficiente para cerca de -B 24 -N 12. Para aumentar esta definição, primeiro deve-se tornar o diretório /etc/conf/cf.d o diretório corrente. Para exibir o valor corrente de SHMMAX deve ser executado:

./configure -y SHMMAX

Para definir um novo valor para SHMMAX deve ser executado

./configure SHMMAX=valor

onde valor é o novo valor que se deseja utilizar (em bytes). Após definir SHMMAX o núcleo deve ser reconstruído

./link_unix

e o sistema reinicializado.

AIX

A partir da versão 5.1, no mínimo, não deve ser necessário fazer qualquer configuração especial para parâmetros como SHMMAX, uma vez que parece estar configurado para permitir que toda a memória seja utilizada como memória compartilhada. Este é o tipo de configuração utilizado normalmente para outros bancos de dados como o DB2.

Pode, entretanto, ser necessário modificar a informação global ulimit em /etc/security/limits, uma vez que os limites rígidos padrão para o tamanho dos arquivos (fsize) e número de arquivos (nofiles) podem ser muito baixos.

Solaris

Ao menos na versão 2.6, o tamanho máximo padrão dos segmentos de memória compartilhada é muito baixo para o PostgreSQL. As definições relevantes podem ser mudadas em /etc/system como, por exemplo:

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

É necessário reinicializar o computador para que as alterações passem a valer.

Também deve ser consultada a página Shared memory uncovered para obter informações sobre memória compartilhada sob o Solaris.

UnixWare

No UnixWare 7 o tamanho máximo para os segmentos de memória compartilhada é de 512 kB na configuração padrão. É suficiente para cerca de -B 24 -N 12. Para obter o valor corrente de SHMMAX, deve ser executado

/etc/conf/bin/idtune -g SHMMAX

que mostra os valores corrente, padrão, mínimo e máximo. Para definir um novo valor para SHMMAX, deve ser executado

/etc/conf/bin/idtune SHMMAX valor

onde valor é o novo valor que se deseja utilizar (em bytes). Após definir SHMMAX, o núcleo deve ser reconstruído:

/etc/conf/bin/idbuild -B

e o sistema reinicializado.

16.5.2. Limites de recursos

Os sistemas operacionais da família Unix obrigam respeitar vários tipos de limite de recursos que podem interferir com a operação do servidor PostgreSQL. São de particular importância os limites do número de processos por usuário, de número de arquivos abertos por processo, e a quantidade de memória disponível para cada processo. Cada um destes possui um limite "rígido" e um "flexível". O limite flexível é o que realmente conta, mas pode ser alterado pelo usuário até o limite rígido. O limite rígido somente pode ser alterado pelo usuário root. A chamada de sistema setrlimit é responsável pela definição destes parâmetros. São utilizados o comando interno do interpretador de comandos ulimit (interpretadores de comandos Bourne) ou limit (csh) para controlar os limites de recursos a partir da linha de comandos. Nos sistemas derivados do BSD o arquivo /etc/login.conf controla os limites dos vários recursos definidos durante a autenticação. Para obter detalhes deve ser vista a documentação do sistema operacional. Os parâmetros relevantes são maxproc, openfiles e datasize. Por exemplo:

default:\
...
        :datasize-cur=256M:\
        :maxproc-cur=256:\
        :openfiles-cur=256:\
...

(-cur é o limite flexível. Deve ser anexado -max para definir o limite rígido).

Os núcleos também podem ter limites para alguns recursos para todo o sistema.

O servidor PostgreSQL utiliza um processo por conexão e, portanto, deve ser especificado pelo menos tantos processos quantas forem as conexões permitidas, em adição ao que for necessário para o restante do sistema. Normalmente não é um problema, mas se forem executados vários servidores na mesma máquina pode ficar apertado.

O limite padrão original para o número de arquivos abertos geralmente é definido como um valor "socialmente amigável", para permitir a coexistência de muitos usuários em uma mesma máquina sem utilizar uma fração não apropriada dos recursos do sistema. Se forem executados vários servidores na mesma máquina provavelmente é o que se deseja, mas para servidores dedicados pode ser necessário aumentar este limite.

Por outro lado, alguns sistemas podem permitir que cada processo abra um grande número de arquivos; se mais que uns poucos processos o fizerem, então o limite global para todo o sistema pode ser facilmente excedido. Se isto estiver acontecendo, e não for desejado alterar o limite para todo o sistema, pode ser definido o parâmetro de configuração max_files_per_process do PostgreSQL para limitar a quantidade de arquivos abertos.

16.5.3. Sobre-alocação de memória no Linux

No Linux 2.4 e posteriores, o comportamento padrão de memória virtual não é o ótimo para o PostgreSQL. Devido à maneira como o núcleo implementa a sobre-alocação (overcommit) de memória, o núcleo pode fechar o servidor PostgreSQL (o processo postmaster), se a demanda por memória de um outro processo fizer com que o sistema fique sem memória virtual. [2]

Caso aconteça, será vista uma mensagem do núcleo parecida com esta (deve ser consultada a documentação e configuração do sistema para achar onde este tipo de mensagem pode ser vista):

Out of Memory: Killed process 12345 (postmaster).

Esta mensagem indica que o processo postmaster foi fechado devido à falta de memória. Embora as conexões com os bancos de dados existentes continuem funcionando normalmente, não é aceita nenhuma nova conexão. Para recuperar é necessário reinicializar o PostgreSQL.

Uma forma de evitar este problema é executar o PostgreSQL em uma máquina onde se tenha certeza que outros processos não vão deixar a máquina sem memória.

No Linux 2.6 e posteriores, uma solução melhor é modificar o comportamento do núcleo para que não haja "sobre-alocação" de memória. Isto é feito selecionando o modo estrito de sobre-alocação através do comando sysctl:

sysctl -w vm.overcommit_memory=2

ou colocando uma entrada equivalente em /etc/sysctl.conf. Também pode ser necessário modificar a percentagem de sobre-alocação (vm.overcommit_ratio). Para obter detalhes deve ser visto o arquivo de documentação do núcleo Documentation/vm/overcommit-accounting. [3]

Existe relato que algumas distribuições do núcleo 2.4 do Linux possuem uma versão inicial do parâmetro overcommit do comando sysctl da versão 2.6. Entretanto, definir vm.overcommit_memory como 2 em um núcleo que não possui o código relevante torna as coisas piores, e não melhores. Recomenda-se a inspeção do código fonte do núcleo utilizado (deve ser consultada a função vm_enough_memory no arquivo mm/mmap.c), para verificar o que é suportado na versão utilizada antes de tentar utilizar numa instalação 2.4. A presença do arquivo de documentação overcommit-accounting não deve ser assumida como um evidência que a funcionalidade está presente. Em caso de dúvida, deve ser consultado um especialista no núcleo ou o distribuidor do núcleo utilizado.

Notas

[1]

Com o System V a AT&T introduziu três novas formas de facilidade de comunicação entre processos (IPC) (filas de mensagens, semáforos e memória compartilhada). Embora o comitê POSIX ainda não tenha completado a padronização destas facilidades, a maioria das implementações dão suporte as mesmas. Além disso, Berkeley (BSD) utiliza soquetes como sua forma primária de IPC, em vez dos elementos do System V. O Linux tem capacidade para utilizar as duas formas de IPC, tanto BSD quanto System V. System V IPC (N. do T.)

[2]

memory overcommit — a sobre-alocação de memória é uma funcionalidade do núcleo do Linux que permite as aplicações alocarem mais memória do que realmente existe. A idéia por trás desta funcionalidade é que algumas aplicações alocam grandes quantidades de memória "apenas para o caso de precisarem", mas na verdade nunca utilizam esta memória. Portanto, a sobre-alocação de memória permite a execução de mais aplicações do que na verdade cabe na memória, desde de que as aplicações realmente não utilizem a memória alocada. Se o fizerem, o núcleo fecha o aplicativo. GNUsound - FAQ (N. do T.)

[3]

Fedora Core 3 — arquivo /usr/share/doc/kernel-doc-2.6.11/Documentation/vm/overcommit-accounting — o núcleo do Linux suporta os seguintes modos de tratamento de sobre-alocação: 0 - tratamento heurístico de sobre-alocação; 1 - sempre faz sobre-alocação; 2 - sem sobre-alocação. (N. do T.)

SourceForge.net Logo CSS válido!