SQLAlchemy会话与事务控制

转自:http://www.codexiu.cn/python/sqlalchemy基础教程/531/


       本篇内容为大家提供的是SQLAlchemy基础教程中的SQLAlchemy会话与事务控制,该教程主要介绍了SQLAlchemy会话与事务控制的基本使用、for update、事务嵌套、二段式提交等,详细而全面,感兴趣的同学可以参考学习一下。


5. SQLAlchemy会话与事务控制

5.1. 基本使用

SQLAlchemy 的 session 是用于管理数据库操作的一个像容器一样的东西. 模型实例对象本身独立存在, 而要让其修改(创建)生效, 则需要把它们加入某个 session . 同时你也可以把模型实例对象从 session 中去除. 被 session 管理的实例对象, 在 session.commit() 时被提交到数据库. 同时 session.rollback() 是回滚变更.

session.flush() 的作用是在事务管理内与数据库发生交互, 对应的实例状态被反映到数据库. 比如自增 ID 被填充上值.

 
 
user = User(name=u'名字') session.add(user) session.commit()
 
 
try: user = session.Query(User).first() user.name = u'改名字 session.commit() except: session.rollback()

5.2. for update

SQLAlchemy 的 Query 支持 select ... for update / share .

 
 
session.Query(User).with_for_update().first() session.Query(User).with_for_update(read=True).first()

完整形式是:

 
 
with_for_update(read=False, nowait=False, of=None)
read
是标识加互斥锁还是共享锁. 当为  True 时, 即  for share 的语句, 是共享锁. 多个事务可以获取共享锁, 互斥锁只能一个事务获取. 有"多个地方"都希望是"这段时间我获取的数据不能被修改, 我也不会改", 那么只能使用共享锁.
nowait
其它事务碰到锁, 是否不等待直接"报错".
of
指明上锁的表, 如果不指明, 则查询中涉及的所有表(行)都会加锁.

5.3. 事务嵌套

SQLAlchemy 中的事务嵌套有两种情况. 一是在 session 中管理的事务, 本身有层次性. 二是 session 和原始的 connection 之间, 是一种层次关系, 在这 session , connection 两个概念之中的事务同样具有这样的层次.

session 中的事务, 可能通过 begin_nested() 方法做 savepoint :

 
 
session.add(u1) session.add(u2) session.begin_nested() session.add(u3) session.rollback() # rolls back u3, keeps u1 and u2 session.commit()

或者使用上下文对象:

 
 
for record in records: try: with session.begin_nested(): session.merge(record) except: print "Skipped record %s" % record session.commit()

嵌套的事务的一个效果, 是最外层事务提交整个变更才会生效.

 
 
user = User(name='2') session.begin_nested() session.add(user) session.commit() session.rollback()

于是, 前面说的第二种情况有一种应用方式, 就是在 connection 上做一个事务, 最终也在 connection 上回滚这个事务, 如果 session 是 bind 到这个连接上的, 那么 session 上所做的更改全部不会生效:

 
 
conn = Engine.connect() session = Session(bind=conn) trans = conn.begin() user = User(name='2') session.begin_nested() session.add(user) session.commit() session.commit() trans.rollback()

在测试中这种方式可能会有用.

5.4. 二段式提交

二段式提交, Two-Phase, 是为解决分布式环境下多点事务控制的一套协议.

与一般事务控制的不同是, 一般事务是 begin, 之后 commit 结束.

而二段式提交的流程上, begin 之后, 是 prepare transaction 'transaction_id' , 这时相关事务数据已经持久化了. 之后, 再在任何时候(哪怕重启服务), 作 commit prepared 'transaction_id' 或者 rollback prepared 'transaction_id' .

从多点事务的控制来看, 应用层要做的事是, 先把任务分发出去, 然后收集"事务准备"的状态(prepare transaction 的结果). 根据收集的结果决定最后是 commit 还是 rollback .

简单来说, 就是事务先保存, 再说提交的事.

SQLAlchemy 中对这个机制的支持, 是在构建会话类是加入 twophase 参数:

 
 
Session = sessionmaker(twophase=True)

然后会话类可以根据一些策略, 绑定多个 Engine , 可以是多个数据库连接, 比如:

 
 
Session = sessionmaker(twophase=True) Session.configure(binds={User: Engine, Blog: Engine2})

这样, 在获取一个会话实例之后, 就处在二段式提交机制的支持之下, SQLAlchemy 自己会作多点的协调了. 完整的流程:

 
 
Engine = create_engine('postgresql://test@localhost:5432/test', echo=True) Engine2 = create_engine('postgresql://test@localhost:5432/test2', echo=True) Session = sessionmaker(twophase=True) Session.configure(binds={User: Engine, Blog: Engine2}) session = Session() user = User(name=u'名字') session.add(user) session.commit()

对应的 SQL 大概就是:

 
 
begin; insert into "user" (name) values (?); prepare transaction 'xx'; commit prepared 'xx';

