【Python】SQLAlchemy:session何时commit,何时close?
SQLAlchemy:session何時(shí)commit,何時(shí)close?
參考閱讀:SQLAlchemy - 官方文檔
官方文檔說明了關(guān)于什么是session,以及如何創(chuàng)建session、如何使用session、如何關(guān)閉session
參考閱讀 - When do I construct a Session, when do I commit it, and when do I close it?
As a general rule, keep the lifecycle of the session separate and external from functions and objects that access and/or manipulate database data. This will greatly help with achieving a predictable and consistent transactional scope.
一般來說,將會(huì)話的生命周期與訪問和/或操作數(shù)據(jù)庫(kù)數(shù)據(jù)的函數(shù)和對(duì)象分開。這將極大地幫助實(shí)現(xiàn)可預(yù)測(cè)和一致的事務(wù)范圍。
Make sure you have a clear notion of where transactions begin and end, and keep transactions short, meaning, they end at the series of a sequence of operations, instead of being held open indefinitely.
確保您對(duì)事務(wù)在何處開始和結(jié)束有一個(gè)清晰的概念,并保持事務(wù)簡(jiǎn)短,即它們在一系列操作中結(jié)束,而不是無限期地保持打開狀態(tài)。
官方示例
E.g. don’t do this:
### this is the **wrong way to do it** ###class ThingOne(object):def go(self):session = Session()try:session.query(FooBar).update({"x": 5})session.commit()except:session.rollback()raiseclass ThingTwo(object):def go(self):session = Session()try:session.query(Widget).update({"q": 18})session.commit()except:session.rollback()raisedef run_my_program():ThingOne().go()ThingTwo().go()Keep the lifecycle of the session (and usually the transaction) separate and external:
### this is a **better** (but not the only) way to do it ###class ThingOne(object):def go(self, session):session.query(FooBar).update({"x": 5})class ThingTwo(object):def go(self, session):session.query(Widget).update({"q": 18})def run_my_program():session = Session()try:ThingOne().go(session)ThingTwo().go(session)session.commit()except:session.rollback()raisefinally:session.close()The most comprehensive approach, recommended for more substantial applications, will try to keep the details of session, transaction and exception management as far as possible from the details of the program doing its work. For example, we can further separate concerns using a context manager:
### another way (but again *not the only way*) to do it ###from contextlib import contextmanager@contextmanager def session_scope():"""Provide a transactional scope around a series of operations."""session = Session()try:yield sessionsession.commit()except:session.rollback()raisefinally:session.close()def run_my_program():with session_scope() as session:ThingOne().go(session)ThingTwo().go(session)StackOverflow 上關(guān)于如何關(guān)閉 SQLAlchemy session 的討論:
回答1:StackOverflow - How to close a SQLAlchemy session?
如何正確的關(guān)閉 SQLAlchemy session?
StackOverflow 上面關(guān)于此問題的回答:
回答2:StackOverflow - How to close a SQLAlchemy session?
如何正確的關(guān)閉 SQLAlchemy session?
再看一個(gè) StackOverflow 上面關(guān)于此問題的回答:
回答說:That is, the Engine is a factory for connections as well as a pool of connections, not the connection itself. When you say conn.close(), the connection is returned to the connection pool within the Engine, not actually closed.
也就是說,Engine 相當(dāng)于一個(gè)創(chuàng)建連接的工廠,而不是連接本身。當(dāng)使用conn.close()時(shí),連接被放回到Engine的連接池當(dāng)中,而不是真正的關(guān)閉了。
如果想要在調(diào)用conn.close()時(shí),真正的關(guān)閉連接,可以使用poolclass=NullPool屬性:
from sqlalchemy.pool import NullPool db = create_engine('mysql://root@localhost/test_database', poolclass=NullPool)拓展閱讀:MySQL server has gone away 原因分析及解決方式
conn.close() 是把連接放回連接池,不是真正的關(guān)閉;池子里的空閑連接在MySQL線程里sleep,長(zhǎng)時(shí)間不操作,MySQL把連接一端關(guān)閉了,所以第二天SQLAlchemy再用這個(gè)連接的時(shí)候,拋出MySQL server has gone away…
總結(jié)
以上是生活随笔為你收集整理的【Python】SQLAlchemy:session何时commit,何时close?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Python】吐槽SQLAlchemy
- 下一篇: 【MySQL】如何让数据库查询区分大小写