SQlALchemy session詳解
系列文章:
概念
session用於創建程序和數據庫之間的會話,所有對象的載入和保存都需通過session對象 。
通過sessionmaker調用創建一個工廠,並關聯Engine以確保每個session都可以使用該Engine連接資源:
from sqlalchemy.orm import sessionmaker
# 創建session
DbSession = sessionmaker(bind=engine)
session = DbSession()
操作
session的常見操作方法包括:
- flush:預提交,提交到數據庫文件,還未寫入數據庫文件中
- commit:提交了一個事務,把內存的數據直接寫入數據庫
- rollback:回滾
- close:關閉
在事務處理時,需注意一下兩點:
- 在事務處理過程發生異常時,進行rollback操作,否則會在下次操作時報錯:
Can’t reconnect until invalid transaction is rolled back
- 一般情況下,在一個事務處理完成之後要關閉session,以確保數據操作的準確性。
建議封裝上下文方法:
from contextlib import contextmanager
@contextmanager
def session_maker(session=session):
try:
yield session
session.commit()
except:
session.rollback()
raise
finally:
session.close()
調用:
def update_user():
with session_maker() as db_session:
db_session.query(Users).filter_by(name='test2').update({'email': 'test2@qq.com'})
線程安全
session不是線程安全的,並且我們一般session對象都是全局的,那麼在多線程情況下,當多個線程共享一個session時,數據處理就會發生錯誤。
為了保證線程安全,需使用scoped_session方法:
db_session = scoped_session(sessionmaker(bind=engine))
內部原理
session對象包含了三個重要的部分:
- 標識映射(Identity Map)
- 對象的狀態 / 狀態跟蹤
- 事務
標識映射
標識映射是與ORM關聯的集合,通過標識映射保證了數據庫操作的準確性。
具體的實現原理是:維護一個Python字典(IdentityMap),關聯這個Session對象到數據庫ID的映射,當應用程序想要獲取一個session對象時,若該對象不存在,標識映射會加載該對象並緩存,若該對象已存在,則直接獲取。這樣的好處是:
- 已經被請求過的session對象緩存下來,不需要連接加載多次,造成額外的開銷;
- 避免了數據不一致
狀態跟蹤
一個Session對象從創建到銷毀,依次經歷四種狀態,分別是:
- Transient:剛new出來的對象,還不在會話中,也沒有保存到數據庫。
- Pending:transient的對象調用add后,就會變成pending狀態,這時會加入sqlalchemy的監管範圍,數據並未更新到數據庫。
- Persistent:該狀態表明數據庫里已經記錄了該對象,在兩種情況下對象處於該狀態:一是通過flush()方法刷新pending對象,二是從數據庫query()得到對象。
- Detached:在會話中的事務提交之後,所有的對象都將是Detached狀態。
所謂的狀態跟蹤,就是跟蹤以上四個狀態,保證數據的準確性並在合理的時機丟棄對象以保證合理開銷,那麼具體是怎麼實現的呢?
我們可以看到,只有在pending狀態時,對象的內存數據和數據庫中的數據不一致,在Persistent狀態時,內存數據和數據庫數據已經一致,那麼此後任意時刻丟棄該對象數據都是可以的,這時就需要找個合適的時機丟棄對象,過早或過晚都有其缺陷。於是,就讓垃圾回收器來做決定,在內存不夠的時候釋放對象,回收內存。
Session對象採用了弱引用機制,所謂弱引用,就是說,在保存了對象的引用的情況下,對象仍然可能被垃圾回收器回收。在某一時刻通過引用訪問對象時,對象可能存在也可能不存在,如果對象不存在,就重新從數據庫中加載對象。而如果不希望對象被回收,只需要另外保存一個對象的強引用即可 。
session對象包括三個屬性:
- new:剛加入會話的對象
- dirty:剛被修改的對象
- deleted:在會話中被刪除的對象
三個屬性共同的特點就是內存的數據和數據庫數據不一致,也就是對象處於pending狀態,這也就表明了session保存了所有對象處於pending狀態的強引用。
以上。
代碼可參照:
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!
※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!
※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!