SQLAlchemy 對象緩存和刷新


SQLAlchemy 對象緩存和刷新

SQLAlchemy 帶有對象緩存機制,在重復查詢相同的對象時,直接先查詢本地的緩存,而不需要從數據庫加載數據。

在每個 model 對象的內部,SQLAlchemy 在對象的 __dict__ 中維護對象的狀態。它往 __dict__ 中加入對象的狀態 _sa_instance_state,通過這個值來跟蹤對象。_sa_instance_statesqlalchemy.orm.state.InstanceState 類型,里面保存這個對象的 session 、orm mapper 等等信息。

在一般的情況下,這種方法會非常高效。但如果在進行跨進程操作時,如果不加以特別的處理,對象緩存機制會導致一個進程無法取得另外一個進程的對象更新情況。

假設兩個進程 A,B,A 在操作 object 的更新,B 等待 object 的狀態,如下:

A 進程

object = session.query(MyObject).first()
# do something
with session.begin():
    object.status = 'SUCCESS'

B 進程

while True:
    object = session.query(MyObject).first()
    if object.status == 'SUCCESS':
        # do something
        break
    sleep(10)

在 B 進程中,雖然每次循環都進行查詢,但由於緩存機制,其實只有第一次會從數據庫加載,在數據過期前,都是直接讀取緩存,所以 B 進程會一直在等待狀態。

解決的方法是進行對象刷新。對於這些需要每次更新狀態的對象,通過 session.refresh(object)session.expire(object),讓對象過期,從而在下次訪問時重新加載。

B 進程

object = session.query(MyObject).first()
while True:
    if object.status == 'SUCCESS':
        # do something
        break
    session.refresh(object)
    sleep(10)

session.refreshsession.expire 支持只刷新特定的屬性,如

session.refresh(object, ['status'])

這種做法就降低重新加載時所傳遞的數據量,具有 BLOB 大數據量的字段可又不重新加載。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM