SQLAlchemy – объект не помечен как истек

У меня есть многопоточный инструмент python3 для управления другими процессами. Я использую записи в базе данных, чтобы отметить, что этот процесс сейчас занят.

class Process(base): id = Column('ID', Integer, primary_key=True) name = Column('NAME', String(128)) tasks = relationship('ProcessTask', back_populates="process", cascade="all, delete-orphan", passive_deletes=True) """ :type: list[ProcessTask] """ class ProcessTask(base): id = Column('ID', Integer, primary_key=True) process_id = Column('PROCESS_ID', Integer, ForeignKey('PROCESS.ID', ondelete='CASCADE', onupdate='CASCADE'), nullable=False) status = Column('STATUS', String(128), nullable=False) process = relationship(Process, back_populates="tasks") """ :type: Process """ 

Например, задачи имеют только два возможных состояния – «запуск» и «завершение»,

Я столкнулся с проблемой:

  • thread1 создает задачу для процесса
  • thread2 проверяет наличие этого процесса. Процесс занят. thread2 sleep пока задача не будет отмечена как завершенная
  • thread1 отмечает задачу как завершенную
  • thread2 не «видит» изменения объекта ProcessTask и не спит навсегда

Я попытался пометить объект ProcessTask как истекший через session.expire(entity) в thread2 – не работает.

Что я делаю не так?


Это код, который я использую для создания фабрики сеансов:

 connString = "mysql+mysqlconnector://{userName}:{userPass}@{host}:{port}/{dbName}".format(...) self._db_engine = sqlalchemy.create_engine(connString, pool_size=100, pool_recycle=3600) self._db_session_factory = sqlalchemy.orm.sessionmaker(bind=self.getEngine()) self._db_session = sqlalchemy.orm.scoped_session(self._db_session_factory) 

Каждый поток создает свой собственный сеанс self._db_session()

Причиной отказа был уровень изоляции транзакций MySQL.

Уровень изоляции по умолчанию для транзакций MySQL – это REPEATABLE READ . Сначала операция чтения внутри транзакции MySQL создает моментальный снимок базы данных и во время транзакции, которую вы читаете из этого моментального снимка. Таким образом, вы не можете читать изменения, сделанные другими потоками, до завершения транзакции.

Чтобы исправить это поведение, мне пришлось установить уровень изоляции для READ COMMITTED

https://dev.mysql.com/doc/refman/5.0/en/set-transaction.html

http://docs.sqlalchemy.org/en/rel_1_0/orm/session_transaction.html#setting-transaction-isolation-levels