【AI总结】python连接MySQL(3)- 数据库配置集中化管理:Python多数据库连接终极方案

数据库配置集中化管理: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"
}

这种方式的致命缺陷

  1. 配置信息重复出现在多个文件中
  2. 密码等敏感信息难以统一管理
  3. 修改配置需全局搜索替换(易出错)
  4. 无法实现环境隔离(开发/测试/生产)
  5. 缺乏版本控制和审计能力

二、配置集中化管理方案设计

整体架构

项目根目录/
├── 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

六、方案优势与最佳实践

核心优势

  1. 集中化管理:所有数据库配置统一存放
  2. 环境隔离:开发/测试/生产环境无缝切换
  3. 敏感信息安全:密码不进代码库
  4. 连接复用:连接池减少开销
  5. 单例模式:避免重复创建连接
  6. 类型提示:提高代码可读性

最佳实践建议

  1. 严格的权限控制

    # 按业务划分数据库账号权限
    DATABASES["REPORT_DB"]["user"] = "readonly_user"  # 只读账号
    
  2. 配置版本控制

    • .env.example纳入版本控制
    • 将真实.env加入.gitignore
  3. 配置加密存储

    # 使用加密库解密配置
    from cryptography.fernet import Fernet
    
    cipher = Fernet(os.getenv("CONFIG_KEY"))
    password = cipher.decrypt(encrypted_password).decode()
    
  4. 连接健康检查

    # 定期检查连接池状态
    def check_pool_health():
        for name, executor in _db_executors.items():
            print(f"{name} 连接池: {executor.pool.pool_size}连接, "
                  f"{len(executor.pool._cnx_queue)}空闲")
    
  5. 多环境配置切换

    # 启动脚本指定环境
    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多数据库管理MySQL配置集中化环境变量最佳实践数据库连接池Python配置中心

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

荔枝吻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值