It can be quite fiddly to support zero-downtime DB migrations in Django. 
For example see 
https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html for tricks 
in Postgres; I'll refer to MySQL herein.

In general the sequence is to first upgrade the DB schema to the new 
version, while keeping the old version of the application running. This 
works if the DB fields have a `DEFAULT NULL`, or if strict mode is not 
enabled; in either case omitted fields are defaulted to NULL or the 
implicit default, respectively  (under MySQL).

However it seems that manual SQL must be written in order to support adding 
fields that aren't nullable; since Django's ORM drops the DB-level default 
when the field is not nullable, there's a window after the schema 
migration, but before the application code has been upgraded, where the 
old-version code could try to write a None to the DB, while the new-version 
DB schema doesn't support it.

For example, a NullBooleanField(default=None) produces this SQL:

`bool_field` tinyint(1) DEFAULT NULL,

Whereas a BooleanField(default=False) (or NullBooleanField with a default) 
produces:

`bool_field` tinyint(1),

This is the same for the other field types I've investigated; Django 
explicitly removes the default from the DB when migrating from a Nullable 
Field to a non-Nullable one.

In MySQL using non-strict mode, this would often go unnoticed (since MySQL 
coerces NULL to the implicit default in that case), but under strict mode 
is recommended, that option is not available (per 
https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html).

Achieving zero-downtime migrations would be much easier if the default 
value was set in the DB; is there a reason that Django does not do this? 
Even if this was an optional flag which only worked for literal values 
(i.e. not functions), it would seem to be a very useful feature. (e.g. 
`Field(set_default_in_db=True)`).

Indeed it seems to me that (based on the paucity of articles/documentation 
around hitless DB migrations) currently most Django users are likely 
incurring brief outages every time they perform a migration (perhaps 
without realizing it), whereas if DB-level defaults were the default 
behaviour, writing hitless DB migrations would require a lot less thought.

I'm sure there's been discussion of this before, so apologies in advance 
for being unable to locate that thread; I'd be interested in any thoughts 
around this.

Cheers,
Paul

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/3581b394-2d16-485b-a836-8e28c1983470%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to