diff options
author | Sam Davies <seivadmas@gmail.com> | 2015-10-29 18:26:54 -0300 |
---|---|---|
committer | Sam Davies <seivadmas@gmail.com> | 2015-10-30 14:04:16 -0300 |
commit | 2c2a8755460ec3d32ece91c9766dbd0304ece028 (patch) | |
tree | 350a241e5ff5e07ad395455fe3d567dea70ede0f /railties/test | |
parent | 0174837bfa263c55cf727f23028d8f28da192d14 (diff) | |
download | rails-2c2a8755460ec3d32ece91c9766dbd0304ece028.tar.gz rails-2c2a8755460ec3d32ece91c9766dbd0304ece028.tar.bz2 rails-2c2a8755460ec3d32ece91c9766dbd0304ece028.zip |
Use advisory locks to prevent concurrent migrations
- Addresses issue #22092
- Works on Postgres and MySQL
- Uses advisory locks because of two important properties:
1. The can be obtained outside of the context of a transaction
2. They are automatically released when the session ends, so if a
migration process crashed for whatever reason the lock is not left
open perpetually
- Adds get_advisory_lock and release_advisory_lock methods to database
adapters
- Attempting to run a migration while another one is in process will
raise a ConcurrentMigrationError instead of attempting to run in
parallel with undefined behavior. This could be rescued and
the migration could exit cleanly instead. Perhaps as a configuration
option?
Technical Notes
==============
The Migrator uses generate_migrator_advisory_lock_key to build the key
for the lock. In order to be compatible across multiple adapters there
are some constraints on this key.
- Postgres limits us to 64 bit signed integers
- MySQL advisory locks are server-wide so we have to scope to the
database
- To fulfil these requirements we use a Migrator salt (a randomly
chosen signed integer with max length of 31 bits) that identifies
the Rails migration process as the owner of the lock. We multiply
this salt with a CRC32 unsigned integer hash of the database name to
get a signed 64 bit integer that can also be converted to a string
to act as a lock key in MySQL databases.
- It is important for subsequent versions of the Migrator to use the
same salt, otherwise different versions of the Migrator will not see
each other's locks.
Diffstat (limited to 'railties/test')
0 files changed, 0 insertions, 0 deletions