I am using master/slave of sqlalchemy, by RoutingSession like
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
I printed log in “get_bind” method. And I found the “get_bind” method was executed twice when using “session.add(r); session.commit()”.
So why twice?
When using “session.execute(‘insert …’); session.commit()”, the “get_bind” method was called only once.
The session supports multiple engines being associated at once with it, and these engines are associated with the session based on mappers or tables. Therefore anytime the Session needs to talk to the database, and it has in hand a specific
mapper()to deal with, it must callget_bind()in order to get at the correct engine for this particular mapper. Within the flush, assuming dirty states exist (a result of session.add(r)), a particularmapper()is consulted more than once to get ready to emit SQL – at the moment at least once for the “save” pass and once for the “delete” pass though I can try to improve the unnecessary grab for the deletes in this case (edit: this is done).You can always tell why something is called when it is by sticking
import pdb; pdb.set_trace()inside of it, then doing a “where” at the console each time you get there.So in general you should assume get_bind() is called all the time. It shouldn’t matter how often it’s called.
Edit: the latest tip for 0.8 and 0.7 does not call get_bind() when there are no states to be flushed for a save/delete pass, so it’s now called once in this particular test.