2012-04-18 108 views
12

sqlalchemyを使用するとキャッシュの問題が発生します。私はsqlalchemyを使用してデータをmysqlデータベースに挿入します。私は他のアプリケーションでこのデータを処理してから、このデータを直接更新します。しかし、私のsqlalchemyは、常に古いデータではなく、更新されたデータを持っています。私はsqlalchemyが私の要求をキャッシュしたと思う.. ..それを無効にする方法は?SQLAlchemyキャッシュを無効にする方法は?

+1

関連する? http://stackoverflow.com/questions/16586114/sqlalchemy-returns-stale-rows –

答えて

34

トランザクションにローカルな通常のSQLAlchemyアイデンティティマップに加えて、「キャッシュ」があると思う一般的な原因は、トランザクション分離の影響を観察していることです。 SQLAlchemyのセッションは、デフォルトでトランザクションモードで動作します。つまり、データベースにデータを保持するためにsession.commit()が呼び出されるまで待機します。この間、進行中の他のトランザクションはこのデータを表示しません。

ただし、トランザクションが分離されているため、余計なことがあります。進行中のこれらの他のトランザクションは、コミットされるまでトランザクションデータを表示しないだけでなく、がコミットまたはロールバックされるまでそれを見ることもできません。(これはあなたのclose()ここに)。平均度がであるトランザクションのトランザクションは、これまでロードされていた状態を保持し、実際のデータが変更されてもトランザクションと同じ状態を継続します。反復可能な読み取りトランザクション隔離用語。 zzzeek優秀な答えは、

にさらに

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

-1

私はSQLAlchemy does not store cachesを知っているので、loggingの出力を見る必要があります。

+0

私はそうだと思います。私は 'echo = True'を開いたが何も役に立たなかった。 –

+0

コミットでセッションを更新しましたか? –

+0

私は、MySQLに更新した。.. –

0

まず、SQLAlchemyのキャッシュはありません。 DBからデータをフェッチする方法に基づいて、データベースが他の人によって更新された後、何らかのテストを行い、新しいデータを取得できるかどうかを確認する必要があります。

(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... 

のステップfolowingしてください:http://docs.sqlalchemy.org/en/latest/core/connections.html

もう一つ考えられる理由は、あなたのMySQL DBを永続的に更新されないです。 MySQLサービスを再起動し、チェックしてください。

+0

返信いただきありがとうございます。私はそれを解決しました。私は 'scoped_session'を使うとき' session.close'を忘れてしまいます... –

3

私は同様の問題がありました。短い生きているセッションを使って問題を解決しました。

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

タスク、タスクグループまたはリクエスト(Webアプリケーションの場合)ごとに新しいセッションを使用しました。それが私の "キャッシング"問題を解決しました。

この材料は私にとって非常に有用であった

When do I construct a Session, when do I commit it, and when do I close it

+1

上記のリンクはセッションのためのドキュメントに行きます。このタイトルは、ここで指し示すべきであることを暗示しています:http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html#session-faq-whentocreate – mozey

11

この問題は、私にとって本当にイライラされているが、私はそれを最終的に考え出しました。

私は古いPHPサイトと一緒にFlask/SQLAlchemyアプリケーションを実行しています。 PHPサイトはデータベースに書き込み、SQLAlchemyは変更を認識しません。

私は()db_session.flushを試みdb_session.expire_all()、及びdb_session.commit()照会する前とどれも働いていない 失敗真sessionmaker設定自動フラッシュ=を試みました。まだ失効したデータを示しました。素晴らしい仕事http://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#transaction-isolation-level

ISOLATION_LEVELの設定:

は最後に、私はSQLAlchemyのドキュメントのこのセクションに出くわしました。今、私のフラスコのアプリはPHPアプリケーションと "話している"。ここでは、コードです:
engine = create_engine(
       "postgresql+pg8000://scott:[email protected]/test", 
       isolation_level="READ UNCOMMITTED" 
      ) 

それがデータベースから直接コミットされていない変更を読むことを意味している「ダーティリード」を実行しますISOLATION_LEVEL「UNCOMMITED READ」とSQLAlchemyのエンジンが始動される

。これはここで


を助け

ホープこれが私のフラスコアプリケーションで起こっていた、と私の解決策は、内のすべてのオブジェクトを期限切れにすることでした

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) 
+0

Flask-SQLAlchemyを使用している場合、 'flask.ext .sqlalchemy.SQLAlchemy'を実行し、 'apply_driver_hacks'関数をオーバーライドして、Flaskの統合をすべて維持しながら、分離レベルを設定します。また、両方のアプリケーションが書き込みをコミットし、それを作成してから長時間待たなければ、分離レベル「READ COMMITTED」で十分です。そうすることで、ダーティな読み込みについて心配する必要がなくなります。読み込むたびに新しくDBスナップショットが表示されます。 –

+0

@AaronD 'flask.ext.sqlalchemy.SQLAlchemy'のサブクラスにコードを記述しても問題ありませんか? –

+1

私はちょうど私のコードでこれを持っている: 'クラスUnlockedAlchemy(SQLAlchemyの): はデフapply_driver_hacks(自己、アプリ、情報、オプション): オプションではない "ISOLATION_LEVEL" 場合: オプションは、[ "ISOLATION_LEVEL"] =「COMMITTED READ " 返品super(UnlockedAlchemy、self).apply_driver_hacks(app、info、options)' –

3

コメントでAaronDの可能な解決策の礼儀でありますセッションごとに要求されます。

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

チャームのように働いた。