usando o PostgreSQL 9.1.2
Estou vendo uso excessivo da CPU e grandes quantidades de gravações no disco a partir de tarefas do postmaster. Isso acontece mesmo enquanto meu aplicativo não faz quase nada (10s de inserções por MINUTE). No entanto, há um número razoável de conexões abertas.
Eu tenho tentado determinar o que no meu aplicativo está causando isso. Sou bem novato no postgresql e ainda não cheguei a lugar algum. Ativei algumas opções de log no meu arquivo de configuração e observei as conexões na tabela pg_stat_activity, mas todas estão ociosas. No entanto, cada conexão consome ~ 50% da CPU e grava ~ 15M / s no disco (não está lendo nada).
Basicamente, estou usando o postgresql.conf com muito poucos ajustes. Agradeço qualquer conselho ou dicas sobre o que posso fazer para rastrear isso.
Aqui está uma amostra do que 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 : Muitas das gravações de arquivos parecem estar em 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 é o OID da tabela. No entanto, existem vários arquivos nomeados tnn_nnnnnnn
e são esses arquivos que parecem ser gravados (talvez sobrescritos) constantemente. Para que são esses arquivos? 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
Atualização : A execução do rastreio nos processos do postmaster mostra basicamente muitas 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, "\0\0\0\0\0\0\0\0\1\0\0\0000\0\360\37\360\37\4 \0\0\0\0b1\5\0\2\0\0\0"..., 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
Atualização : Portanto, esse problema parece ter tudo a ver com tabelas temporárias. Alteramos nossa configuração para que as tabelas temporárias sejam tabelas 'regulares', e toda a atividade do disco tenha desaparecido, e o desempenho esteja de volta ao que eu esperava. Agora, essa alteração foi apenas um teste rápido e sujo: se realmente vamos mudar para usar tabelas regulares, temos problemas com simultaneidade e limpeza. As mesas temporárias são realmente tão más ou estamos abusando delas?
Atualização : Um pouco mais de experiência. Estou usando um middleware de replicação baseado em instruções desenvolvido internamente . É bastante maduro e tem sido usado em vários projetos ao longo de vários anos, mas usando o MySQL. Trabalhamos apenas com o PostgreSQL nos últimos dois anos. Basicamente, estávamos 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 10 a 20 conexões (de longa duração) e ~ 50 tabelas, isso pode resultar em muitas tabelas temporárias. Todas as tabelas temporárias foram criadas com:
CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;
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 no MySQL, mas parece que a implementação não foi boa também. Com base nas pesquisas que fiz, não acho que tabelas temporárias foram realmente destinadas à função para a qual as usamos.
Eu não sou o especialista interno (nem de perto) sobre esse assunto, apenas um usuário, por isso minha explicação pode não ser 100% precisa, mas acho que é bem próxima.