0

У меня есть несколько приложений python (отдельные процессы), которые используют Flask-SQLAlchemy для доступа к базе данных sqlite. Один из них настроен с использованием модуля asyncio (но все еще является флеш-приложением), а другой - Flask-RESTful API.Данные SQLAlchemy не согласованы между соединениями

Я вижу проблему, в которой данные, записанные в базу данных API-интерфейса Flask-RESTful, не видны приложению asyncio. Я читал, что это, вероятно, связано с уровнями изоляции (How to disable SQLAlchemy caching?). Если я использую session.expire_all(), проблема исчезнет.

Так ли это из-за уровней изоляции? Я понимаю, что sqlite использует serializable isolation level почти все время (я считаю, что это в моем случае). API REST, который делает запись, совершает транзакции, но код асинхронного кода просто не видит их, если я не позвоню session.expire_all(). Это похоже на проблему изоляции транзакций и больше похоже на проблему SQLAlchemy, но я не уверен на 100%.

Должен ли я всегда помнить, чтобы позвонить session.expire_all() перед тем, как запросить базу данных? Есть ли лучший способ сохранить совместимость между приложениями?

Вот код, если это помогает:

from flask import Flask 
from flask.ext.sqlalchemy import SQLAlchemy 

app = Flask(__name__)  
db = SQLAlchemy(app) 

@asyncio.coroutine 
def grab_data_off_queue(self): 
    while True: 
     try: 
      hit = self.hit_queue.get(False) 

      # required for this session to see the changes made by REST api 
      db.session.expire_all() 

      rows = MyTable.query.filter_by.all() 

      for row in rows: 
       # the REST API is setting field_2 to 123, 
       # but this session cannot see those changes 
       if row.field_2 == 123: 
        do_something() #execution never gets here 

Вот REST API:

from flask import Flask 
from flask.ext.sqlalchemy import SQLAlchemy 

app = Flask(__name__)  
db = SQLAlchemy(app) 

class MyApi(Resource): 
    def put(self, id): 
     row = MyTable.query.filter_by(table_id=id).one() 
     row.field_2 = 123 
     db.session.commit() 
     return '', 204 

ответ

1

SQLAlchemy не не вносить изменения по умолчанию до выходов обработчика, вам необходимо позвонить session.commit() явно.

Но использование синхронного SQLAlchemy кода от async coroutine эффективно убивает производительность даже при относительной умеренной нагрузке вы знаете.

+0

Атрибут REST api вызывает 'session.commit()'. Вы говорите, что даже асинхронный код, который просто запрашивает данные, а не обновляет или вставляет что-либо, также нужно вызвать 'session.commit()'? – d512