O postmaster usa CPU excessiva e gravações de disco

9

usando o PostgreSQL 9.1.2

Estou vendo uso excessivo de CPU e grandes quantidades de gravações no disco de tarefas do postmaster. Isso acontece mesmo quando meu aplicativo está fazendo quase nada (10s de inserções por minuto). No entanto, existe um número razoável de conexões abertas.

Eu tenho tentado determinar o que no meu aplicativo está causando isso. Eu sou muito novo com postgresql, e não cheguei a lugar nenhum até agora. Eu ativei algumas opções de registro no meu arquivo de configuração, e olhei para conexões na tabela pg_stat_activity, mas elas estão todas ociosas. No entanto, cada conexão consome ~ 50% da CPU e está gravando ~ 15M / s no disco (sem ler nada).

Estou basicamente usando o arquivo postgresql.conf com pequenos ajustes. Eu apreciaria qualquer conselho ou indicações sobre o que posso fazer para rastrear isso.

Aqui está uma amostra do que o top / iotop está me mostrando:

Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                          
17057 postgres  20   0  236m  33m  13m R 45.0  0.1  73:48.78 postmaster                                                                                                                       
17188 postgres  20   0  219m  15m  11m R 42.3  0.0  61:45.57 postmaster                                                                                                                       
17963 postgres  20   0  219m  16m  11m R 42.3  0.1  27:15.01 postmaster                                                                                                                       
17084 postgres  20   0  219m  15m  11m S 41.7  0.0  63:13.64 postmaster                                                                                                                       
17964 postgres  20   0  219m  17m  12m R 41.7  0.1  27:23.28 postmaster                                                                                                                       
18688 postgres  20   0  219m  15m  11m R 41.3  0.0  63:46.81 postmaster                                                                                                                       
17088 postgres  20   0  226m  24m  12m R 41.0  0.1  64:39.63 postmaster                                                                                                                       
24767 postgres  20   0  219m  17m  12m R 41.0  0.1  24:39.24 postmaster                                                                                                                       
18660 postgres  20   0  219m  14m 9.9m S 40.7  0.0  60:51.52 postmaster                                                                                                                       
18664 postgres  20   0  218m  15m  11m S 40.7  0.0  61:39.61 postmaster                                                                                                                       
17962 postgres  20   0  222m  19m  11m S 40.3  0.1  11:48.79 postmaster                                                                                                                       
18671 postgres  20   0  219m  14m   9m S 39.4  0.0  60:53.21 postmaster                                                                                                                       
26168 postgres  20   0  219m  15m  10m S 38.4  0.0  59:04.55 postmaster  


Total DISK READ: 0.00 B/s | Total DISK WRITE: 195.97 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                                                                                                                        
17962 be/4 postgres    0.00 B/s   14.83 M/s  0.00 %  0.25 % postgres: aggw aggw [local] idle
17084 be/4 postgres    0.00 B/s   15.53 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17963 be/4 postgres    0.00 B/s   15.00 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17188 be/4 postgres    0.00 B/s   14.80 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17964 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
18664 be/4 postgres    0.00 B/s   15.13 M/s  0.00 %  0.23 % postgres: aggw aggw [local] idle
17088 be/4 postgres    0.00 B/s   14.71 M/s  0.00 %  0.13 % postgres: aggw aggw [local] idle
18688 be/4 postgres    0.00 B/s   14.72 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
24767 be/4 postgres    0.00 B/s   14.93 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18671 be/4 postgres    0.00 B/s   16.14 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
17057 be/4 postgres    0.00 B/s   13.58 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
26168 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18660 be/4 postgres    0.00 B/s   15.85 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle

Atualização : muito da gravação de arquivos parece ser de alguns arquivos temporários (?) no diretório $ PG_DATA / base /. Meu entendimento da estrutura do arquivo aqui é que cada tabela é basicamente armazenada como um arquivo cujo nome é OID da mesa. No entanto, existem vários arquivos denominados tnn_nnnnnnn , e são esses arquivos que parecem ser gravados (talvez gravados) constantemente. Quais são esses arquivos para? Existem ~ 4700 dos arquivos, e todos têm 8K de tamanho:

-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t12_1430975
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t16_1432736
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439066
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436243
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436210
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t19_1393372
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439051
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t8_1430334

Atualizar : Correndo strace nos processos postmaster, basicamente, mostra um monte de coisas de E / S de arquivos:

