citusdata / django-multitenant

Python/Django support for distributed multi-tenant databases like Postgres+Citus
MIT License
712 stars 117 forks source link

Objects with same id cannot be stored in database for two different Tenants #38

Closed divick closed 5 years ago

divick commented 5 years ago

Since the id is created automatically by Django's ORM and sets it to be primary_key, even if we have

 class Product(TenantModelMixin, models.Model):
    store = models.ForeignKey(Store)
    tenant_id='store_id'
    name = models.CharField(max_length=255)
    description = models.TextField()

    class Meta(object):
        unique_together = ["id", "store"]

Another store with same id cannot be created, assuming the id is not autoadd. Ideally the primary key should be set as composite one with (id, store_id). I am aware though that composite primary key support is still not there in Django as it breaks a lot of other things like admin where the lookup is primarily based on id only.

It is not clear then in the docs that why having unique_together on id, store is needed, if id is anyways a primary key.

louiseGrandjonc commented 5 years ago

Hi @divick,

so this library is primarily meant to be used with a distributed postgres database. It should also work with a single node postgres.

In citus, when we distribute a table (split it in smaller tables on multiple workers), we have to change the primary key to be a composite primary key with (store_id, id). So you are right, the primary key should be composite :) As you say composite primary key are tricky, because of the admin and also because of the views urls like for example /products/id.

The documentation has to be updated :), thank you for your feedback.

Having unique constraint with the tenant_id column is necessary in a distributed postgresql setup. As each shard is a table, and are distributed on different workers, unique constraints need to include the column to avoid slow writes (we don't want to have to check all the shards on all the workers :) )

If you want more information on this here is the documentation of citus: https://docs.citusdata.com/en/v8.1/