目录
数据库配置集中化管理:Python多数据库连接终极方案
摘要:本文将展示如何将MySQL连接配置抽象为公共常量,实现多数据库环境下的统一管理,彻底解决配置分散问题!
一、传统配置方式的痛点分析
当项目涉及多个数据库时,常见的不良实践:
# 文件1: user_dao.py
DB_CONFIG_USER = {
"host": "10.0.0.1",
"user": "app_user",
"password": "user_pwd",
"database": "user_db"
}
# 文件2: order_dao.py
DB_CONFIG_ORDER = {
"host": "10.0.0.2", # 配置不一致
"user": "app_order", # 用户名不同
"password": "order_pwd",
"database": "order_db"
}
# 文件3: report_service.py
DB_CONFIG_REPORT = {
"host": "10.0.0.3",
"user": "app_report",
"password": "report_pwd",
"database": "report_db"
}
这种方式的致命缺陷:
- 配置信息重复出现在多个文件中
- 密码等敏感信息难以统一管理
- 修改配置需全局搜索替换(易出错)
- 无法实现环境隔离(开发/测试/生产)
- 缺乏版本控制和审计能力
二、配置集中化管理方案设计
整体架构
项目根目录/
├── config/ # 配置中心
│ ├── __init__.py # 配置加载入口
│ ├── databases.py # 数据库配置定义
│ ├── dev_settings.py # 开发环境配置
│ ├── prod_settings.py # 生产环境配置
│ └── .env # 敏感信息存储
├── core/
│ └── db.py # 数据库连接封装
└── services/ # 业务服务
├── user_service.py
└── order_service.py
三、完整实现代码
1. 配置文件结构
# config/__init__.py
"""
配置加载中心 - 自动识别当前环境
"""
import os
# 自动识别运行环境
ENV = os.getenv("APP_ENV", "dev").lower()
if ENV == "prod":
from .prod_settings import *
else:
from .dev_settings import *
# config/databases.py
"""
数据库配置定义 - 支持多数据库实例
"""
from core.db import MySQLExecutor
# 数据库连接池配置模板
BASE_CONFIG = {
"pool_name": "mysql_pool",
"pool_size": 5,
"pool_reset_session": True,
"charset": "utf8mb4",
"autocommit": False
}
# 数据库实例定义
DATABASES = {
"USER_DB": {
"host": None, # 从环境变量获取
"port": 3306,
"user": None,
"password": None,
"database": "user_db"
},
"ORDER_DB": {
"host": None,
"port": 3306,
"user": None,
"password": None,
"database": "order_db"
},
"REPORT_DB": {
"host": None,
"port": 3307, # 不同端口
"user": None,
"password": None,
"database": "report_db"
}
}
# 数据库执行器实例缓存
_db_executors = {}
def get_db_executor(db_name: str) -> MySQLExecutor:
"""获取数据库执行器(单例模式)"""
if db_name not in _db_executors:
config = DATABASES[db_name].copy()
config.update(BASE_CONFIG)
_db_executors[db_name] = MySQLExecutor(config)
return _db_executors[db_name]
2. 环境特定配置
# config/dev_settings.py
"""
开发环境配置
"""
import os
from dotenv import load_dotenv
from .databases import DATABASES
# 加载.env文件中的环境变量
load_dotenv(".env.dev")
# 填充数据库配置
DATABASES["USER_DB"].update({
"host": os.getenv("DEV_USER_DB_HOST", "localhost"),
"user": os.getenv("DEV_USER_DB_USER"),
"password": os.getenv("DEV_USER_DB_PWD")
})
DATABASES["ORDER_DB"].update({
"host": os.getenv("DEV_ORDER_DB_HOST", "db-order.dev.com"),
"user": os.getenv("DEV_ORDER_DB_USER"),
"password": os.getenv("DEV_ORDER_DB_PWD")
})
DATABASES["REPORT_DB"].update({
"host": os.getenv("DEV_REPORT_DB_HOST", "db-report.dev.com"),
"user": os.getenv("DEV_REPORT_DB_USER"),
"password": os.getenv("DEV_REPORT_DB_PWD")
})
# config/prod_settings.py
"""
生产环境配置
"""
import os
from .databases import DATABASES
# 从系统环境变量获取(不依赖文件)
DATABASES["USER_DB"].update({
"host": os.environ["PROD_USER_DB_HOST"],
"user": os.environ["PROD_USER_DB_USER"],
"password": os.environ["PROD_USER_DB_PWD"]
})
DATABASES["ORDER_DB"].update({
"host": os.environ["PROD_ORDER_DB_HOST"],
"user": os.environ["PROD_ORDER_DB_USER"],
"password": os.environ["PROD_ORDER_DB_PWD"]
})
DATABASES["REPORT_DB"].update({
"host": os.environ["PROD_REPORT_DB_HOST"],
"user": os.environ["PROD_REPORT_DB_USER"],
"password": os.environ["PROD_REPORT_DB_PWD"]
})
3. 数据库连接封装(增强版)
# core/db.py
"""
增强版MySQL执行器 - 支持连接池和自动重连
"""
import mysql.connector
from mysql.connector import pooling, errorcode, Error
from typing import Union, List, Tuple, Dict, Any
class MySQLExecutor:
"""支持连接池的MySQL执行器"""
def __init__(self, config: Dict[str, Any]):
self.config = config
self.pool = self._create_pool()
def _create_pool(self) -> pooling.MySQLConnectionPool:
"""创建数据库连接池"""
try:
return pooling.MySQLConnectionPool(**self.config)
except Error as err:
if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
print("用户名或密码错误")
elif err.errno == errorcode.ER_BAD_DB_ERROR:
print("数据库不存在")
else:
print(f"连接池创建失败: {err}")
raise
def get_connection(self):
"""从连接池获取连接"""
return self.pool.get_connection()
def execute_query(
self,
sql: str,
params: Union[Tuple, List, None] = None,
dictionary: bool = True
) -> List[Dict]:
"""
执行查询语句(返回字典列表)
"""
try:
with self.get_connection() as conn:
with conn.cursor(dictionary=dictionary) as cursor:
cursor.execute(sql, params)
return cursor.fetchall()
except Error as e:
print(f"查询执行失败: {e}")
raise
def execute_command(
self,
sql: str,
params: Union[Tuple, List, None] = None,
commit: bool = True
) -> int:
"""
执行写操作
"""
try:
with self.get_connection() as conn:
with conn.cursor() as cursor:
cursor.execute(sql, params)
affected_rows = cursor.rowcount
if commit:
conn.commit()
return affected_rows
except Error as e:
conn.rollback()
print(f"操作执行失败: {e}")
raise
def execute_many(
self,
sql: str,
params_list: List[Union[Tuple, List]],
commit: bool = True
) -> int:
"""
批量执行操作(高效)
"""
try:
with self.get_connection() as conn:
with conn.cursor() as cursor:
cursor.executemany(sql, params_list)
affected_rows = cursor.rowcount
if commit:
conn.commit()
return affected_rows
except Error as e:
conn.rollback()
print(f"批量操作失败: {e}")
raise
四、业务层使用示例
用户服务模块
# services/user_service.py
from config import get_db_executor
class UserService:
def __init__(self):
# 获取用户数据库执行器
self.db = get_db_executor("USER_DB")
def get_user_by_id(self, user_id: int) -> dict:
sql = "SELECT * FROM users WHERE id = %s"
result = self.db.execute_query(sql, (user_id,))
return result[0] if result else None
def create_user(self, name: str, email: str) -> int:
sql = "INSERT INTO users (name, email) VALUES (%s, %s)"
return self.db.execute_command(sql, (name, email))
def batch_create_users(self, users: list):
"""批量创建用户(高效)"""
sql = "INSERT INTO users (name, email) VALUES (%s, %s)"
# 参数格式: [('张三', 'zhang@test.com'), ('李四', 'li@test.com')]
self.db.execute_many(sql, users)
订单服务模块
# services/order_service.py
from config import get_db_executor
class OrderService:
def __init__(self):
# 获取订单数据库执行器
self.db = get_db_executor("ORDER_DB")
def get_orders_by_user(self, user_id: int) -> list:
sql = """
SELECT o.order_id, o.amount, p.product_name
FROM orders o
JOIN products p ON o.product_id = p.id
WHERE o.user_id = %s
"""
return self.db.execute_query(sql, (user_id,))
def create_order(self, user_id: int, product_id: int, amount: float):
sql = "INSERT INTO orders (user_id, product_id, amount) VALUES (%s, %s, %s)"
return self.db.execute_command(sql, (user_id, product_id, amount))
五、环境配置与敏感信息管理
.env文件示例(开发环境)
# config/.env.dev
# 用户数据库配置
DEV_USER_DB_HOST=db-user.dev.com
DEV_USER_DB_USER=dev_user
DEV_USER_DB_PWD=dev123456
# 订单数据库配置
DEV_ORDER_DB_HOST=db-order.dev.com
DEV_ORDER_DB_USER=dev_order
DEV_ORDER_DB_PWD=order@dev
# 报表数据库配置
DEV_REPORT_DB_HOST=db-report.dev.com
DEV_REPORT_DB_USER=dev_report
DEV_REPORT_DB_PWD=report!dev
生产环境变量设置(Linux示例)
# 设置环境变量
export APP_ENV=prod
# 用户数据库
export PROD_USER_DB_HOST=cluster-user.prod.com
export PROD_USER_DB_USER=prod_user
export PROD_USER_DB_PWD=Pr0d@2023
# 订单数据库
export PROD_ORDER_DB_HOST=cluster-order.prod.com
export PROD_ORDER_DB_USER=prod_order
export PROD_ORDER_DB_PWD=0rder@Pr0d
# 报表数据库
export PROD_REPORT_DB_HOST=cluster-report.prod.com
export PROD_REPORT_DB_USER=prod_report
export PROD_REPORT_DB_PWD=R3port!Pr0d
六、方案优势与最佳实践
核心优势
- 集中化管理:所有数据库配置统一存放
- 环境隔离:开发/测试/生产环境无缝切换
- 敏感信息安全:密码不进代码库
- 连接复用:连接池减少开销
- 单例模式:避免重复创建连接
- 类型提示:提高代码可读性
最佳实践建议
-
严格的权限控制
# 按业务划分数据库账号权限 DATABASES["REPORT_DB"]["user"] = "readonly_user" # 只读账号 -
配置版本控制
- 将
.env.example纳入版本控制 - 将真实
.env加入.gitignore
- 将
-
配置加密存储
# 使用加密库解密配置 from cryptography.fernet import Fernet cipher = Fernet(os.getenv("CONFIG_KEY")) password = cipher.decrypt(encrypted_password).decode() -
连接健康检查
# 定期检查连接池状态 def check_pool_health(): for name, executor in _db_executors.items(): print(f"{name} 连接池: {executor.pool.pool_size}连接, " f"{len(executor.pool._cnx_queue)}空闲") -
多环境配置切换
# 启动脚本指定环境 APP_ENV=staging python app.py
七、高级扩展方案
1. 配置中心集成(Consul/Vault)
import consul
def load_config_from_consul():
"""从Consul配置中心加载配置"""
c = consul.Consul()
index, data = c.kv.get("databases/user_db", recurse=True)
return {item['Key']: item['Value'] for item in data}
2. 动态配置热更新
import threading
import time
def config_watcher():
"""监控配置变化并自动更新"""
while True:
new_config = load_remote_config()
if new_config != current_config:
update_executors(new_config)
time.sleep(60) # 每分钟检查一次
# 启动监控线程
threading.Thread(target=config_watcher, daemon=True).start()
3. 多类型数据库支持
# 统一数据库接口
class DatabaseExecutor(ABC):
@abstractmethod
def execute_query(self, sql, params=None):
pass
@abstractmethod
def execute_command(self, sql, params=None):
pass
# MySQL实现
class MySQLExecutor(DatabaseExecutor): ...
# PostgreSQL实现
class PostgresExecutor(DatabaseExecutor): ...
# SQLite实现
class SQLiteExecutor(DatabaseExecutor): ...
结语:通过配置集中化管理,我们不仅解决了多数据库环境下的配置分散问题,还实现了环境隔离、安全管控和资源优化。这套架构可轻松支撑从初创项目到企业级系统的平滑演进!
部署工具推荐:
- python-dotenv - 环境变量管理
- Consul - 分布式配置中心
- Vault - 企业级密钥管理
- SQLAlchemy - 多数据库ORM支持
安全警告:
- 永远不要将敏感信息提交到版本控制系统
- 生产环境禁用默认账号和弱密码
- 定期轮换数据库凭证
- 使用网络隔离限制数据库访问来源
关键词:
Python多数据库管理、MySQL配置集中化、环境变量最佳实践、数据库连接池、Python配置中心
4万+

被折叠的 条评论
为什么被折叠?



