Как установить уровень изоляции транзакции в SQLAlchemy для PostgreSQL?

Мы ' Я использую декларативную базу SQLAlchemy, и у меня есть метод, для которого я хочу изолировать уровень транзакции. Чтобы объяснить, есть два процесса, одновременно пишущие в базу данных, и я должен заставить их выполнить свою логику в транзакции. Уровень изоляции транзакции по умолчанию - 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

Я делаю это для вызова этого с использованием уровня изоляции транзакции, но он не делает то, что я ожидаю , Уровень изоляции все еще READ COMMITTED из того, что я вижу в журналах postgres. Может ли кто-нибудь помочь определить, что я делаю неправильно?

I ' используя 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)
10
задан Mahmoud Abdelkader 19 August 2010 в 05:05
поделиться

2 ответа

От Майкла Байера, сопровождающего SQLAlchemy:

Используйте «isolation_level» аргумент для create_engine() и используйте последний совет SQLAlchemy пока не выйдет 0.6.4, как было недавно исправлена ​​ошибка, связанная с psycopg2 относительно уровня изоляции.

Приведенный ниже подход не влияют на то же соединение, которое позже используется для запросов - вы бы вместо этого используйте PoolListener, который устанавливает установить set_isolation_level на всех соединения по мере их создания.

10
ответ дан 4 December 2019 в 02:24
поделиться

Уровень изоляции устанавливается внутри транзакции, например

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

Из документа PostgreSQL :

Если SET TRANSACTION выполняется без предварительного START TRANSACTION или BEGIN, это не будет иметь никакого эффекта, поскольку транзакция будет немедленно завершена.

-2
ответ дан 4 December 2019 в 02:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: