SqlAlchemy快取機制導致的問題與解決方法

2021-09-29 20:54:37 字數 1243 閱讀 4094

最近寫**時發現乙個問題,**邏輯如下

def

test

(self, employee_id, name)

: row=self.db.query(employee)

.filter

(employee.

id== employee_id)

.first(

) employee.batch_update(

) self.db.commit(

)return self.db.query(employee)

.filter

(employee.

id== employee_id)

.first(

).name

實際只做了很簡單的操作,查詢資訊,修改,再次查詢。

但是第二次查詢得到的資訊並不是修改後的內容,而是第一次的查詢結果,這是由於sqlalchemy 自身的「快取」機制導致的。

對於第一次的查詢結果row來說,如果進行了一次查詢,實際是生成了乙個單例模式的物件,並在這個物件中管理了session。當這個物件處於持久狀態(persistent),後續的查詢實際上是從這個物件中取的值。關於該物件更詳細的敘述,可參考官方文件

現在知道了產生問題的原因,那我們只需要將這個物件中的「快取」給清理掉。sqlalchemy 有多種方法可以清除

db.session.expire(product)

db.session.refresh(product)

db.session.expire_all(

)db.session.flush(

)db.session.commit(

)

但現在問題又來了,既然commit會自動清除快取,那為什麼我們更新之後查到的還是上一次的結果呢。網上有人分析是mysql的事務隔離導致的不可重複讀,但這裡個人的看法是:employee.batch_update() 這句話實際上又建立了乙個物件,commit只是將該物件的快取清空,並沒有影響到已有的查詢物件。

所以這裡還有乙個辦法,直接用remove釋放本次session,那麼下一次一定是沒有快取的。

self.db.remove(

)

還有乙個有意思的點,如果查詢的物件沒有被引用, 該物件將會被python的gc自動**,對應的session也將不復存在。如果不想被**掉,可以自己參照官方文件設計強引用。

sqlalchemy連線池機制

一.sqlalchemy連線池 我寫了乙個簡單的內網dns管理系統,用到flask和sqlalchemy。主要就是通過web頁面和api對dns記錄進行增刪改查,所有這些操作都寫入資料庫,每次更改後產生乙個celery任務來非同步的重新生成dns的配置檔案。看起來乙個簡單的問題,但是在celery中...

IOS 開發快取機制 記憶體快取機制

使用快取的目的是為了使用的應用程式能更快速的響應使用者輸入,是程式高效的執行。有時候我們需要將遠端 web伺服器獲取的資料快取起來,減少對同乙個 url多次請求。記憶體快取我們可以使用 sdk中的 nsurlcache類。nsurlrequest需要乙個快取引數來說明它請求的 url何如快取資料的,...

SQLAlchemy多執行緒下事務隔離機制詳解

通過開啟多執行緒,併發查詢訂單詳情資訊,通過將不同訂單物件傳送給不同執行緒,執行完所需要的業務邏輯之後,對訂單物件的資料進行修改,然後執行 commit,查詢資料庫發現資料沒有更新,且後台日誌沒有任何的報錯 錯誤 from concurrent.futures import threadpoolex...