2011-11-20 11 views
10

Estoy ejecutando Django 1.3 con PostgreSQL 9.1/PostGIS 1.5, psycopg2 2.4.2 y pgbouncer 1.4.2.pgbouncer - cierre porque: servidor sucio en cada conexión

En cada conexión a la base de datos consigo una entrada de registro en pgbouncer.log:

2011-11-20 02: 15: 25.027 29.538 REGISTRO DE S-0x96c2200: app_db/[email protected] : 5432 cierre porque: servidor sucio (edad = 0).

No encuentro ninguna solución a este problema. ¿Alguien tiene una idea de por qué? He intentado reconfigurar pgbouncer (modo de sesión/transacción, diferentes tiempos de espera, etc.), pero fue en vano.

Respuesta

15

Ok, creo que lo he descubierto. El problema radica en un problema de larga data con Django y Psycopg2. Básicamente, Psycopg2 emitirá automáticamente una instrucción BEGIN en el DB. Sin embargo, si Django cree que no se ha producido ninguna modificación de datos, no emitirá un COMPROMISO al final de una transacción.

Existen algunas soluciones a este problema, consulte http://www.slideshare.net/OReillyOSCON/unbreaking-your-django-application para obtener más información. Lo ideal es desactivar las confirmaciones automáticas (configurando autocommit = True en la configuración de su base de datos, convención de nomenclatura incómoda). Esto evita transacciones en funciones de solo lectura, pero también en funciones de escritura, por lo que debe ajustar manualmente esas funciones en un decorador @commit_on_success.

Como alternativa, solo agregue el django.middleware.transaction.TransactionMiddleware a sus clases de Middleware. Esto ajustará todas las solicitudes en una transacción. Esto significa también que envuelve innecesariamente las solicitudes de solo lectura en una transacción, pero es una solución rápida y sucia.

+0

Ok, acabo de enterarme por el camino difícil, ADVERTENCIA: no haga esto solo si usa apio (u otra cosa) para el procesamiento de tareas en segundo plano. Es probable que existan condiciones de carrera en las que pase la clave principal de un objeto a una tarea que se ejecute de forma asíncrona. La tarea puede comenzar a ejecutarse antes de que la solicitud finalice (y la transacción se haya comprometido), por lo que la tarea no puede encontrar el objeto. Creo que la única solución para esto es la gestión manual de transacciones. – Dick

+1

Solo una nota para agradecerle por vincular mi presentación ... ¡Me alegro de que haya sido útil! :) – Christophe

+0

¡Por supuesto! Fue una gran presentación; Me parece sorprendente que se sepa muy poco sobre la gestión de transacciones 'interrumpida' en Django. – Dick

Cuestiones relacionadas