SQLAlchemy 對象緩存和刷新 ====================================== SQLAlchemy 帶有對象緩存機制,在重覆查詢相同的對象時,直接先查詢本地的緩存,而不需要從資料庫載入數據。 在每個 model 對象的內部,SQLAlchemy 在對象的 中維護 ...
SQLAlchemy 對象緩存和刷新
SQLAlchemy 帶有對象緩存機制,在重覆查詢相同的對象時,直接先查詢本地的緩存,而不需要從資料庫載入數據。
在每個 model 對象的內部,SQLAlchemy 在對象的 __dict__
中維護對象的狀態。它往 __dict__
中加入對象的狀態 _sa_instance_state
,通過這個值來跟蹤對象。_sa_instance_state
是 sqlalchemy.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.refresh
或 session.expire
支持只刷新特定的屬性,如
session.refresh(object, ['status'])
這種做法就降低重新載入時所傳遞的數據量,具有 BLOB 大數據量的欄位可又不重新載入。