问题
I'm writing a SQLAlchemy app that needs to connect to a PostgreSQL database and a MySQL database. Basically I'm loading the data from an existing MySQL database, doing some transforms on it, and then saving it in PostgreSQL.
I am managing the PostgreSQL schema using SQLAlchemy's declarative base
. The MySQL database already exists, and I am accessing the schema via SQLAlchemy's reflection. Both have very different schemas.
I know I need dedicated engines
for each database, but I'm unclear on whether I need dedicated objects of any of the following:
Base
- I think this corresponds to the database schema. Since both databases have very different schemas, I will need a dedicatedBase
for each schema.Metadata
- Is this intended to be a single global metadata object that holds all schemas from all engines?Sessions
- I'm not sure, but I think I need separate sessions for each database? Or can a singlesession
share multipleengine
/Base
combos? I'm usingscoped_sessions
.
Part of my confusion comes from not understanding the difference between Base
and Metadata
. The SQLAlchemy docs say:
MetaData is a container object that keeps together many different features of a database (or multiple databases) being described.
This seems to imply that a single metadata
can hold multiple Base
's, but I'm still a bit fuzzy on how that works. For example, I want to be able to call metadata.create_all()
and create tables in PostgreSQL, but not MySQL.
回答1:
The short answer is that it's easiest to have separate instances of them all for both databases. It is possible to create a single routing session, but it has its caveats.
The sessionmaker
and Session
also support passing multiple binds as an argument and 2-phase commits, which can also allow using a single session with multiple databases. As luck would have it, the 2 databases that support 2-phase commits are PostgreSQL and MySQL.
About the relation between Base
and metadata
:
Base is a base class that has a metaclass used to declaratively create Table
objects from information provided in the class itself and its subclasses. All Table
objects implicitly declared by subclasses of Base
will share the same MetaData
.
You can provide metadata as an argument when creating a new declarative base and thus share it between multiple Base
s, but in your case it is not useful.
MetaData
is a collection of Table
objects and their associated schema constructs. It also can hold a binding to an Engine
or Session
.
In short, you can have Table
s and MetaData
without a Base
, but a Base
requires MetaData
to function.
来源:https://stackoverflow.com/questions/36342716/when-connecting-to-multiple-databases-do-i-need-multiple-sqlalchemy-metadata-b