Подтвердить что ты не робот

Как отключить кеширование SQLAlchemy?

Я встречаю проблему с кешем, когда использую sqlalchemy. Я использую sqlalchemy вставить данные в базу данных mysql. У меня есть другой процесс приложения этих данных, а затем обновлять эти данные напрямую. Но мой sqlalchemy всегда получал старые данные, а не обновленные данные. Я думаю, sqlalchemy кэшировал мой запрос.. так.. Как отключить его?

4b9b3361

Ответ 1

Обычная причина, по которой люди думают, что в игре есть "кеш", помимо обычной карты идентификации SQLAlchemy, которая является локальной транзакцией, заключается в том, что они наблюдают эффекты изоляции транзакций. Сеанс SQLAlchemy работает по умолчанию в транзакционном режиме, то есть он ждет, пока не будет вызываться session.commit(), чтобы сохранить данные в базе данных. В течение этого времени другие транзакции, происходящие в других местах, не будут видеть эти данные.

Однако из-за изолированного характера транзакций есть дополнительный поворот. Те другие транзакции не будут отображаться не только ваши транзакционные данные до тех пор, пока они не будут зафиксированы, они также не смогут увидеть их в некоторых случаях до тех пор, пока они не будут совершены или не откатны (что является тем же эффектом, что и у вашего закрытия(), Транзакция со средней степенью изоляции будет удерживаться в состоянии, которое она загрузила до сих пор, и продолжает предоставлять вам то же самое состояние, локальное для транзакции, даже если реальные данные изменились - это называется repeatable читает на языке изоляции транзакций.

http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

Ответ 2

Эта проблема для меня очень расстраивала, но я, наконец, понял это.

У меня есть приложение Flask/SQLAlchemy, работающее рядом со старым PHP-сайтом. Сайт PHP будет писать в базу данных, и SQLAlchemy не будет знать никаких изменений.

Я попробовал настройку sessionmaker autoflush = True безуспешно Я попробовал db_session.flush(), db_session.expire_all() и db_session.commit() перед запросом и NONE. Все еще показывали устаревшие данные.

Наконец, я столкнулся с этим разделом документов SQLAlchemy: http://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#transaction-isolation-level

Настройка параметра изоляции_области отлично работала. Теперь мое приложение Flask "разговаривает" с PHP-приложением. Здесь код:

engine = create_engine(
                "postgresql+pg8000://scott:[email protected]/test",
                isolation_level="READ UNCOMMITTED"
            )

Когда движок SQLAlchemy запускается с помощью параметра "READ UNCOMMITED" isol_level, он будет выполнять "грязные чтения", что означает, что он будет читать немедленные изменения непосредственно из базы данных.

Надеюсь, что это поможет


Вот возможное решение, предоставленное AaronD в комментариях

from flask.ext.sqlalchemy import SQLAlchemy

class UnlockedAlchemy(SQLAlchemy):
    def apply_driver_hacks(self, app, info, options):
        if "isolation_level" not in options:
            options["isolation_level"] = "READ COMMITTED"
    return super(UnlockedAlchemy, self).apply_driver_hacks(app, info, options)

Ответ 3

Дополнительно к zzzeek отличный ответ,

У меня была аналогичная проблема. Я решил проблему, используя короткие сеансы.

with closing(new_session()) as sess:
    # do your stuff

Я использовал новый сеанс для каждой задачи, группы задач или запроса (в случае веб-приложения). Это решило проблему "кэширования" для меня.

Этот материал был очень полезен для меня:

Когда я создаю сеанс, когда я его фиксирую и когда его закрываю

Ответ 4

Это происходило в моем приложении Flask, и мое решение заключалось в том, чтобы истечь все объекты в сеансе после каждого запроса.

from flask.signals import request_finished
def expire_session(sender, response, **extra):
    app.db.session.expire_all()
request_finished.connect(expire_session, flask_app)

Работал как шарм.

Ответ 5

Во-первых, для SQLAlchemy нет кеша. Основываясь на вашем методе получения данных из БД, вы должны сделать некоторый тест после обновления базы данных другими, посмотрите, сможете ли вы получать новые данные.

(1) use connection:
connection = engine.connect()
result = connection.execute("select username from users")
for row in result:
    print "username:", row['username']
connection.close()
(2) use Engine ...
(3) use MegaData...

пожалуйста, сделайте шаг: http://docs.sqlalchemy.org/en/latest/core/connections.html

Другая возможная причина заключается в том, что ваша база данных MySQL не обновляется постоянно. Перезапустите службу MySQL и проверьте чек.