usando PostgreSQL 9.1.2
Veo un uso excesivo de la CPU y grandes cantidades de escrituras en el disco desde las tareas de postmaster. Esto sucede incluso mientras mi aplicación no está haciendo casi nada (10s de inserciones por MINUTO). Sin embargo, hay un número razonable de conexiones abiertas.
He estado tratando de determinar qué está causando esto en mi aplicación. Soy bastante nuevo con postgresql, y hasta ahora no he llegado a ningún lado. Encendí algunas opciones de registro en mi archivo de configuración y miré las conexiones en la tabla pg_stat_activity, pero todas están inactivas. Sin embargo, cada conexión consume ~ 50% de CPU y escribe ~ 15M / s en el disco (sin leer nada).
Básicamente estoy usando el stock postgresql.conf con muy pocos ajustes. Agradecería cualquier consejo o sugerencia sobre lo que puedo hacer para rastrear esto.
Aquí hay una muestra de lo que me muestra top / iotop:
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
Actualización : Gran parte de la escritura del archivo parece estar en algunos archivos temporales (?) En el directorio $ PG_DATA / base /. Comprendo la estructura del archivo aquí es que cada tabla se almacena básicamente como un archivo cuyo nombre es el OID de la tabla. Sin embargo, hay toneladas de archivos nombrados tnn_nnnnnnn
, y son estos archivos los que parecen estar escritos (quizás reescritos) constantemente. ¿Para qué son estos archivos? Hay ~ 4700 de los archivos, y todos tienen un tamaño de 8K:
-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
Actualización : ejecutar strace en los procesos de postmaster básicamente muestra muchas cosas de E / S de archivos:
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
Actualización : por lo tanto, este problema parece tener que ver con tablas temporales. Cambiamos nuestra configuración para que las tablas temporales sean tablas 'regulares', y toda la actividad del disco desapareció, y el rendimiento volvió a donde esperaba que estuviera. Ahora, este cambio fue solo una prueba rápida y sucia: si realmente vamos a cambiar para usar tablas regulares, tenemos problemas con la concurrencia y la limpieza. ¿Las tablas temporales son realmente tan malvadas o las estamos abusando?
Actualización : un poco más de fondo. Estoy utilizando un middleware de replicación basado en sentencias desarrollado internamente . Es bastante maduro y ha estado en uso en varios proyectos durante varios años, pero usando MySQL. Solo hemos estado trabajando con PostgreSQL durante el último año o dos. Esencialmente estábamos usando las tablas temporales como parte del mecanismo de replicación. Cada vez que se establece una nueva conexión, creamos una tabla temporal para cada tabla en la base de datos. Con 10-20 conexiones (de larga duración) y ~ 50 tablas, esto puede equivaler a muchas tablas temporales. Todas las tablas temporales se crearon con:
CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;
La semántica de las tablas temporales encaja muy bien con nuestro esquema de replicación, y simplificó mucho el código que tuvimos que usar para MySQL, pero parece que la implementación no fue tan buena. Por el poco de investigación que he hecho, no creo que las tablas temporales estén realmente destinadas a la función para la que las estábamos usando.
No soy el experto interno (ni siquiera cercano) en este tema, solo un usuario del mismo, por lo que mi explicación puede no ser 100% precisa, pero creo que está bastante cerca.
fuente
Respuestas:
Su configuración de PostgreSQL está muy lejos. Esto fue sospechoso por tu publicación inicial,
De 32 GB en su servidor, ~ 25 GB son gratuitos, excluyendo ~ 575 MB de búfer.
Desde su archivo postgresql.conf,
Supongo que esta es una base de datos dedicada. Si es así, cámbielo a los siguientes parámetros y vuelva a cargar / reiniciar,
Hágame saber cómo esto cambia su rendimiento y puede ajustarlo aún más según sea necesario.
Con respecto a las tablas no registradas, si sus tablas temporales contienen datos temporales que son efímeros y, como mencionó, se crean en la sesión, es mejor usar tablas no registradas.
Puede truncar sus tablas después de la sesión si eso es aceptable.
Más información aquí: http://michael.otacoo.com/postgresql-2/unlogged-table-performance-in-postgresql-9-1/
No estoy seguro de por qué necesita tablas temporales para la replicación. ¿No puedes usar la replicación de transmisión PostgreSQL?
fuente
Usar tablas temporales y tener conexiones de larga data (probablemente la agrupación de conexiones está involucrada) puede ser una carga si su servidor no está preparado para ello. Un parámetro de PostgreSQL con el que puede intentar jugar es el
temp_buffers
que controla la RAM asignada a las tablas temporales. Esos búferes temporales se asignan por conexión y el valor predeterminado (8 MB) es probablemente demasiado bajo para su sitio.Tal vez también necesite cambiar un poco el comportamiento de su aplicación cliente, dependiendo de cómo use sus tablas temporales. Hay una pregunta similar con una buena respuesta en Stack Overflow .
fuente
temp_buffers
. ¿También puede decirnos cuál es el tamaño de la base de datos que está tratando de replicar? ¿Cuántas tablas, tamaño medio por tabla y tamaño total de la base de datos?¿Podría publicar su archivo postgresql.conf? Su postgresql parece estar significativamente menos optimizado.
¿Podrías también publicar:
Si está utilizando tablas no registradas para sus tablas temporales?
¿Cuántos discos y en qué configuración RAID?
fuente