Recientemente, mi aplicación Django se ha bloqueado con frecuencia debido a errores de conexión a la base de datos:
OperationalError: FATAL: sorry, too many clients already Cuando entro en la base de datos de la aplicación, veo que, de hecho, hay casi 100 conexiones abiertas, todas con la misma consulta (ejecutada por Django ORM) y todas en estado idle .
He estado haciendo manualmente SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle'; pero estoy perplejo en cuanto a por qué sucede esto. ¿Alguien puede arrojar alguna idea de lo que está sucediendo aquí?
La configuración de mi base de datos Django no se desvía de los valores predeterminados (no he definido CONN_MAX_AGE ni nada por el estilo).
Que podria causar esto? No estoy haciendo consultas avanzadas de Django. ¿Es esto algo que se puede resolver con una configuración de Django o tal vez alguna configuración de PostgreSQL? Cualquier consejo es apreciado.
aparentemente no te desconectas. Usar db.close_connection() después de que finalice la consulta ayudaría. Además, si lo hago bien, CONN_MAX_AGE a un valor corto podría ayudar. Y considere usar algún agrupador de sesiones, por ejemplo, pgbouncer para conexiones django. De esta manera, si tiene demasiadas conexiones, esperará (o reutilizará las anteriores, según la configuración) en lugar de cancelar la ejecución con un error...
actualización : explicación por qué lo propongo
cada subproceso mantiene su propia conexión, su base de datos debe admitir al menos tantas conexiones simultáneas como subprocesos de trabajo tenga.
Entonces, si tiene más subprocesos que postgres max_connections , obtendrá un error mencionado. Cada subproceso puede reutilizar la conexión si CONN_MAX_AGE no ha pasado. Su configuración es 0, por lo que la conexión debe cerrarse después de completar la consulta, pero verá 100 conexiones inactivas. Por eso no cierran. La gran cantidad de conexiones significa que tampoco se reutilizan (lógica: si tuviera 100 consultas paralelas, no todas estarían inactivas, y si tiene tantas, no se reutilizarán, abriendo nuevas). Así que creo que Django no los cierra como se prometió, por lo que CONN_MAX_AGE establecido en 0 no funciona en su código. Así que propongo usar db.close_connection() para forzar la desconexión y establecer CONN_MAX_AGE en un valor pequeño puede cambiar el comportamiento.
Mejor conjetura sin más detalles, pero si es la misma consulta, y todos están inactivos, se siente como si estuviera haciendo algún tipo de programación asincrónica, y ha llegado a un punto muerto, y específicamente su punto muerto se manifiesta en db las conexiones se saturan.
Si no ha definido CONN_MAX_AGE y no está utilizando ningún agrupador de terceros, entonces esto debe ser un problema en algún lugar de su código o en una biblioteca que está utilizando. Django por defecto abre y cierra la conexión db por solicitud. Y el hecho de que vea conexiones inactivas en pg_stat_activity no significa que haya un interbloqueo, sino que algo abrió estas conexiones y no las cerró.
Primero me aseguraría de que estas conexiones realmente provengan de Django, por ejemplo, reiniciando la aplicación y viendo cómo afecta a pg_stat_activity . Si lo confirma, verifique si no está mezclando ningún código asincrónico o de multiprocesamiento que deje hilos/procesos colgando.