如何防止并发插入创建重复项?

2024-04-20 14:45:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个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))

在两个独立的客户端进程中,运行此代码以创建具有唯一任务标识的新实例;任务标识必须只有一个实例:

^{pr2}$

我如何重写这段代码,使它以原子方式创建具有指定ID的任务?在


Tags: 对象实例代码模型idtruetaskbase
2条回答

你的问题界定不清。你的数据库有一个设计缺陷。不能通过行的自动递增id来定义该行的唯一性。必须有其他字段将其定义为唯一的(例如,task_name+worker),然后通过这些字段创建任务:Task(task_name=smt, worker=smt)-不要手动放置task_id它将自动分配为下一个表id。autoinc主键只用于查找和关系-但是始终放置由其他表组成的唯一键。如果您不能确定哪些字段-那么您的表没有被规范化。在

现在,对于处理重复插入的问题: 会话.刷新()执行先前的工作

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

在代码块周围使用锁。在

# 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

相关问题 更多 >