Documentação do PostgreSQL 7.4.1 | ||||
---|---|---|---|---|
Anterior | Início | Capítulo 16. Ambiente do servidor em tempo de execução | Fim | Próxima |
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 há realmente necessidade de uma instalação "grande"). Caso tenha deparado com este tipo de problema, prossiga a leitura.
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 de 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 vista 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] | veja 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 haver necessidade de 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.
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.
$ bpatch -r sysptsize 0x9 = 9Em 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.
options "SEMMNI=40" options "SEMMNS=240"
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.
$ echo 134217728 >/proc/sys/kernel/shmall $ echo 134217728 >/proc/sys/kernel/shmmaxEstes 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 = 134217728Este 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.
sysctl -w kern.sysv.shmmax sysctl -w kern.sysv.shmmin sysctl -w kern.sysv.shmmni sysctl -w kern.sysv.shmseg sysctl -w kern.sysv.shmallNo OS X 10.3 estes comandos foram movidos para /etc/rc devendo ser editados neste local.
./configure -y SHMMAXPara definir um novo valor para SHMMAX deve ser executado
./configure SHMMAX=valoronde valor é o novo valor que se deseja utilizar (em bytes). Após definir SHMMAX o núcleo deve ser reconstruído
./link_unixe o sistema reinicializado.
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=32O computador deve ser reinicializado para as modificações terem efeito. Também deve ser vista a página Shared memory uncovered para obter informações sobre memória compartilhada sob o Solaris.
/etc/conf/bin/idtune -g SHMMAXque 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 valoronde 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 -Be o sistema reinicializado.
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.
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á recebida 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 voltar ao normal é 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 um 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-se querer modificar a definição relacionada vm.overcommit_ratio. Para obter detalhes deve ser visto o arquivo de documentação do núcleo Documentation/vm/overcommit-accounting.
É relatado 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 vista 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.
[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 a aplicação. GNUsound - FAQ (N. do T.) |