Published on

Django连接多个数据库

Authors
  • avatar
    Name
    Lif
    Twitter

初衷

为了让不同业务的数据分离,落到不同的库,使用django连接多个数据库。

设置

# settings.py
DATABASES = {
    "default": {},
    "users": {
        "NAME": "user_data",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "superS3cret",
    },
    "customers": {
        "NAME": "customer_data",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_cust",
        "PASSWORD": "veryPriv@ate",
    },
}
  • Django使用default数据库,如果没有其他选择
  • default可以没有,但是必须设置一个空字典

同步

设置多个数据库,需要同步多次。这里比较麻烦。

python3 manage.py
python manage.py migrate message。# 迁移到default库
python manage.py migrate message  --database=message_db

迁移将会把所有model的所有表镜像的迁移到两个库,自带的指令不要指望一次迁移所有model分表存储

Database Routing

class MessageRouter:
    """
    A router to control all database operations on models in the
    auth and contenttypes applications.
    """

    route_app_labels = { "message", "data"}
    

    def db_for_read(self, model, **hints):
        """
        Attempts to read auth and contenttypes models go to message_db.
        """


        if model._meta.app_label in self.route_app_labels:
            return "message_db"
            
            
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth and contenttypes models go to message_db.
        """
        if model._meta.app_label in self.route_app_labels:

            return "message_db"
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth or contenttypes apps is
        involved.
        """

        if (
            obj1._meta.app_label in self.route_app_labels
            or obj2._meta.app_label in self.route_app_labels
        ):
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth and contenttypes apps only appear in the
        'message_db' database.
        """
        if app_label in self.route_app_labels:

           
            return db == "message_db"
       
        return None

可以通过django的路径中间件来对数据库的读、写、迁移权限进行设置。 需要在settings.py中添加

DATABASE_ROUTERS = ["path.to.MessageRouter"]
# my instance is ["message.MessageRouter.MessageRouter"]

fake迁移

如果遇到不希望迁移到A库,但会一直提示的情况,可以使用fake迁移

py manage.py migrate  <app> --fake

总结

数据分库存储(也称为数据库分片或数据库分区)是一种将大型数据库分解为更小、更易于管理的组件(称为“分片”或“分区”)的策略。这种方法有多个潜在好处:

  1. 提高性能和响应时间 读写分离: 通过将读操作和写操作分配到不同的数据库或分片上,可以提高系统的吞吐量和响应时间。 并行处理: 分库允许多个查询和事务并行执行在不同的数据库或分片上,从而提高性能。
  2. 扩展性 水平扩展: 当数据量和访问量增加时,可以通过添加更多的数据库或分片来轻松扩展系统,而不是替换现有的硬件(这称为垂直扩展)。
  3. 简化备份和恢复 更快的备份: 小的数据库分片更容易和更快地备份。 局部恢复: 如果一个分片出现问题,你可以只恢复那个特定的分片,而不影响整个系统。
  4. 高可用性和故障转移 冗余: 数据可以在多个分片或数据库中进行冗余存储,从而提高数据的可用性。 故障隔离: 如果一个数据库或分片出现问题,它不会影响到其他分片,从而减少了故障的影响范围。
  5. 数据局部性 优化查询: 数据分片可以根据应用的访问模式来进行优化,例如,通过地理位置或时间来分片,从而提高查询性能。
  6. 管理和维护 分布式管理: 小的、分散的数据库通常更容易管理和维护。 版本控制和更新: 可以逐个更新或修改数据库分片,而不是一次性更新整个数据库。
  7. 成本效益 硬件成本: 通过使用分库,你可以在廉价的 commodity 硬件上分布式地存储和处理数据,而不是依赖单一、昂贵的高性能服务器。 尽管数据分库存储有很多好处,但它也带来了一些挑战,如数据一致性、复杂的查询和事务处理等。因此,在决定采用这种策略之前,需要仔细评估应用的需求和特点。

但是会比较麻烦,每次都要迁移两个数据库。