2

我有一个如下所示的 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 的任务?

4

2 回答 2

2

你的问题定义不明确。您的数据库存在设计缺陷。您不能通过其自动递增的 id 来定义行的唯一性。您必须有其他将其定义为唯一的字段(例如 task_name+worker),然后通过这些字段创建任务:Task(task_name=smt, worker=smt)- 不要task_id手动放置 - 它将自动分配为下一个 table-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
于 2010-11-27T00:48:30.040 回答
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
于 2010-11-26T21:18:03.417 回答