diff options
8 files changed, 75 insertions, 4 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index f6a6aa05a9..71dcecd346 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,13 @@ +* Add database configuration to disable advisory locks. + + ``` + production: + adapter: postgresql + advisory_locks: false + ``` + + *Guo Xiang* + * SQLite3 adapter `alter_table` method restores foreign keys. *Yasuo Honda* diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index a4748dbeda..529d099e16 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -77,7 +77,14 @@ module ActiveRecord SIMPLE_INT = /\A\d+\z/ attr_accessor :visitor, :pool - attr_reader :schema_cache, :owner, :logger, :prepared_statements, :lock + + attr_reader :schema_cache, + :owner, + :logger, + :prepared_statements, + :lock, + :advisory_locks + alias :in_use? :owner def self.type_cast_config_to_integer(config) @@ -119,6 +126,10 @@ module ActiveRecord else @prepared_statements = false end + + @advisory_locks_enabled = self.class.type_cast_config_to_boolean( + config.fetch(:advisory_locks, true) + ) end def migrations_paths # :nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 9de8242a58..9ff76435a1 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -111,7 +111,7 @@ module ActiveRecord end def supports_advisory_locks? - true + @advisory_locks_enabled end def get_advisory_lock(lock_name, timeout = 0) # :nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index fdf6f75108..4802a87c6a 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -298,7 +298,7 @@ module ActiveRecord end def supports_advisory_locks? - true + @advisory_locks_enabled end def supports_explain? diff --git a/activerecord/test/cases/adapters/helpers/test_supports_advisory_locks.rb b/activerecord/test/cases/adapters/helpers/test_supports_advisory_locks.rb new file mode 100644 index 0000000000..4905e17725 --- /dev/null +++ b/activerecord/test/cases/adapters/helpers/test_supports_advisory_locks.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require "support/connection_helper" + +module TestSupportsAdvisoryLocks + include ConnectionHelper + + def test_supports_advisory_locks? + assert ActiveRecord::Base.connection.supports_advisory_locks? + + run_without_connection do |orig_connection| + ActiveRecord::Base.establish_connection( + orig_connection.merge(advisory_locks: false) + ) + + assert_not ActiveRecord::Base.connection.supports_advisory_locks? + + ActiveRecord::Base.establish_connection( + orig_connection.merge(advisory_locks: true) + ) + + assert ActiveRecord::Base.connection.supports_advisory_locks? + end + end +end diff --git a/activerecord/test/cases/adapters/mysql2/test_advisory_locks_disabled_test.rb b/activerecord/test/cases/adapters/mysql2/test_advisory_locks_disabled_test.rb new file mode 100644 index 0000000000..4857900820 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/test_advisory_locks_disabled_test.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require "cases/helper" +require "cases/adapters/helpers/test_supports_advisory_locks" + +class Mysql2AdvisoryLocksDisabledTest < ActiveRecord::Mysql2TestCase + include TestSupportsAdvisoryLocks +end diff --git a/activerecord/test/cases/adapters/postgresql/advisory_locks_disabled_test.rb b/activerecord/test/cases/adapters/postgresql/advisory_locks_disabled_test.rb new file mode 100644 index 0000000000..f14e9baeb9 --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/advisory_locks_disabled_test.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require "cases/helper" +require "cases/adapters/helpers/test_supports_advisory_locks" + +class PostgresqlAdvisoryLocksDisabledTest < ActiveRecord::PostgreSQLTestCase + include TestSupportsAdvisoryLocks +end diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 6e4f1f9648..36882fec3f 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -989,6 +989,14 @@ development: If your development database has a root user with an empty password, this configuration should work for you. Otherwise, change the username and password in the `development` section as appropriate. +Advisory Locks are enabled by default on MySQL and are used to make database migrations concurrent safe. You can disable advisory locks by setting `advisory_locks` to `false`: + +```yaml +production: + adapter: mysql2 + advisory_locks: false +``` + #### Configuring a PostgreSQL Database If you choose to use PostgreSQL, your `config/database.yml` will be customized to use PostgreSQL databases: @@ -1001,12 +1009,13 @@ development: pool: 5 ``` -Prepared Statements are enabled by default on PostgreSQL. You can disable prepared statements by setting `prepared_statements` to `false`: +By default Active Record uses database features like prepared statements and advisory locks. You might need to disable those features if you're using an external connection pooler like PgBouncer: ```yaml production: adapter: postgresql prepared_statements: false + advisory_locks: false ``` If enabled, Active Record will create up to `1000` prepared statements per database connection by default. To modify this behavior you can set `statement_limit` to a different value: |