2012-04-18 97 views
12

我在使用sqlalchemy時遇到緩存問題。我使用sqlalchemy將數據插入到mysql數據庫中。我有另一個應用程序處理這些數據,然後直接更新這些數據。但我的sqlalchemy總是得到舊數據,而不是更新的數據..我認爲sqlalchemy緩存我的請求..所以..如何禁用它?如何禁用SQLAlchemy緩存?

+1

相關? http://stackoverflow.com/questions/16586114/sqlalchemy-returns-stale-rows – 2013-05-16 11:21:50

回答

34

通常引起人的思維有一個「緩存」在作怪,除了一般的SQLAlchemy的身份地圖是本地的事務,是他們正在觀察事務隔離的效果。默認情況下,SQLAlchemy的會話在事務模式下工作,這意味着它會等到調用session.commit()才能將數據保存到數據庫。在此期間,別處正在進行的其他交易將不會看到這些數據。

然而,由於交易的性質孤立,有一個額外的扭曲。在進展的其他交易不僅不會看到您的交易數據,直到它承諾,他們也無法看到它在某些情況下,直到他們提交或回滾也(這是一樣的效果您close()時有這裏)。平均程度的隔離事務將保留狀態,它迄今加載,並不斷給你同樣的狀態本地儘管實際數據已經改變了交易 - 這被稱爲重複的事務讀取隔離的說法。

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

-1

據我所知SQLAlchemy的does not store caches,所以你需要尋找logging輸出。

+0

我這麼認爲。我打開'echo = True',但沒有任何用處。 – 2012-04-18 13:31:04

+0

你有提交更新會話嗎? – 2012-04-18 13:38:12

+0

我更新數據而不使用sqlalchemy ..使用'MySQLdb' ..我確保數據已經在MySQL中更新了.. – 2012-04-18 13:40:25

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

請如下因素在步:http://docs.sqlalchemy.org/en/latest/core/connections.html

另一個可能的原因是你的MySQL數據庫沒有更新永久。重新啓動MySQL服務並進行檢查。

+0

感謝您的回覆。我解決了它。當我使用'scoped_session'時,我忘了'session.close' ... – 2012-04-18 14:11:48

3

此外,以zzzeek出色答卷,

我有一個類似的問題。我通過短暫的生活會議解決了這個問題。

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 2015-05-29 09:13:24

11

這個問題對我來說真的很令人沮喪,但我終於想通了。

我旁邊有一個較舊的PHP網站上投放的瓶/ SQLAlchemy的應用。 PHP站點會寫入數據庫,SQLAlchemy不會意識到任何更改。

我試過sessionmaker設置autoflush = True失敗 在查詢和NONE工作之前,我嘗試了db_session.flush(),db_session.expire_all()和db_session.commit()。仍然顯示陳舊的數據。

最後,我遇到了SQLAlchemy的文檔的這一部分:http://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#transaction-isolation-level

設置ISOLATION_LEVEL偉大的工作。現在我的Flask應用程序正在與PHP應用程序「交談」。下面的代碼:

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

當SQLAlchemy的發動機起動「讀UNCOMMITED」 ISOLATION_LEVEL它將執行「髒讀」,這意味着它會直接從數據庫中讀取未提交更改。

希望這有助於


這是在評論

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」足以讓兩個應用程序在創建它們之後提交它們的寫入,而不是等待很長時間。這樣,您就不必擔心臟讀 - 每次閱讀時它都會爲您提供全新的數據庫快照。 – 2015-09-16 05:09:18

+0

@AaronD你可以將你的代碼發佈到子類'flask.ext.sqlalchemy.SQLAlchemy'嗎? – 2016-03-08 20:05:11

+1

我只是有這個在我的代碼: '類UnlockedAlchemy(SQLAlchemy的): 高清apply_driver_hacks(個體經營,應用,信息,選項): 如果沒有 「ISOLATION_LEVEL」 的選項: 選項[ 「ISOLATION_LEVEL」] =「READ COMMITTED 「 return super(UnlockedAlchemy,self).apply_driver_hacks(app,info,options)' – 2016-03-09 14:33:59

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) 

工作就像一個魅力。