使用 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”方法的主要内容,如果未能解决你的问题,请参考以下文章

PHP 和 MYSQL:为啥 A 有效而 B 无效?

如何异步查询多条SQL?

技术积累树形结构的循环查找实现案例1

HA_Mirror 数据库镜像

使用 NSString 方法 boundingRectWithSize 时在 iOS 11 上崩溃

为啥使用 GTKGLArea 时在 PyOpenGL 中未定义 glGenVertexArrays