open("base/16388/t24_1435947_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
ftruncate(9, 0)                         = 0
lseek(9, 0, SEEK_END)                   = 0
open("base/16388/t24_1435941", O_RDWR)  = 18
lseek(18, 0, SEEK_END)                  = 0
write(9, "
CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;
Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                          
17057 postgres  20   0  236m  33m  13m R 45.0  0.1  73:48.78 postmaster                                                                                                                       
17188 postgres  20   0  219m  15m  11m R 42.3  0.0  61:45.57 postmaster                                                                                                                       
17963 postgres  20   0  219m  16m  11m R 42.3  0.1  27:15.01 postmaster                                                                                                                       
17084 postgres  20   0  219m  15m  11m S 41.7  0.0  63:13.64 postmaster                                                                                                                       
17964 postgres  20   0  219m  17m  12m R 41.7  0.1  27:23.28 postmaster                                                                                                                       
18688 postgres  20   0  219m  15m  11m R 41.3  0.0  63:46.81 postmaster                                                                                                                       
17088 postgres  20   0  226m  24m  12m R 41.0  0.1  64:39.63 postmaster                                                                                                                       
24767 postgres  20   0  219m  17m  12m R 41.0  0.1  24:39.24 postmaster                                                                                                                       
18660 postgres  20   0  219m  14m 9.9m S 40.7  0.0  60:51.52 postmaster                                                                                                                       
18664 postgres  20   0  218m  15m  11m S 40.7  0.0  61:39.61 postmaster                                                                                                                       
17962 postgres  20   0  222m  19m  11m S 40.3  0.1  11:48.79 postmaster                                                                                                                       
18671 postgres  20   0  219m  14m   9m S 39.4  0.0  60:53.21 postmaster                                                                                                                       
26168 postgres  20   0  219m  15m  10m S 38.4  0.0  59:04.55 postmaster  


Total DISK READ: 0.00 B/s | Total DISK WRITE: 195.97 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                                                                                                                        
17962 be/4 postgres    0.00 B/s   14.83 M/s  0.00 %  0.25 % postgres: aggw aggw [local] idle
17084 be/4 postgres    0.00 B/s   15.53 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17963 be/4 postgres    0.00 B/s   15.00 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17188 be/4 postgres    0.00 B/s   14.80 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17964 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
18664 be/4 postgres    0.00 B/s   15.13 M/s  0.00 %  0.23 % postgres: aggw aggw [local] idle
17088 be/4 postgres    0.00 B/s   14.71 M/s  0.00 %  0.13 % postgres: aggw aggw [local] idle
18688 be/4 postgres    0.00 B/s   14.72 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
24767 be/4 postgres    0.00 B/s   14.93 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18671 be/4 postgres    0.00 B/s   16.14 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
17057 be/4 postgres    0.00 B/s   13.58 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
26168 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18660 be/4 postgres    0.00 B/s   15.85 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t12_1430975
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t16_1432736
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439066
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436243
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436210
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t19_1393372
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439051
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t8_1430334
open("base/16388/t24_1435947_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
ftruncate(9, 0)                         = 0
lseek(9, 0, SEEK_END)                   = 0
open("base/16388/t24_1435941", O_RDWR)  = 18
lseek(18, 0, SEEK_END)                  = 0
write(9, "
CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;
%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%00%pre%00 %pre%%pre%%pre%%pre%b1%pre%%pre%%pre%%pre%"..., 8192) = 8192 lseek(18, 0, SEEK_END) = 0 close(9) = 0 open("base/16388/t24_1435947", O_RDWR) = 9 lseek(9, 0, SEEK_END) = 8192 close(18) = 0 close(9) = 0 open("base/16388/t24_1435944_fsm", O_RDWR) = -1 ENOENT (No such file or directory) open("base/16388/t24_1435944_vm", O_RDWR) = -1 ENOENT (No such file or directory) open("base/16388/t24_1435944", O_RDWR) = 9 lseek(9, 0, SEEK_END) = 0 close(9) = 0
%pre%%pre%%pre%%pre%%pre%%pre%%pre%00%pre%00 %pre%%pre%%pre%%pre%b1%pre%%pre%%pre%%pre%"..., 8192) = 8192 lseek(18, 0, SEEK_END) = 0 close(9) = 0 open("base/16388/t24_1435947", O_RDWR) = 9 lseek(9, 0, SEEK_END) = 8192 close(18) = 0 close(9) = 0 open("base/16388/t24_1435944_fsm", O_RDWR) = -1 ENOENT (No such file or directory) open("base/16388/t24_1435944_vm", O_RDWR) = -1 ENOENT (No such file or directory) open("base/16388/t24_1435944", O_RDWR) = 9 lseek(9, 0, SEEK_END) = 0 close(9) = 0

Atualizar : Portanto, esse problema parece ser tudo a ver com tabelas temporárias. Nós mudamos nossa configuração para que as tabelas temporárias sejam tabelas 'regulares', e toda a atividade do disco foi embora, e o desempenho está de volta para onde eu esperava que fosse. Agora, essa mudança foi apenas um teste rápido e sujo: se realmente mudarmos para usar tabelas regulares, temos problemas com simultaneidade e limpeza. Tabernas temporárias são realmente tão más, ou estamos abusando delas?

Atualizar : Mais alguns antecedentes. Estou usando um middleware de replicação baseado em declarações desenvolvido internamente. É bastante maduro e tem sido usado em vários projetos ao longo de vários anos, mas usando o MySQL. Nós só estamos trabalhando com o PostgreSQL há um ano ou dois. Nós estávamos essencialmente usando as tabelas temporárias como parte do mecanismo de replicação. Sempre que uma nova conexão é estabelecida, criamos uma tabela temporária para cada tabela no banco de dados. Com conexões 10-20 (de longa duração) e ~ 50 tabelas, isso pode equivaler a muitas tabelas temporárias. Todas as tabelas temporárias foram criadas com:

%pre%

A semântica das tabelas temporárias se encaixa muito bem com o nosso esquema de replicação, e simplificou muito do código que tínhamos que usar para o MySQL, mas parece que a implementação também não foi justa. Da parte da pesquisa que fiz, não acho que as tabelas temporárias fossem realmente destinadas à função para a qual usávamos.

Eu não sou o especialista interno (nem mesmo próximo) sobre esse assunto, apenas um usuário dele, então minha explicação pode não ser 100% precisa, mas acho que é bem próxima.

    
por wolfcastle 03.07.2012 / 22:12

3 respostas

1

A sua configuração do PostgreSQL está muito distante. Isso foi suspeito do seu post inicial,

 Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
 Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
 Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

Com 32 GB no seu servidor, ~ 25 GB é gratuito, excluindo ~ 575 MB de buffer.

Do seu arquivo postgresql.conf,

 shared_buffers = 32MB                   # min 128kB                               
 #temp_buffers = 8MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 #work_mem = 1MB                         # min 64kB
 #maintenance_work_mem = 16MB            # min 1MB
 #max_stack_depth = 2MB   

Estou assumindo que este é um banco de dados dedicado. Se sim, mude para os seguintes parâmetros e recarregue / reinicie,

 shared_buffers = 16GB                   # min 128kB                               
 temp_buffers = 128MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 work_mem = 8MB                         # min 64kB
 maintenance_work_mem = 64MB            # min 1MB
 max_stack_depth = 4MB   

Deixe-me saber como isso altera seu desempenho e pode ajustá-lo conforme necessário.

Em relação a tabelas não lógicas, se suas tabelas temporárias contiverem dados temporários efêmeros e, como você mencionou, forem criados na sessão, é melhor usar tabelas não lidas.

Você pode truncar suas tabelas após a sessão, se isso for aceitável.

Mais informações aqui - link

Não tenho certeza de por que você precisa de tabelas temporárias para replicação. Você não pode usar a replicação de streaming do PostgreSQL?

    
por 13.08.2012 / 10:22
0

O uso de tabelas temporárias e conexões de longa data (provavelmente o pool de conexões está envolvido) pode ser um fardo se o seu servidor não estiver preparado para isso. Um parâmetro do PostgreSQL com o qual você pode tentar brincar é temp_buffers que controla o RAM alocada para tabelas temporárias. Esses buffers temporários são alocados por conexão e o valor padrão (8 MB) provavelmente é muito baixo para o seu site.

Talvez você também precise alterar um pouco o comportamento de seu aplicativo cliente, dependendo de como você usa suas tabelas temporárias. Há uma dúvida semelhante com uma resposta agradável no estouro de pilha .

    
por 03.08.2012 / 21:47
0

Você poderia postar seu arquivo postgresql.conf? Seu postgresql parece estar significativamente otimizado.

Você também pode postar:

  • Se você estiver usando tabelas não registradas para suas tabelas temporárias?

  • Quantos discos e em qual configuração RAID?

por 12.08.2012 / 12:01