2010-11-26 6 views
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で新しいインスタンスを作成するために実行されています。それはアトミックに指定されたIDを持つタスクを作成するようにどのように私はこのコードを書き換えることができ

task = session.query(Task).filter(Task.task_id == task_id).first() 
if not task: 
    task = Task(task_id) 
    session.add(task) 
    session.flush() 

:TASK_IDのインスタンスは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 
+0

を実行し、私はそれよりも実用的なものを好みます。 1つ、ロック何? –

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 
+0

ええ、DBに制約を追加するのは間違いなく正しい方法です。 'task_id = sa.Column(sa.String(255)、unique = True、index = True)' –

+0

@ THC4k: 'unique = True 'は、ユニークであると宣言されている必要があります。 'はユニークなインデックスを作成するため、' index = True'は冗長です。 –

関連する問題