Django中的动态数据库路由

时间:2014-03-12 19:43:56

标签: database django sharding

在我的数据库中,我在我的数据库中定义了一个Customer表,其他所有表都是外键控制的。

class Customer(models.Model):
    ...

class TableA(models.Model):
    Customer = models.ForeignKey(Customer)
    ...

class TableB(models.Model):
    Customer = models.ForeignKey(Customer)
    ...

我正在尝试实现一个数据库路由器,它根据Customer表的主键确定要连接的数据库。例如,1到100范围内的id将连接到数据库A,101 - 200范围内的id将连接到数据库B.

我已经阅读了routers上的Django文档,但我不确定我所问的是否可行。具体而言,方法db_for_read(model, **hints)db_for_write(model, **hints)适用于对象的类型。这对我来说没用,因为我需要基于对象实例的内容进行路由。该文档进一步指出,此时提供的唯一**hints是适用的instance对象,在某些情况下根本不提供instance。这并不能让我充满信心,因为它没有明确说明没有提供instance时的情况。

我实际上是在尝试实现数据库的应用程序级分片。这在Django中是否可行?

1 个答案:

答案 0 :(得分:1)

解决鸡肉和鸡蛋

在保存新客户时,您必须解决鸡和蛋的问题。您必须保存以获取ID,但您必须知道ID才能知道保存位置。

您可以先通过保存DatabaseA中的所有客户来解决这个问题,然后检查ID并将其保存在目标数据库中。见Django multidb: write to multiple databases。如果你这样做,你就不会遇到these problems。但请务必注意deleting客户。

然后使用**提示路由

如果提示中有instance,那么剩下的路由问题非常简单。要么 是客户,那么您将返回' DatabaseA'或客户,您将决定其customer_id或customer.id。

试着记住,没有勺子。

如果提示中没有实例,但它是您应用中的模型,则引发错误,以便您可以更改创建Queryset的代码。当它们没有自动添加时,您应该始终提供提示。

什么才能真正烘焙你的饼干

如果对于大多数查询,您都知道客户,这没关系。但请考虑像TableA.objects.filter(customer__name__startswith='foo')

这样的查询