Соединение с несколькими экземплярами БД с помощью SqlAlchemy Core - PullRequest
0 голосов
/ 04 февраля 2019

Я пытаюсь установить соединение с несколькими базами данных.Сейчас я могу создать соединение с одним движком для нескольких баз данных.Это работает для моей основной базы данных (Shared database), определенной в mainschema.py (псевдоним dbm):

mymetadata = MetaData()

Base = declarative_base(metadata=mymetadata)

class newbase(DeferredReflection, Base):
    __abstract__ = True

table_args = {
        'mysql_engine': dict_constants['sql_mainDB_engine'],
        'mysql_charset': dict_constants['sql_mainDB_collation'],
        'schema' : 'smv',
    }

class Company(newbase):
__tablename__ = 'companies'
__table_args__ = table_args

id = Column(INTEGER(unsigned=True), primary_key=True)
company = Column(String(255))
db = Column(String(255))
enabled = Column(BOOLEAN, nullable=False)

Тогда для каждого клиента у меня будет определенная база данных, определенная в dbschema.py (псевдоним dbc)

mymetadata = MetaData()

Base = declarative_base()

table_args = {
        'mysql_engine': dict_constants['sql_mainDB_engine']
    }


# __abstract__ causes declarative to skip the production of a table or mapper for the class entirely
class newbase(DeferredReflection, Base):
    __abstract__ = True


#Creating Base Classes

class ObjectGroup(newbase):
    __tablename__ = 'objectgroups'
    __table_args__ = table_args

    id = Column(INTEGER(unsigned=True), primary_key=True, autoincrement=True)
    name = Column(String(30), unique=True, nullable=False)
    parentobjectgroup_id = Column(INTEGER(unsigned=True), ForeignKey(id,onupdate="CASCADE", ondelete="RESTRICT"), nullable=False)
    created_at = Column(DATETIME, nullable=False)
    updated_at = Column(DATETIME, nullable=False)
    enabled = Column(BOOLEAN, nullable=False)

После этого я создаю движок:

self.clientconnection   = '%s://%s:%s@%s:%s/%s?charset=%s&use_unicode=0' % (self.dict_constants['sql_clientDB_driver'],
                                                                  self.dict_constants['sql_clientDB_user'], self.dict_constants['sql_clientDB_passwd'],
                                                                  host, port, db, self.dict_constants['sql_mainDB_collation'])
self.engine = create_engine(self.clientconnection, echo=False, pool_size=1, pool_timeout=30)

self.base = dbc.newbase

#opening several threads on the same time produces error in prepare, only one at a time

with sema_clientengine:
        try:
            self.base.prepare(self.engine)

пример запроса:

position_table = dbc.Position.__table__
position = alias(position_table, name='position', flat=True)
filter = and_(position.c.object_id == objectid, position.c.validpos == 1)
query = select([position]).where(filter).order_by(position.c.moment_id.desc()).limit(1)

Вот как я прочитал:

    with sema_reads:
        debug_starttime = time()
        try:
            self.engine.dispose()
            with self.engine.connect() as connection:
                proxyobject = connection.execute(query)

Хорошо, так что в основном у меня в одном экземпляре одна основная база данных, называемая smv, и для каждого клиента независимая БД.

Поэтому, когда я создаю движок и запускаю соединение в зависимости от класса, оно будетперейти к определенной схеме.Это прекрасно работает, я даже могу объединять базы данных.Теперь мне нужно поместить основную базу данных «smv» в другой экземпляр БД, чтобы я мог масштабироваться, и вот, когда все перестает работать, потому что общий движок подключается только к экземпляру клиентов, и теперь схема smv не существует.

Есть идеи?

Добавлено 2019-02-05:

Хорошо, после некоторого тестирования я могу заставить его работать с сессиями, обратите внимание, что таблица Company не просто находится в другой базе данных, чемОбъекты, находящиеся в другом экземпляре базы данных, с разными IP и портом:

config_1 = {
    "sqlalchemy.url": "%s://%s:%s@%s:%s/%s" % (dict_constants['sql_mainDB_driver'], dict_constants['sql_mainDB_user'],
                                                     dict_constants['sql_mainDB_passwd'], dict_constants['sql_mainDB_host'],
                                                     dict_constants['sql_mainDB_port'], dict_constants['sql_mainDB_name']),
    "sqlalchemy.echo": False,
}

config_2 = {
    "sqlalchemy.url": "%s://%s:%s@%s:3307/clientdb" % (dict_constants['sql_mainDB_driver'], dict_constants['sql_mainDB_user'],
                                                     dict_constants['sql_mainDB_passwd'], dict_constants['sql_mainDB_host']),
    "sqlalchemy.echo": False,
}

engine_1 = engine_from_config(config_1)
engine_2 = engine_from_config(config_2)

Base = declarative_base()
Base2 = declarative_base()

class Company(Base):
    __tablename__ = 'companies'


    id = Column(INTEGER(unsigned=True), primary_key=True)
    company = Column(String(255))
    db = Column(String(255))
    enabled = Column(BOOLEAN, nullable=False)

class Object(Base2):
    __tablename__ = 'objects'

    id = Column(INTEGER(unsigned=True), primary_key=True)
    name = Column(String(30), unique=True, nullable=False)
    objectgroup_id = Column(INTEGER(unsigned=True), nullable=False)
    objectaction_id = Column(SMALLINT(unsigned=True), nullable=False)
    created_at = Column(DATETIME, nullable=False)
    updated_at = Column(DATETIME, nullable=False)
    enabled = Column(BOOLEAN, nullable=False)


#session.configure(bind={Company:engine_1})

binds = {Base:engine_1, Base2:engine_2}

session = sessionmaker(binds=binds)
session = session()

print session.query(Company).all()

print session.query(Object).all()

Так что это работает, но мне нужно выполнять более сложные запросы, и для меня это лучше, но это работает только тогда, когда яуказать двигатель.Любой способ, которым сессия обнаруживает это автоматически в зависимости от класса таблицы?Также возможно ли выполнить объединение с таблицами из другого экземпляра базы данных?

company = alias(Company.__table__, name='company', flat=True)
query = select([Company]).order_by(company.c.company)
proxyobject = session.execute(query, bind=engine_1)

rows = proxyobject.fetchall()

print rows
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...