Метод get_bind дважды вызывался в sqlalchemy при использовании RoutingSession.

Я использую master/slave 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". И я обнаружил, что метод «get_bind» выполнялся дважды при использовании «session.add(r); session.commit()». Так почему дважды?

При использовании "session.execute('insert ...'); session.commit()" метод "get_bind" вызывался только один раз.


person Tallmad    schedule 11.06.2012    source источник


Ответы (1)


Сеанс поддерживает несколько механизмов, связанных с ним одновременно, и эти механизмы связаны с сеансом на основе картографов или таблиц. Поэтому в любое время, когда сеансу необходимо обратиться к базе данных, и он имеет в своем распоряжении определенный mapper(), он должен вызвать get_bind(), чтобы получить правильный движок для этого конкретного преобразователя. При сбросе, если существуют грязные состояния (результат session.add(r)), к конкретному mapper() обращаются более одного раза, чтобы подготовиться к отправке SQL - на данный момент по крайней мере один раз для прохода «сохранить» и один раз для проход «удалить», хотя я могу попытаться улучшить ненужный захват для удаления в этом случае (редактировать: это сделано).

Вы всегда можете сказать, почему что-то вызывается, когда оно есть, вставив import pdb; pdb.set_trace() внутри него, а затем выполняя «где» в консоли каждый раз, когда вы туда попадаете.

Таким образом, вы должны предполагать, что get_bind() вызывается все время. Неважно, как часто его вызывают.

Редактировать: последний совет для 0.8 и 0.7 не вызывает get_bind(), когда нет состояний, которые нужно очистить для прохода сохранения/удаления, поэтому теперь он вызывается один раз в этом конкретном тесте.

person zzzeek    schedule 13.06.2012