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))

2 つの個別のクライアント プロセスで、このコードが実行され、一意の task_id を持つ新しいインスタンスが作成されます。task_id のインスタンスは 1 つだけである必要があります。

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- 次のテーブル 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 に答える