1

重複したユーザーを別のテーブルに記録することにより、挿入での主キー違反の後に回復しようとしています。ただし、私のコードではエラーが発生しますInvalidRequestError: This transaction is inactive

残念ながら、トレースバックは、エラーが発生したこの関数内の特定の行を示していません。これは、この関数を呼び出している関数と同じくらい深くなるだけです (これは奇妙です)。

私の try/except begin/rollback/commit パターンは正しいですか?

def convert_email(db, user_id, response):
    """Map a submitted email address to a user, if the user
    does not yet have an email address.
    """
    email = response['text_response']
    trans = db.begin()
    try:
        update_stmt = users_tbl.update(
                and_(users_tbl.c.user_id==user_id,
                     users_tbl.c.email==None))
        db.execute(update_stmt.values(dict(email=email)))
        trans.commit()
    except sqlalchemy.exc.IntegrityError as e:
        trans.rollback()
        if e.orig.pgcode == UNIQUE_VIOLATION:
            trans = db.begin()
            try:
                user = db.execute(users_tbl.select(users_tbl.c.email==email))
                parent_user_id = user.first()['user_id']

                insert_stmt = duplicate_public_users_tbl.insert().values(
                        user_id=user_id,
                        parent_id=parent_user_id)
                db.execute(insert_stmt)
                trans.commit()
            except sqlalchemy.exc.IntegrityError as e:
                trans.rollback()
                if e.orig.pgcode != UNIQUE_VIOLATION:
                    raise
4

1 に答える 1

1

呼び出し元の関数によって例外が生成され、それ自体がトランザクションにラップされていました。

with engine.begin() as db:
    convert_email(db, user_id, response)

内部rollback()呼び出しは、外部トランザクションも終了する必要があります。これは、のドキュメントで示唆されていますTransaction.close()

... これは、含まれているトランザクションのスコープに影響を与えずにトランザクションをキャンセルするために使用されます。

于 2013-03-21T20:08:41.983 に答える