Mi aplicación está utilizando una sesión de ámbito y el estilo declarativo de SQLALchemy. Es una aplicación web y muchas de las inserciones de DB se ejecutan en Celery
, un programador de tareas.Tratar con claves primarias duplicadas en la inserción en SQLAlchemy (estilo declarativo)
Por lo general, cuando se decide insertar un objeto, el código podría hacer algo a lo largo de las siguientes líneas:
from schema import Session
from schema.models import Bike
pk = 123 # primary key
bike = Session.query(Bike).filter_by(bike_id=pk).first()
if not bike: # no bike in DB
new_bike = Bike(pk, "shiny", "bike")
Session.add(new_bike)
Session.commit()
El problema aquí es que debido a que mucho de esto se lleva a cabo por los trabajadores asíncronos, es posible que una trabajando para estar a la mitad, insertando un Bike
con id=123
, mientras que otro está comprobando su existencia. En este caso, el segundo trabajador intentará insertar una fila con la misma clave principal, y SQLAlchemy generará un IntegrityError
.
no puedo por la vida de mí encontrar una buena manera de hacer frente a este problema, aparte de el canje de Session.commit()
para:
'''schema/__init__.py'''
from sqlalchemy.orm import scoped_session, sessionmaker
Session = scoped_session(sessionmaker())
def commit(ignore=False):
try:
Session.commit()
except IntegrityError as e:
reason = e.message
logger.warning(reason)
if not ignore:
raise e
if "Duplicate entry" in reason:
logger.info("%s already in table." % e.params[0])
Session.rollback()
Y entonces todas partes tengo Session.commit
ahora tengo schema.commit(ignore=True)
donde I don' Me importa que la fila no se inserte de nuevo.
Para mí esto parece muy frágil debido a la comprobación de cadena. Así como un FYI, cuando se produce un IntegrityError
se ve así:
(IntegrityError) (1062, "Duplicate entry '123' for key 'PRIMARY'")
Así que por supuesto es la clave principal que estaba insertando fue algo así como Duplicate entry is a cool thing
entonces yo supongo que podría perderse IntegrityError
's que no eran en realidad debido a las claves primarias duplicadas.
¿Hay enfoques mejores, que mantienen el enfoque SQLAlchemy limpia que estoy usando (en lugar de empezar a escribir declaraciones en las cadenas etc...)
Db es MySQL (aunque para las pruebas unitarias me gusta para usar SQLite, y no quisiera obstaculizar esa capacidad con nuevos enfoques).
¡Salud!
¿por qué no se tiene en cuenta el uso de incremento automático para la generación de las claves principales que? entonces no tienes que preocuparte por este problema. ¿O hay alguna razón específica para no hacer eso? – mata
Hay una razón específica (lo siento, el ejemplo es un poco trivial). – Edwardr