为什么SQLAlchemy Session.filter()。update / delete在使用RoutingSession时会引发只读异常?

时间:2013-05-14 04:10:07

标签: python mysql session sqlalchemy master-slave

以下是我的配置,slave是只读的:

engines = {                                                                        
    'master': create_engine(                                                       
        settings.MASTER_URL, echo=settings.ECHO_SQL, pool_recycle=3600),           
    'slave': create_engine(                                                        
        settings.SLAVE_URL, echo=settings.ECHO_SQL, pool_recycle=3600),            
}                                                                                  


class RoutingSession(Session):                                                     
    def get_bind(self, mapper=None, clause=None):                                  
        #return engines['master']                                                  
        if self._flushing:                                                         
            return engines['master']                                               
        else:                                                                      
            return engines['slave']                                                

DBSession = scoped_session(sessionmaker(class_=RoutingSession))

当我这样做时:

s = DBSession()
#synchronize_session=False makes execution faster
s.query(Model).filter(Model.id == 1).delete(synchronize_session=False)
s.commit()

它引发了一个例外,即由于“只读”而无法删除。

如何重写我的RoutingSession以使上述'删除'使用'master'数据库

--- --- EDIT1

我做了更多测试。上面的'delete'与以下'delete'不同,RoutingSession将返回'master':

model = s.query(Model).filter(Model.id == 1).first()
s.delete(model)
s.commit()

1 个答案:

答案 0 :(得分:0)

query.delete()不是“同花顺”的一部分,因此通常情况下,如果您使用的是routing session recipe,则需要实施using_bind()并在操作之前调用delete() class RoutingSession(Session): def get_bind(self, mapper=None, clause=None ): if self._name: return engines[self._name] else: # other cases here _name = None def using_bind(self, name): s = RoutingSession() vars(s).update(vars(self)) s._name = name return s

Session().using_bind("master").query(Model1).delete()

然后使用:

{{1}}