在Django项目中配置多个数据库是处理复杂业务场景(如读写分离、多租户架构或数据隔离)的常见需求,以下为通过数据库路由实现多数据库配置的完整方案及最佳实践示例。
1、主从数据库读写分离
2、垂直拆分不同业务模块数据
3、跨数据库数据聚合分析
4、多租户系统隔离存储
5、对接遗留数据库系统
1. 修改settings.py配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'primary_db', 'USER': 'admin', 'PASSWORD': 'securepass123', 'HOST': '127.0.0.1', 'PORT': '5432', }, 'products_db': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'product_data', 'USER': 'app_user', 'PASSWORD': 'mysqlpass456', 'HOST': 'db.product.com', 'PORT': '3306', }, 'logs_db': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'logs.db', } }
2. 创建数据库路由类
database_routers.py class ModelBasedRouter: def db_for_read(self, model, **hints): if model._meta.app_label == 'products': return 'products_db' elif model._meta.app_label == 'logger': return 'logs_db' return None def db_for_write(self, model, **hints): if model._meta.app_label == 'products': return 'products_db' return 'default' def allow_relation(self, obj1, obj2, **hints): db_set = {'default', 'products_db'} if obj1._state.db in db_set and obj2._state.db in db_set: return True return None def allow_migrate(self, db, app_label, model_name=None, **hints): if app_label == 'products': return db == 'products_db' elif app_label == 'logger': return db == 'logs_db' return db == 'default'
3. 激活路由配置
DATABASE_ROUTERS = ['project.database_routers.ModelBasedRouter']
1. 手动选择数据库
显式指定数据库 User.objects.using('default').all() Product.objects.using('products_db').filter(active=True) 保存到特定数据库 new_user = User(name='test') new_user.save(using='default')
2. 多数据库迁移操作
迁移默认数据库 python manage.py migrate 迁移指定数据库 python manage.py migrate --database=products_db python manage.py migrate --database=logs_db
3. 事务管理
from django.db import transaction with transaction.atomic(using='products_db'): # 产品相关原子操作 product.stock -= 1 product.save()
1、跨数据库关系:Django ORM不支持跨数据库的外键关系
2、事务一致性:不同数据库的事务相互独立,需自行实现分布式事务
3、性能监控:建议使用Django Debug Toolbar进行查询分析
4、连接管理:合理配置CONN_MAX_AGE优化连接池
5、测试环境:使用TEST
配置项定义测试数据库
1、为只读数据库配置'OPTIONS': {'read_default_file': '/path/to/my.cnf'}
2、对分析型数据库启用连接池
3、使用select_for_update(using='default')
处理写后读一致性
4、定期清理多数据库连接
5、实现数据库健康检查中间件
> 引用说明:本文实现方案参考Django官方文档[Database Routers](https://docs.djangoproject.com/en/4.2/topics/db/multi-db/)章节,并经过生产环境验证,测试环境建议使用Django 4.2+版本,不同版本可能存在配置差异。