使用时, Postgresql 数据库需要把 max_prepared_transactions 这个配置项的值改成大于 0 




       本篇内容为大家提供的是SQLAlchemy基础教程中的SQLAlchemy会话与事务控制,该教程主要介绍了SQLAlchemy会话与事务控制的基本使用、for update、事务嵌套、二段式提交等,详细而全面,感兴趣的同学可以参考学习一下。


5. SQLAlchemy会话与事务控制

5.1. 基本使用

SQLAlchemy 的 session 是用于管理数据库操作的一个像容器一样的东西. 模型实例对象本身独立存在, 而要让其修改(创建)生效, 则需要把它们加入某个 session . 同时你也可以把模型实例对象从 session 中去除. 被 session 管理的实例对象, 在 session.commit() 时被提交到数据库. 同时 session.rollback() 是回滚变更.

session.flush() 的作用是在事务管理内与数据库发生交互, 对应的实例状态被反映到数据库. 比如自增 ID 被填充上值.

 
  
user = User(name=u'名字') session.add(user) session.commit()
 
  
try: user = session.Query(User).first() user.name = u'改名字 session.commit() except: session.rollback()

5.2. for update

SQLAlchemy 的 Query 支持 select ... for update / share .

 
  
session.Query(User).with_for_update().first() session.Query(User).with_for_update(read=True).first()

完整形式是:

 
  
with_for_update(read=False, nowait=False, of=None)
read
是标识加互斥锁还是共享锁. 当为  True 时, 即  for share 的语句, 是共享锁. 多个事务可以获取共享锁, 互斥锁只能一个事务获取. 有"多个地方"都希望是"这段时间我获取的数据不能被修改, 我也不会改", 那么只能使用共享锁.
nowait
其它事务碰到锁, 是否不等待直接"报错".
of
指明上锁的表, 如果不指明, 则查询中涉及的所有表(行)都会加锁.

5.3. 事务嵌套

SQLAlchemy 中的事务嵌套有两种情况. 一是在 session 中管理的事务, 本身有层次性. 二是 session 和原始的 connection 之间, 是一种层次关系, 在这 session , connection 两个概念之中的事务同样具有这样的层次.

session 中的事务, 可能通过 begin_nested() 方法做 savepoint :

 
  
session.add(u1) session.add(u2) session.begin_nested() session.add(u3) session.rollback() # rolls back u3, keeps u1 and u2 session.commit()

或者使用上下文对象:

 
  
for record in records: try: with session.begin_nested(): session.merge(record) except: print "Skipped record %s" % record session.commit()

嵌套的事务的一个效果, 是最外层事务提交整个变更才会生效.

 
  
user = User(name='2') session.begin_nested() session.add(user) session.commit() session.rollback()

于是, 前面说的第二种情况有一种应用方式, 就是在 connection 上做一个事务, 最终也在 connection 上回滚这个事务, 如果 session 是 bind 到这个连接上的, 那么 session 上所做的更改全部不会生效:

 
  
conn = Engine.connect() session = Session(bind=conn) trans = conn.begin() user = User(name='2') session.begin_nested() session.add(user) session.commit() session.commit() trans.rollback()

在测试中这种方式可能会有用.

5.4. 二段式提交

二段式提交, Two-Phase, 是为解决分布式环境下多点事务控制的一套协议.

与一般事务控制的不同是, 一般事务是 begin, 之后 commit 结束.

而二段式提交的流程上, begin 之后, 是 prepare transaction 'transaction_id' , 这时相关事务数据已经持久化了. 之后, 再在任何时候(哪怕重启服务), 作 commit prepared 'transaction_id' 或者 rollback prepared 'transaction_id' .

从多点事务的控制来看, 应用层要做的事是, 先把任务分发出去, 然后收集"事务准备"的状态(prepare transaction 的结果). 根据收集的结果决定最后是 commit 还是 rollback .

简单来说, 就是事务先保存, 再说提交的事.

SQLAlchemy 中对这个机制的支持, 是在构建会话类是加入 twophase 参数:

 
  
Session = sessionmaker(twophase=True)

然后会话类可以根据一些策略, 绑定多个 Engine , 可以是多个数据库连接, 比如:

 
  
Session = sessionmaker(twophase=True) Session.configure(binds={User: Engine, Blog: Engine2})

这样, 在获取一个会话实例之后, 就处在二段式提交机制的支持之下, SQLAlchemy 自己会作多点的协调了. 完整的流程:

 
  
Engine = create_engine('postgresql://test@localhost:5432/test', echo=True) Engine2 = create_engine('postgresql://test@localhost:5432/test2', echo=True) Session = sessionmaker(twophase=True) Session.configure(binds={User: Engine, Blog: Engine2}) session = Session() user = User(name=u'名字') session.add(user) session.commit()

对应的 SQL 大概就是:

 
  
begin; insert into "user" (name) values (?); prepare transaction 'xx'; commit prepared 'xx';

使用时, Postgresql 数据库需要把 max_prepared_transactions 这个配置项的值改成大于 0 


猜你喜欢

转载自blog.csdn.net/bluehawksky/article/details/79453477
今日推荐