sqlalchemy-session

本文主要用来探讨如何合理的使用 sqlalchemysession的一些基础知识

session 可能遇到的问题

  • 占用连接未释放,导致数据库连接满
  • 已查询的数据使用时返回None
  • 已变更过数据,但是查询时并没有得到最新的更新

session 是什么

  • 它管理与数据库相关的所有操作,包括数据连接、释放、事物相关等操作。

  • 它作为程序访问数据库的一个entrypoint

  • 它把从数据中取回的数据映射为ORM中的一个对象,并且存储在一个名为Identity Map的数据结构中

  • 它在存入数据时把一个ORM对应到一个数据表

session生命周期管理

使用session的一个基本准则,一个应用应该去管理session的生命周期,对于处理特殊数据的函数session应该作为一个参数被传递进来并且使用。

  • 对于一个后台任务,建议每个子线程分配一个session,生命周期为子线程生命周期
  • 对于命令行任务,建议应用建立一个单独的全局session
  • GUI驱动的应用,建议一个用户事件作为session的生命周期
  • 对于WEB应用,建议一个request作为生命周期

创建session

  • 对于sessionmaker 一般是作为一个全局变量仅定义一次
  • 对于session一般是在有数据逻辑操作开始的时候创建

使用session

在session中存储了一个对象的弱引用

  • 每条数据只保留一个副本,使用主键识别一条数据。如果查询时该数据已经存在session中,查询后将不会替换该数据,除非该数据已过期。
  • 查一条数据的最新状态时先commit再query
  • session的细节,事物和异常管理尽量与程序的细节分开处理

commit&&close

  • commit 或者rollback 前每个session 代表一个事物, 在commitsession中的数据会被标记为过期,但是不会被删除。应保证每个事物尽量短,避免持有数据锁时间过长影响数据库并发量。
  • 关闭session后所有的资源都会被释放,前面说了session中的ORM都是弱引用,查询所得的数据都可能消失。
  • 保证任务结束后关闭session防止资源泄漏,毕竟一个应用一般也就分配几百个连接,使用完后就么有了。

session使用例子

from contextlib import contextmanager

@contextmanager
def session_scope():
    """Provide a transactional scope around a series of operations."""
    session = Session()
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()
        
        
def run_my_program():
    with session_scope() as session:
        ThingOne().go(session)
        ThingTwo().go(session)

你可能感兴趣的:(sqlalchemy-session)