我的应用程序正在使用范围会话和SQLALchemy的声明式风格。它是一个web应用程序,许多DB插入都是由任务调度程序Celery执行的。
通常,当决定插入一个对象时,我的代码可能会沿着以下几行执行操作: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()
这里的问题是,因为很多工作都是由异步工作人员完成的,所以一个工作人员可能在插入带有id=123的Bike的过程中完成了一半,而另一个工作人员正在检查它的存在性。在这种情况下,第二个worker将尝试插入具有相同主键的行,SQLAlchemy将引发一个IntegrityError。
我一辈子都找不到解决这个问题的好办法,除了把Session.commit()换成:'''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()
然后在任何地方我都有Session.commit我现在有schema.commit(ignore=True)我不介意行不再被插入。
在我看来,这似乎很脆弱,因为字符串检查。正如仅供参考,当IntegrityError升高时,它看起来是这样的:(IntegrityError) (1062, "Duplicate entry '123' for key 'PRIMARY'")
当然,我插入的主键是Duplicate entry is a cool thing,我想我可能会漏掉IntegrityError,这并不是因为主键重复。
有没有更好的方法可以保持我使用的干净的SQLAlchemy方法(而不是开始用字符串写出语句等等…)
Db是MySQL(尽管对于单元测试,我喜欢使用SQLite,并且不想用任何新方法阻碍这种能力)。
干杯!
博客围绕使用范围会话和SQLAlchemy声明式风格的Web应用展开。因异步工作,插入数据时会出现主键重复,引发IntegrityError。当前解决办法是替换commit方法,但依赖字符串检查较脆弱。作者寻求更好方法,数据库为MySQL,单元测试用SQLite。
1万+

被折叠的 条评论
为什么被折叠?



