-
Notifications
You must be signed in to change notification settings - Fork 56
Description
I'm getting ActiveRecord::ConcurrentMigrationError: Failed to release advisory lock
on fresh rails 7.1.3.4 app.
╰─ rails db:migrate
Including for_alter statements
== 20240612095004 CreateThings: migrating =====================================
-- create_table(:things)
-> 0.0076s
== 20240612095004 CreateThings: migrated (0.0076s) ============================
bin/rails aborted!
ActiveRecord::ConcurrentMigrationError: (ActiveRecord::ConcurrentMigrationError)
Failed to release advisory lock
Tasks: TOP => db:migrate
(See full trace by running task with --trace
Environment
macOS Sonoma 14.4.1
mySQL 8.0.34 for macos13 on arm64
pt-online-schema-change 3.5.5
ruby 3.2.2
rails 7.1.3.4
departure 6.7.0
Steps to reproduce
rails new departure_sample_rails_71_app -d mysql
- Add
departure
toGemfile
bundle install
rails db:create
rails g migration create_things
rails db:migrate
There will be an error, but changes in database will appear - it's possible to do rails db:rollback
which reverts the changes and produces the same error.
Additional notes
There was a similar issue in the past for rails 5.2.0 - #31 - and reverting the fix for that issue (#32) fixes the problem for rails 7.1.3.4.
After adding:
config/initializers/departure_connection_base_overwrite.rb
module Departure
class ConnectionBase < ActiveRecord::Base
def self.establish_connection(config = nil)
super
end
end
class OriginalAdapterConnection < ConnectionBase; end
end
rails db:migrate
works without issue.
The problem is in this rails method: https://github.com/rails/rails/blob/v7.1.3.4/activerecord/lib/active_record/migration.rb#L1594
def with_advisory_lock
lock_id = generate_migrator_advisory_lock_id
got_lock = connection.get_advisory_lock(lock_id)
raise ConcurrentMigrationError unless got_lock
load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
yield
ensure
if got_lock && !connection.release_advisory_lock(lock_id)
raise ConcurrentMigrationError.new(
ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
)
end
end
In rails 7.0.8.4 connection.instance_variable_get(:@config)[:adapter]
returns mysql2
before and after yield
.
In rails 7.1.3.4 connection.instance_variable_get(:@config)[:adapter]
returns mysql2
before yield
and percona
after.
Here are the logs from log/development.log
during the migration:
(0.1ms) SELECT GET_LOCK('2327322385476548145', 0)
ActiveRecord::SchemaMigration Load (0.2ms) SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
ActiveRecord::InternalMetadata Load (0.6ms) SELECT * FROM `ar_internal_metadata` WHERE `ar_internal_metadata`.`key` = 'environment' ORDER BY `ar_internal_metadata`.`key` ASC LIMIT 1
Migrating to CreateThings (20240612095004)
(0.2ms) SET NAMES utf8mb4, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.wait_timeout = 2147483
(0.1ms) SET NAMES utf8mb4, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.wait_timeout = 2147483
(6.2ms) CREATE TABLE `things` (`id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, `created_at` datetime(6) NOT NULL)
(8.2ms) CREATE TABLE `things` (`id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, `created_at` datetime(6) NOT NULL)
ActiveRecord::SchemaMigration Create (0.5ms) INSERT INTO `schema_migrations` (`version`) VALUES ('20240612095004')
(0.4ms) SELECT RELEASE_LOCK('2327322385476548145')
(1.3ms) SELECT RELEASE_LOCK('2327322385476548145')
at some point the SQL commands are duplicated and I believe that the second RELEASE_LOCK
fails and causes the error to be raised.