6 ms·
Django zero-downtime migrations for Postgres that respect database locks
- etaioinshrdlu 8y agoIs there any equivalent for django+mysql? I historically found more tools for online schema changes in the mysql sphere, such as gh-ost ( https://github.com/github/gh-ost https://github.com/github/gh-ost )
- Doxin 8y agoI'm not even sure this is possible in mysql. Last time I checked mysql still couldn't do DDL statements in a transaction.
- lloeki 8y agoLast time I checked MySQL even silently commits out of the transaction and proceeds with the remainder of the queries. Here are the "implicit commit" statements: https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html
- fredley 8y agoIn Django it doesn't, it just dumps you out with a fucked-up semi-migration that takes you 20 minutes to get back to a consistent state...
- Doxin 8y agoHonestly I don't see a single good reason for any new project to use mysql over postgres. mysql is almost universally terrible at actually being a database.
- leowoo91 8y agoAfaik mysql migrations doesn't have transactions in Django.
- rantanplan 8y agogh-ost is hardly useful for anyone outside of github. It's predicated on the fact that you don't use foreign keys. Now why would someone use MySQL without FKs... is beyond me, but I'm sure they have their reasons. MySQL has this https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl.html https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl.ht... for Online Schema migration and MariaDB has ALTER ONLINE https://mariadb.com/kb/en/library/alter-table/ https://mariadb.com/kb/en/library/alter-table/ They both work with triggers + ghost tables, so they don't need transactions.
- orf 8y agoRails does not use foreign keys by default.
- rantanplan 8y agoWhat does "by default" mean? If you want to have referential integrity there's no other choice. Otherwise you create tables that have no relation to each other. No one stops you from doing this, but then you probably don't want an RDBMS in the first place.
- orf 8y agoRails by default does not add a foreign key constraint at the database level when defining a relationship[1]. And once you have a fairly large rails app that uses this default it's somewhat tricky to migrate. It's madness, I know. 1. https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_reference https://api.rubyonrails.org/classes/ActiveRecord/ConnectionA...
- rantanplan 8y agoWTF! Thanks for that tidbit, I have no XP with Rails, but I would never imagine they do something so atrocious.
- 8y ago
- StavrosK 8y agoSo basically what this does is avoid locking the database while migrating? Obviously (and the README mentions this) the two releases have to be backwards- and forwards-compatible, so with this backend you avoid locking for other processes while migrating. Very useful, especially for long migrations, but I would like to see a bit more detail about how this library achieves this, what the caveats are, etc. EDIT: Never mind, there's a comprehensive "how it works" section farther down, I just needed to scroll far enough. This is very useful.
- tbicr 8y agoI found only two caveats: - it doesn't use transactions, so if migration will down, then you will need to fix state manually (one point of improvement), however you cannot run `CREATE INDEX CONCURRENTLY` in transaction. - it can use `CHECK (column IS NOT NULL)` constraint for safe `NOT NULL` replacement for huge tables, that isn't compatible with standard django behavior. So all this cases highlighted in README.
- aidos 8y agoLooks like this handles a bunch of cases around locking you can run into, which seems a noble goal. I like the approach of making a matrix of all the migration operations and figuring out how to work around the locks, kudos. There are definitely some wonderful ways to mess things up when starting out with postgres migrations. Nothing quite like the surprise you get the first time you rewrite every tuple on a table with 20M rows because you added a column with a default value (no longer an issue with the latest postgres). As pointed out in the docs, your code must be prepared to support the schema both before and after the migration. Not that I use django anyway, but normally I'm more worried about the interlacing of the code and db changes to keep things running smoothy. Migrate a bit, release some code, migrate some more etc.
- orf 8y agoThere have been some messages on the development mailing list about adding support for create index concurrently when using Postgresql, which is a big pain point for larger migrations. It's a bit tricky as you cannot use it in a transaction though
- tbicr 8y agoConstraints creation also tricky because in transaction it take ACCESS EXCLUSIVE lock (eg. lock table on READ/WRITE) and spend time to constraint validation (CHECK, NOT NULL, FOREIGN KEY), so lock will be released only on transaction commit/rollback.
- bmdavi3 8y agoThis is cool. Another alternative would be to use postgres savepoints, which are like transactions inside transactions, as a wrapper around each migration. You can do the same thing - set lock_timeout and catch errors when those values are exceeded, and try the transaction again. Provide an option to run the handful of operations that can't be run inside a transaction as an escape hatch, and then you can retain the ability to run migrations inside transactions, which is usually a good thing.
- tbicr 8y agoUnfortunately savepoints live only in transaction and ACCESS EXCLUSIVE will be released only on whole transaction commit/rollback, so look like no benefits with savepoints for schema migrations to compare with plain transaction.
- crescentfresh 8y agoThis is amazing. My conundrum is we don't use Django lol. Wish this sort of thoroughness existed in standalone pg migration tooling.
- fredley 8y agoThis is indeed incredible. My conundrum is we don't use pg :-(
- ggregoire 8y agoSame here. Our backend team uses Python, SQLAlchemy and PG. They are looking for a tool to handle migrations and schema versionings. Any recommendations?
- aidos 8y agoAlembic. It's made by zzzeek (Mike Bayer), who created SQLA and it's hackable to do custom migrations. We use it by changing the models in code and then having Alembic automatically create a suitable migration for us. Then we change the migration as required (adding steps for data migrations etc). It's really simple: alembic revision --autogenerate -m 'changing something...' That generates a python file with an upgrade and downgrade function. You can then customise fully as you require. Then on the db server you can run: alembic upgrade head # or downgrade etc
- crescentfresh 8y agoWe use the "forward only" approach, and use a combination of .sql and .py migration scripts and use mschematool[1] to tie the room together. [1] https://github.com/aartur/mschematool https://github.com/aartur/mschematool
- rbanffy 8y agoThis is awesome. It's not a silver bullet and won't solve all case. You'll still need to design in degraded modes for your application for when parts of it become unusable (that's you should be doing anyway), but this covers a lot of your likely needs.