我有一个SQLAlchemy模型对象,如下所示:
ResultModelBase = declarative_base()
class Task(ResultModelBase):
"""Task result/status."""
id = sa.Column(sa.Integer, sa.Sequence("task_id_sequence"),
primary_key=True,
autoincrement=True)
task_id = sa.Column(sa.String(255))
在两个单独的客户端进程中,正在运行此代码以创建具有唯一task_id的新实例;必须只有一个task_id实例:
task = session.query(Task).filter(Task.task_id == task_id).first()
if not task:
task = Task(task_id)
session.add(task)
session.flush()
如何重写此代码,以便它以原子方式创建具有指定ID的任务?
答案 0 :(得分:2)
你的问题不明确。您的数据库中存在设计缺陷。您无法通过其自动递增ID定义行的唯一性。您必须有其他字段将其定义为唯一(例如task_name + worker),然后按以下字段创建任务:Task(task_name=smt, worker=smt)
- 不要手动放置task_id
- 它将被指定为下一个表-id自动。仅将autoinc主键用于查找和关系 - 但始终放置由其他表组成的唯一键。如果你无法确定哪些字段 - 而不是你的表没有规范化。
现在,针对处理重复项插入的问题: session.flush()#执行上一个工作
session.flush()
try:
t = Task(task_name=smt, worker=smt)
session.add()
session.flush()
except sqlalchemy.exc.IntegrityError:
# task already exists
else:
# task added to db
答案 1 :(得分:0)
在代码块周围使用锁。
# lock here
task = session.query(Task).filter(Task.task_id == task_id).first()
if not task:
task = Task(task_id)
session.add(task)
session.flush()
# unlock here