2011-08-11 15 views
6

Configuración:Fuerza Django para cometer

  • script Python A inserta datos a una base de datos cada 15 minutos
  • Python guión B consultas de algunas de las últimas entradas de la base de datos cada pocos minutos

Ambos usan ORM de django, se ejecutan en la misma máquina y usan una base de datos MySQL local.

El problema:
B obtiene entradas, a excepción de la última, a pesar de que Un la guarda minutos antes.

sospechaba que Un no se cierra la transacción, por lo tanto B ve la base de datos sin la última entrada. De hecho, al examinar los registros de MySQL, me di cuenta de la commit para cada INSERT sucede justo antes de la próxima INSERT.

A pesar de que se supone que debe ser redundante, añadí @commit_on_success decorador a la Una función que incluye el save(), pero no sirvió de nada.

¿Cómo puedo forzar Django (o MySQL ?!) para cometer justo después de la save()?

ACTUALIZACIÓN:
descubrí que la compromete DO pasar - Yo era errónea creer que no lo hacen porque MySQL's General Query Log only has 1 sec resolution.
A la luz de esta y otra información nueva, he hecho la pregunta here.

Respuesta

9

Usted puede utilizar el decorador commit_manually y llamarlo siempre que lo desee.

Directamente desde el documentation:

from django.db import transaction 

@transaction.commit_manually 
def viewfunc(request): 
    ... 
    # You can commit/rollback however and whenever you want 
    transaction.commit() 
    ... 

    # But you've got to remember to do it yourself! 
    try: 
     ... 
    except: 
     transaction.rollback() 
    else: 
     transaction.commit() 

Esto responde a la pregunta que le solicitará , aunque me pregunto si podría haber algo más en el trabajo.

+0

¿Cómo sería eso diferente de '@ commit_on_success'? (cambiar a la confirmación manual dañará nuestro tiempo de actividad, así que me gustaría entender mejor por adelantado antes de atemperar el sistema) – Jonathan

+0

'commit_on_success' solo ejecuta la confirmación después de que la función envuelta retorna; si está inactivo sin regresar, no será de ayuda. 'commit_manually' te permite invocar la confirmación justo después del último guardado. No estoy seguro de lo que está haciendo tu código, así que eso es todo lo que puedo pensar en este momento. – eric

+0

Aunque descubrí que mi problema estaba en otra parte, creo que su respuesta es significativa para aquellos que buscan forzar django commits, por lo tanto, la marqué como la respuesta correcta – Jonathan

0

El problema es causado por que MySQL por defecto tiene un nivel de aislamiento-Lectura repetible. Eso significa que se espera que la misma consulta devuelva los mismos valores. Los cambios no volverán. Puede hacer dos cosas aquí:

  1. Establezca el nivel de aislamiento de transacción como READ-COMPROMETIDO en la configuración. Como se explica here.
  2. Fuerza de una confirmación, por lo tanto cerrar la transacción en el guión B, así como se inicia una nueva transacción, podrás ver todos los cambios antes de que esta nueva transacción.Model.objects.update() hace el truco