使用 RoutingSession 时在 sqlalchemy 中调用了两次“get_bind”方法
Posted
技术标签:
【中文标题】使用 RoutingSession 时在 sqlalchemy 中调用了两次“get_bind”方法【英文标题】:"get_bind" method was called twice in sqlalchemy when using RoutingSession 【发布时间】:2012-06-11 03:49:40 【问题描述】:我正在使用 sqlalchemy 的主/从,通过 RoutingSession 之类的
engines =
'master':create_engine("sqlite:///master.db"),
'other':create_engine("sqlite:///other.db"),
'slave1':create_engine("sqlite:///slave1.db"),
'slave2':create_engine("sqlite:///slave2.db"),
from sqlalchemy.orm import Session, sessionmaker
import random
class RoutingSession(Session):
def get_bind(self, mapper=None, clause=None):
if mapper and issubclass(mapper.class_, MyOtherClass):
return engines['other']
elif self._flushing:
return engines['master']
else:
return engines[
random.choice(['slave1','slave2'])
]
http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#custom-vertical-partitioning
我用“get_bind”方法打印了日志。我发现在使用“session.add(r); session.commit()”时,“get_bind”方法被执行了两次。 那为什么要两次呢?
当使用“session.execute('insert ...'); session.commit()”时,“get_bind”方法只被调用一次。
【问题讨论】:
【参考方案1】:会话支持同时关联多个引擎,这些引擎基于映射器或表与会话关联。因此,任何时候 Session 需要与数据库通信,并且它手头有一个特定的mapper()
来处理,它必须调用get_bind()
以便为这个特定的映射器获取正确的引擎。在刷新中,假设存在脏状态(session.add(r) 的结果),会多次咨询特定的mapper()
以准备发出 SQL - 目前至少一次用于“保存”传递和一次用于“删除”传递,尽管在这种情况下我可以尝试改进不必要的删除抓取(编辑:完成)。
您总是可以通过将import pdb; pdb.set_trace()
粘贴在其中,然后每次到达那里时在控制台上执行“位置”来判断为什么调用某项。
所以通常你应该假设 get_bind() 一直被调用。它被调用的频率应该是无关紧要的。
编辑:0.8 和 0.7 的最新提示不会调用 get_bind() 当没有要刷新的状态以进行保存/删除传递时,因此现在在此特定测试中调用一次。
【讨论】:
以上是关于使用 RoutingSession 时在 sqlalchemy 中调用了两次“get_bind”方法的主要内容,如果未能解决你的问题,请参考以下文章