2011-08-22 31 views
13

Estoy usando MySQL con el motor InnoDB y el nivel de aislamiento REPEATABLE-READ.¿Es esta una forma segura de incrementar y obtener el valor de un contador en Django?

He escrito una función que creo que debería incrementar atómicamente un IntegerField, y darme el valor después del incremento. Me gustaría obtener opiniones sobre si mi código es robusto frente a problemas de concurrencia.

Mi código es el siguiente:

class MyModel(models.Model): 
    version = models.IntegerField() 

    @staticmethod 
    @transaction.commit_on_success 
    def acquire_version(pk): 
    MyModel.objects.filter(pk = pk).update(version = F('version') + 1) 
    return MyModel.objects.get(pk = pk).version 

Mi pensamiento es que en dos llamadas simultáneas, las actualizaciones mutuamente se excluyen entre sí debido a un bloqueo de escritura, y luego REPETIBLE-LEER deben garantizar que mi posterior. get me dará el valor después de la ACTUALIZACIÓN. ¿Estoy en lo cierto?

(Esto no es un general "cómo hago un incremento atómica?" Pregunta, ya hay uno de ellos. Esto es acerca de si ésta manera particular es válido.)

+0

¿Has mirado en http://stdbrouw.github.com/django-locking/ - Asumo que usted está haciendo esto para el bloqueo optimista – dstarh

+0

relacionados http://stackoverflow.com/questions/1598932/atomic-increment-of-a-counter-in-django –

Respuesta

1

Una regla general-de- thumb es any sort of custom queries or customized query behavior should go into manager methods. Esto tiene sentido en su caso, porque puede incrementar, guardar y devolver el número de versión en un nivel muy bajo: durante la consulta real.

Por lo tanto, utilizar un gestor (object = MyManager()) y escribir una consulta SQL que se incrementa el número de versión (UPDATE mytable SET version=(version+1) WHERE pk=pk, ver here), e inmediatamente devolver la versión incrementada de la instancia de modelo, antes de cualquier otra llamada puede ser ejecutado.

Ver también Managers

+0

Bien, pero ¿el código que se da en la pregunta es correcto o está defectuoso? – kdt

+0

Creo que es más peligroso porque la implementación real de .update() puede ser independiente de la versión de Django. También estás haciendo una búsqueda doble y probablemente incluso tres veces doble. Honestamente, no sé si es (actualmente) correcto. – Remi

Cuestiones relacionadas