我的MySQL服务器上有几个数据库实例,我想创建一个小库来处理它们。所有DB都具有相同的结构 - 具有相同列的相同表。我使用SQLAlchemy来处理这个DB,但是我不能同时使用一个引擎来建立与多个DB的连接。那么,让我们举一个例子:
+----------+
| Database |
+----------+
| DB1 |
| DB2 |
| DB3 |
| DB4 |
+----------+
所有这些都有结构:
+----------------+
| Tables_in_DB_N |
+----------------+
| table_1 |
| table_2 |
| table_3 |
+----------------+
所以,我有一个想法,使用装饰器来创建引擎和Session
类:
Session = None
def decor(func, user=USERNAME, passw=PASSWORD, host=HOSTNAME, port=POST, db=DB):
def real_decor(func):
def wrapper(*args, **kwargs):
engine = create_engine('mysql+mysqlconnector://{user}:{passw}@{host}:{port}/{db}'.format(user=user, passw=passw, host=host, port=port, db=db))
global Session
Session = sessionmaker(bind=engine)
return func(*args, **kwargs)
return wrapper
return real_decor
和使用此装饰器示例的函数:
@decor(db='DB1')
def get_db1_table1_values():
session = Session()
values = session.query(Table1).all()
session.close()
return values
此解决方案有效。我真的不喜欢用global Session
破解...所以,还有其他方法可以做这个功能吗?
这是一个有趣的问题,如果不了解应用程序的生命周期,很难找到适合您用例的解决方案,但这是一次尝试:
def another_decor(user=USERNAME, passw=PASSWORD, host=HOSTNAME, port=PORT, db=DB):
def real_decor(func):
def wrapper(*args, **kwargs):
engine = create_engine('mysql+mysqlconnector://{user}:{passw}@{host}:{port}/{db}'.format(user=user, passw=passw, host=host, port=port, db=db))
session = sessionmaker(bind=engine)
return func(session, *args, **kwargs)
return wrapper
return real_decor
使用这个装饰器,它会将会话直接注入调用函数,并避免使用global
关键字。这样做需要像下面这样定义数据库访问功能:
@another_decor(db='three')
def get_three_table1_values(session):
session = session()
query = session.query(Table1).all()
session.close()
return query
使用它自己的Engine
和Session
来装饰每个数据库访问函数,这取决于SQLAlchemy如何管理其数据库连接,可能很容易耗尽与数据库的连接。
MySQL通常在内存中运行,基于SQLAlchemys documentation我认为它将汇集连接。所以这种用法可能没问题。