0

私はsqlalchemyのマスター/スレーブを使用しています。

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」メソッドが2回実行されたことがわかりました。では、なぜ2回なのか。

「session.execute('insert ...'); session.commit()」を使用する場合、「get_bind」メソッドは1回だけ呼び出されました。

4

1 に答える 1

1

セッションは、一度に関連付けられる複数のエンジンをサポートし、これらのエンジンは、マッパーまたはテーブルに基づいてセッションに関連付けられます。したがって、セッションがデータベースと通信する必要があり、処理する特定のものが手元にあるときはいつでも、この特定のマッパーの正しいエンジンを取得するためにmapper()呼び出す必要があります。get_bind()フラッシュ内で、ダーティ状態が存在すると仮定すると(session.add(r)の結果)、mapper()SQLを発行する準備をするために、特定のものが複数回参照されます。現時点では、「保存」パスに対して少なくとも1回、この場合、削除のための不要なグラブを改善することを試みることができますが、「削除」パス(編集:これは行われます)。

import pdb; pdb.set_trace()何かが呼び出されたときにその中に貼り付けて、そこに着くたびにコンソールで「どこ」を実行することで、いつでも何かが呼び出される理由を知ることができます。

したがって、一般に、get_bind()が常に呼び出されると想定する必要があります。どれくらいの頻度で呼び出されるかは問題ではありません。

編集:保存/削除パスのためにフラッシュされる状態がない場合、0.8および0.7の最新のヒントはget_bind()を呼び出さないため、この特定のテストで1回呼び出されるようになりました。

于 2012-06-13T14:00:24.147 に答える