【发布时间】:2012-05-06 13:00:29
【问题描述】:
我的应用程序正在使用范围会话和 SQLALchemy 的声明式样式。这是一个网络应用程序,许多数据库插入由任务调度程序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()
这里的问题是,因为很多工作是由异步工作人员完成的,所以一个工作可能会在插入 Bike 和 id=123 的过程中完成,而另一个工作可能会检查它的存在。在这种情况下,第二个工作人员将尝试插入具有相同主键的行,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 进行单元测试,并且不想用任何新方法阻碍这种能力)。
干杯!
【问题讨论】:
-
为什么不考虑使用自动增量来生成主键?那么您不必担心这个问题。还是有特定的理由不这样做?
-
有具体原因(对不起,例子有点琐碎)。
标签: python mysql sqlalchemy celery