0

私は次のことをしようとしています:

  • テーブルAには、一意の番号で構成される列が1つだけあります(連続していない)
  • テーブルBには、id(一意の非連続整数)とhit_number(正の整数)の2つの列があります。

番号とIDを指定して、次のことを行います。

番号が表Aにあるかどうかを確認します。

  • それが存在する場合は、何もしないでください。私に知らせてください
  • 存在しない場合は、テーブルAに挿入し、このIDに対応するテーブルBのhit_number列をインクリメントして、お知らせください。

これは単一のトランザクションで実行する必要があり、同じ値で2つの同時接続を行う場合は、hit_numberを1つだけ増やす必要があります(したがって、ある程度の分離が必要だと思います)。

私は1つの解決策を思いつきました(この例ではsqliteとpythonを使用しています)が、それが十分に良いかどうかはわかりません:

何かのようなもの

con = sqlite3.connect(":memory:", isolation_level="EXCLUSIVE")
con.execute("create table A (num integer primary key);")
con.execute("create table B (user_id integer primary key, hit_number integer);")

# ... fill it with something

def hit(v, id, con):
    try:
        with con:
           con.execute("INSERT INTO A VALUES (?);" +
                       "UPDATE B SET hit_number=hit_number+1 WHERE user_id=(?);", (v, id))
    except sqlite3.IntegrityError:
       return False
    return True

このトランザクションはアトミックですか?ここで実際にEXCLUSIVEが必要ですか、それとも分離レベルを低くするとまったく同じ動作になりますか?もっと良い方法はありますか?

4

1 に答える 1

4

このメソッドでは、一度に1つのステートメントのみを実行してください.execute()。トランザクション内では、そのような1回の呼び出しで2つのステートメントを実行する必要はありません。整合性エラーの例外は、すでにトランザクションを発生させて中止します。

try:
    with con:
       con.execute("INSERT INTO A VALUES (?);", (v,))
       con.execute("UPDATE B SET hit_number=hit_number+1 WHERE user_id=(?);", (id,)
except sqlite3.IntegrityError:
   return False
return True
于 2013-03-25T21:02:43.500 に答える