15

SQLAlchemy 宣言型ベースを使用しており、トランザクション レベルを分離したいメソッドがあります。説明すると、データベースに同時に書き込みを行う 2 つのプロセスがあり、それらのロジックをトランザクションで実行する必要があります。デフォルトのトランザクション分離レベルは READ COMMITTED ですが、SERIALIZABLE 分離レベルを使用してコードを実行できる必要があります。

これは SQLAlchemy を使用してどのように行われますか? 現在、基本的にモデルには、SQLAlchemy の宣言ベースから継承するメソッドがあり、基本的にトランザクションで呼び出す必要があります。

from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
from psycopg2.extensions import ISOLATION_LEVEL_READ_COMMITTED
from psycopg2.extensions import ISOLATION_LEVEL_SERIALIZABLE

class OurClass(SQLAlchemyBaseModel):

    @classmethod
    def set_isolation_level(cls, level=ISOLATION_LEVEL_SERIALIZABLE):
        cls.get_engine().connect().connection.set_isolation_level(level)

    @classmethod
    def find_or_create(cls, **kwargs):
        try:
            return cls.query().filter_by(**kwargs).one()
        except NoResultFound:
            x = cls(**kwargs)
            x.save()
            return x

トランザクション分離レベルを使用してこれを呼び出すためにこれを行っていますが、期待どおりの動作をしていません。分離レベルは、postgres ログに表示される内容からまだ READ COMMITTED です。誰かが私が間違っていることを特定するのを助けることができますか?

SQLAlchemy 0.5.5 を使用しています

class Foo(OurClass):

    def insert_this(self, kwarg1=value1):
        # I am trying to set the isolation level to SERIALIZABLE
        try:
            self.set_isolation_level()
            with Session.begin():
                self.find_or_create(kwarg1=value1)
        except Exception:  # if any exception is thrown...
            print "I caught an expection."
            print sys.exc_info()
        finally:
            # Make the isolation level back to READ COMMITTED
            self.set_isolation_level(ISOLATION_LEVEL_READ_COMMITTED)
4

2 に答える 2

13

SQLAlchemyのメンテナーであるMichaelBayerから:

分離レベルに関して最近修正されたpsycopg2固有のバグがあったため 、 create_engine()に「isolation_level」引数を 使用し、 0.6.4がリリースされるまでSQLAlchemyの最新のヒントを使用してください。

以下のアプローチは、後でクエリに使用される同じ接続には影響しません。代わりに、作成時にすべての接続にset_isolation_levelを設定するPoolListenerを使用します。

于 2010-08-25T21:16:28.780 に答える
-3

分離レベルはトランザクション内で設定されます。例:

try:
    Session.begin()
    Session.execute('set transaction isolation level serializable')
    self.find_or_create(kwarg1=value1)
except:
    ...

PostgreSQLドキュメントから:

SET TRANSACTIONが事前のSTARTTRANSACTIONまたはBEGINなしで実行された場合、トランザクションはすぐに終了するため、効果がないように見えます。

于 2010-08-22T01:43:48.240 に答える