Skip to content

ActiveRecord::ConcurrentMigrationError with departure on fresh rails 7.1.3.4 app #110

@krismichalski

Description

@krismichalski

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

  1. rails new departure_sample_rails_71_app -d mysql
  2. Add departure to Gemfile
  3. bundle install
  4. rails db:create
  5. rails g migration create_things
  6. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions