into merge 主键重复_在SQLAlchemy(声明式样式)中处理插入时的重复主键

博客围绕使用范围会话和SQLAlchemy声明式风格的Web应用展开。因异步工作,插入数据时会出现主键重复,引发IntegrityError。当前解决办法是替换commit方法,但依赖字符串检查较脆弱。作者寻求更好方法,数据库为MySQL,单元测试用SQLite。

我的应用程序正在使用范围会话和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,并且不想用任何新方法阻碍这种能力)。

干杯!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值