Module: Gitlab::Database

Defined in:
lib/gitlab/database.rb,
lib/gitlab/database/count.rb,
lib/gitlab/database/grant.rb,
lib/gitlab/database/metrics.rb,
lib/gitlab/database/pg_class.rb,
lib/gitlab/database/date_time.rb,
lib/gitlab/database/migration.rb,
lib/gitlab/database/pg_depend.rb,
lib/gitlab/database/reflection.rb,
lib/gitlab/database/reindexing.rb,
lib/gitlab/database/type/color.rb,
lib/gitlab/database/batch_count.rb,
lib/gitlab/database/bulk_update.rb,
lib/gitlab/database/consistency.rb,
lib/gitlab/database/partitioning.rb,
lib/gitlab/database/shared_model.rb,
lib/gitlab/database/async_indexes.rb,
lib/gitlab/database/batch_counter.rb,
lib/gitlab/database/each_database.rb,
lib/gitlab/database/gitlab_schema.rb,
lib/gitlab/database/health_status.rb,
lib/gitlab/database/sha_attribute.rb,
lib/gitlab/database/tables_locker.rb,
lib/gitlab/database/bump_sequences.rb,
lib/gitlab/database/load_balancing.rb,
lib/gitlab/database/postgres_index.rb,
lib/gitlab/database/query_analyzer.rb,
lib/gitlab/database/schema_cleaner.rb,
lib/gitlab/database/schema_helpers.rb,
lib/gitlab/database/tables_truncate.rb,
lib/gitlab/database/connection_timer.rb,
lib/gitlab/database/sha256_attribute.rb,
lib/gitlab/database/similarity_score.rb,
lib/gitlab/database/async_constraints.rb,
lib/gitlab/database/migration_helpers.rb,
lib/gitlab/database/migrations/runner.rb,
lib/gitlab/database/schema_migrations.rb,
lib/gitlab/database/type/json_pg_safe.rb,
lib/gitlab/database/with_lock_retries.rb,
lib/gitlab/database/gitlab_schema_info.rb,
lib/gitlab/database/loose_foreign_keys.rb,
lib/gitlab/database/postgres_partition.rb,
lib/gitlab/database/read_only_relation.rb,
lib/gitlab/database/consistency_checker.rb,
lib/gitlab/database/load_balancing/host.rb,
lib/gitlab/database/lock_writes_manager.rb,
lib/gitlab/database/migrations/squasher.rb,
lib/gitlab/database/postgres_constraint.rb,
lib/gitlab/database/transaction/context.rb,
lib/gitlab/database/as_with_materialized.rb,
lib/gitlab/database/health_status/logger.rb,
lib/gitlab/database/load_balancing/setup.rb,
lib/gitlab/database/migration_helpers/v2.rb,
lib/gitlab/database/migrations/observers.rb,
lib/gitlab/database/postgres_foreign_key.rb,
lib/gitlab/database/postgres_hll/buckets.rb,
lib/gitlab/database/query_analyzers/base.rb,
lib/gitlab/database/rename_table_helpers.rb,
lib/gitlab/database/transaction/observer.rb,
lib/gitlab/database/batch_average_counter.rb,
lib/gitlab/database/dynamic_model_helpers.rb,
lib/gitlab/database/health_status/context.rb,
lib/gitlab/database/health_status/signals.rb,
lib/gitlab/database/load_balancing/logger.rb,
lib/gitlab/database/type/symbolized_jsonb.rb,
lib/gitlab/database/load_balancing/session.rb,
lib/gitlab/database/migrations/observation.rb,
lib/gitlab/database/reindexing/coordinator.rb,
lib/gitlab/database/type/indifferent_jsonb.rb,
lib/gitlab/database/load_balancing/resolver.rb,
lib/gitlab/database/load_balancing/sticking.rb,
lib/gitlab/database/async_indexes/index_base.rb,
lib/gitlab/database/background_migration_job.rb,
lib/gitlab/database/database_connection_info.rb,
lib/gitlab/database/health_status/indicators.rb,
lib/gitlab/database/load_balancing/host_list.rb,
lib/gitlab/database/migrations/redis_helpers.rb,
lib/gitlab/database/obsolete_ignored_columns.rb,
lib/gitlab/database/reindexing/queued_action.rb,
lib/gitlab/database/migrations/pg_backend_pid.rb,
lib/gitlab/database/reindexing/reindex_action.rb,
lib/gitlab/database/schema_migrations/context.rb,
lib/gitlab/database/count/exact_count_strategy.rb,
lib/gitlab/database/migrations/instrumentation.rb,
lib/gitlab/database/migrations/sidekiq_helpers.rb,
lib/gitlab/database/migrations/timeout_helpers.rb,
lib/gitlab/database/partitioning/replace_table.rb,
lib/gitlab/database/postgres_partitioned_table.rb,
lib/gitlab/database/reindexing/index_selection.rb,
lib/gitlab/database/async_indexes/index_creator.rb,
lib/gitlab/database/load_balancing/primary_host.rb,
lib/gitlab/database/load_balancing/srv_resolver.rb,
lib/gitlab/database/migrations/lock_retry_mixin.rb,
lib/gitlab/database/partitioning/time_partition.rb,
lib/gitlab/database/reindexing/grafana_notifier.rb,
lib/gitlab/database/unidirectional_copy_trigger.rb,
lib/gitlab/database/async_constraints/validators.rb,
lib/gitlab/database/load_balancing/configuration.rb,
lib/gitlab/database/load_balancing/load_balancer.rb,
lib/gitlab/database/migrations/extension_helpers.rb,
lib/gitlab/database/postgres_autovacuum_activity.rb,
lib/gitlab/database/queue_error_handling_concern.rb,
lib/gitlab/database/schema_migrations/migrations.rb,
lib/gitlab/database/transaction_timeout_settings.rb,
lib/gitlab/database/x509_serial_number_attribute.rb,
lib/gitlab/database/partitioning/monthly_strategy.rb,
lib/gitlab/database/postgres_index_bloat_estimate.rb,
lib/gitlab/database/tables_sorted_by_foreign_keys.rb,
lib/gitlab/database/async_indexes/index_destructor.rb,
lib/gitlab/database/count/reltuples_count_strategy.rb,
lib/gitlab/database/load_balancing/rack_middleware.rb,
lib/gitlab/database/migrations/constraints_helpers.rb,
lib/gitlab/database/migrations/observers/query_log.rb,
lib/gitlab/database/partitioning/partition_manager.rb,
lib/gitlab/database/partitioning_migration_helpers.rb,
lib/gitlab/database/async_ddl_exclusive_lease_guard.rb,
lib/gitlab/database/async_indexes/migration_helpers.rb,
lib/gitlab/database/load_balancing/connection_proxy.rb,
lib/gitlab/database/migrations/lock_retries_helpers.rb,
lib/gitlab/database/partitioning/list/convert_table.rb,
lib/gitlab/database/reindexing/reindex_concurrently.rb,
lib/gitlab/database/schema_cache_with_renamed_table.rb,
lib/gitlab/database/background_migration/batched_job.rb,
lib/gitlab/database/count/tablesample_count_strategy.rb,
lib/gitlab/database/load_balancing/service_discovery.rb,
lib/gitlab/database/async_constraints/validators/base.rb,
lib/gitlab/database/health_status/indicators/wal_rate.rb,
lib/gitlab/database/migrations/base_background_runner.rb,
lib/gitlab/database/migrations/test_background_runner.rb,
lib/gitlab/database/partitioning/partition_monitoring.rb,
lib/gitlab/database/postgresql_adapter/type_map_cache.rb,
lib/gitlab/database/async_indexes/postgres_async_index.rb,
lib/gitlab/database/background_migration/batch_metrics.rb,
lib/gitlab/database/load_balancing/wal_tracking_sender.rb,
lib/gitlab/database/migrations/observers/batch_details.rb,
lib/gitlab/database/migrations/observers/query_details.rb,
lib/gitlab/database/partitioning/sliding_list_strategy.rb,
lib/gitlab/database/rename_reserved_paths_migration/v1.rb,
lib/gitlab/database/async_constraints/migration_helpers.rb,
lib/gitlab/database/migration_helpers/announce_database.rb,
lib/gitlab/database/migration_helpers/convert_to_bigint.rb,
lib/gitlab/database/postgres_hll/batch_distinct_counter.rb,
lib/gitlab/database/background_migration/batch_optimizer.rb,
lib/gitlab/database/load_balancing/wal_tracking_receiver.rb,
lib/gitlab/database/migrations/batched_migration_last_id.rb,
lib/gitlab/database/load_balancing/action_cable_callbacks.rb,
lib/gitlab/database/migrations/observers/query_statistics.rb,
lib/gitlab/database/partitioning/ci_sliding_list_strategy.rb,
lib/gitlab/database/with_lock_retries_outside_transaction.rb,
lib/gitlab/database/background_migration/batched_migration.rb,
lib/gitlab/database/health_status/indicators/patroni_apdex.rb,
lib/gitlab/database/migrations/runner_backoff/communicator.rb,
lib/gitlab/database/query_analyzers/gitlab_schemas_metrics.rb,
lib/gitlab/database/schema_validation/inconsistency_filter.rb,
lib/gitlab/database/background_migration/prometheus_metrics.rb,
lib/gitlab/database/convert_feature_category_to_group_label.rb,
lib/gitlab/database/migration_helpers/wraparound_autovacuum.rb,
lib/gitlab/database/migrations/background_migration_helpers.rb,
lib/gitlab/database/migrations/observers/migration_observer.rb,
lib/gitlab/database/partitioning/detached_partition_dropper.rb,
lib/gitlab/database/partitioning/list/locking_configuration.rb,
lib/gitlab/database/async_constraints/validators/foreign_key.rb,
lib/gitlab/database/health_status/indicators/write_ahead_log.rb,
lib/gitlab/database/load_balancing/service_discovery/sampler.rb,
lib/gitlab/database/load_balancing/sidekiq_client_middleware.rb,
lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb,
lib/gitlab/database/migration_helpers/restrict_gitlab_schema.rb,
lib/gitlab/database/partitioning_migration_helpers/bulk_copy.rb,
lib/gitlab/database/query_analyzers/restrict_allowed_schemas.rb,
lib/gitlab/database/migrations/observers/transaction_duration.rb,
lib/gitlab/database/migrations/reestablished_connection_stack.rb,
lib/gitlab/database/migrations/test_batched_background_runner.rb,
lib/gitlab/database/partitioning/single_numeric_list_partition.rb,
lib/gitlab/database/migration_helpers/loose_foreign_key_helpers.rb,
lib/gitlab/database/migration_helpers/wraparound_vacuum_helpers.rb,
lib/gitlab/database/migrations/runner_backoff/migration_helpers.rb,
lib/gitlab/database/query_analyzers/ci/partitioning_id_analyzer.rb,
lib/gitlab/database/background_migration/sub_batch_timeout_error.rb,
lib/gitlab/database/partitioning_migration_helpers/index_helpers.rb,
lib/gitlab/database/async_constraints/validators/check_constraint.rb,
lib/gitlab/database/background_migration/batched_migration_runner.rb,
lib/gitlab/database/migrations/runner_backoff/active_record_mixin.rb,
lib/gitlab/database/postgresql_adapter/dump_schema_versions_mixin.rb,
lib/gitlab/database/postgresql_adapter/force_disconnectable_mixin.rb,
lib/gitlab/database/background_migration/batched_migration_wrapper.rb,
lib/gitlab/database/migration_helpers/cascading_namespace_settings.rb,
lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb,
lib/gitlab/database/background_migration/batched_job_transition_log.rb,
lib/gitlab/database/migrations/batched_background_migration_helpers.rb,
lib/gitlab/database/migrations/observers/total_database_size_change.rb,
lib/gitlab/database/query_analyzers/ci/partitioning_routing_analyzer.rb,
lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb,
lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb,
lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection.rb,
lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb,
lib/gitlab/database/health_status/indicators/autovacuum_active_on_table.rb,
lib/gitlab/database/health_status/indicators/prometheus_alert_indicator.rb,
lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb,
lib/gitlab/database/postgresql_database_tasks/load_schema_versions_mixin.rb,
lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb,
lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb,
lib/gitlab/database/async_constraints/postgres_async_constraint_validation.rb,
lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb,
lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb

Defined Under Namespace

Modules: ActiveRecordBaseTransactionMetrics, AsyncConstraints, AsyncDdlExclusiveLeaseGuard, AsyncIndexes, BackgroundMigration, BatchCount, BulkUpdate, Count, DateTime, DynamicModelHelpers, EachDatabase, GitlabSchema, HealthStatus, LoadBalancing, LooseForeignKeys, MigrationHelpers, Migrations, Partitioning, PartitioningMigrationHelpers, PostgresHll, PostgresqlAdapter, PostgresqlDatabaseTasks, QueryAnalyzers, QueueErrorHandlingConcern, ReadOnlyRelation, RealTransactionContext, Reindexing, RenameReservedPathsMigration, RenameTableHelpers, SchemaCacheWithRenamedTable, SchemaHelpers, SchemaMigrations, SchemaValidation, Transaction, TransactionManagerContext, Type Classes: AsWithMaterialized, BackgroundMigrationJob, BatchAverageCounter, BatchCounter, BumpSequences, ConnectionTimer, Consistency, ConsistencyChecker, ConvertFeatureCategoryToGroupLabel, DatabaseConnectionInfo, GitlabSchemaInfo, Grant, LockWritesManager, Metrics, Migration, ObsoleteIgnoredColumns, PgClass, PgDepend, PgUser, PostgresAutovacuumActivity, PostgresConstraint, PostgresForeignKey, PostgresIndex, PostgresIndexBloatEstimate, PostgresPartition, PostgresPartitionedTable, QueryAnalyzer, Reflection, SchemaCleaner, Sha256Attribute, ShaAttribute, SharedModel, SimilarityScore, TablesLocker, TablesSortedByForeignKeys, TablesTruncate, TransactionTimeoutSettings, UnidirectionalCopyTrigger, WithLockRetries, WithLockRetriesOutsideTransaction, X509SerialNumberAttribute

Constant Summary collapse

MAIN_DATABASE_NAME =
'main'
CI_DATABASE_NAME =
'ci'
DEFAULT_POOL_HEADROOM =
10
TABLES_TO_BE_RENAMED =

This constant is used when renaming tables concurrently. If you plan to rename a table using the ‘rename_table_safely` method, add your table here one milestone before the rename. Example: TABLES_TO_BE_RENAMED =

'old_name' => 'new_name'

.freeze

{}.freeze
MINIMUM_POSTGRES_VERSION =

Minimum PostgreSQL version requirement per documentation: docs.gitlab.com/ee/install/requirements.html#postgresql-requirements

13
MAX_INT_VALUE =
2147483647
MIN_INT_VALUE =
-2147483648
MAX_TIMESTAMP_VALUE =

The max value between MySQL’s TIMESTAMP and PostgreSQL’s timestampz: www.postgresql.org/docs/9.1/static/datatype-datetime.html dev.mysql.com/doc/refman/5.7/en/datetime.html FIXME: this should just be the max value of timestampz

Time.at((1 << 31) - 1).freeze
MAX_TEXT_SIZE_LIMIT =

The maximum number of characters for text fields, to avoid DoS attacks via parsing huge text fields gitlab.com/gitlab-org/gitlab-foss/issues/61974

1_000_000
MIN_SCHEMA_GITLAB_VERSION =

Migrations before this version may have been removed

'15.11'
DYNAMIC_PARTITIONS_SCHEMA =

Schema we store dynamically managed partitions in (e.g. for time partitioning)

:gitlab_partitions_dynamic
STATIC_PARTITIONS_SCHEMA =

Schema we store static partitions in (e.g. for hash partitioning)

:gitlab_partitions_static
EXTRA_SCHEMAS =

This is an extensive list of postgres schemas owned by GitLab It does not include the default public schema

[DYNAMIC_PARTITIONS_SCHEMA, STATIC_PARTITIONS_SCHEMA].freeze
PRIMARY_DATABASE_NAME =

rubocop:disable Database/MultipleDatabases

ActiveRecord::Base.connection_db_config.name.to_sym
FULLY_QUALIFIED_IDENTIFIER =
/^\w+\.\w+$/
MODE_SINGLE_DATABASE =

Database Modes

"single-database"
MODE_SINGLE_DATABASE_CI_CONNECTION =
"single-database-ci-connection"
MODE_MULTIPLE_DATABASES =
"multiple-databases"
BINARY_TYPE =

PostgreSQL defines its own class with slightly different behaviour from the default Binary type.

ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Bytea

Class Method Summary collapse

Class Method Details

.add_post_migrate_path_to_rails(force: false) ⇒ Object



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/gitlab/database.rb', line 220

def self.add_post_migrate_path_to_rails(force: false)
  return if ENV['SKIP_POST_DEPLOYMENT_MIGRATIONS'] && !force

  Rails.application.config.paths['db'].each do |db_path|
    path = Rails.root.join(db_path, 'post_migrate').to_s

    next if Rails.application.config.paths['db/migrate'].include? path

    Rails.application.config.paths['db/migrate'] << path

    # Rails memoizes migrations at certain points where it won't read the above
    # path just yet. As such we must also update the following list of paths.
    ActiveRecord::Migrator.migrations_paths << path
  end
end

.all_database_connection_filesObject



57
58
59
# File 'lib/gitlab/database.rb', line 57

def self.all_database_connection_files
  Dir.glob(Rails.root.join("db/database_connections/*.yaml"))
end

.all_database_connectionsObject



65
66
67
68
69
70
71
72
# File 'lib/gitlab/database.rb', line 65

def self.all_database_connections
  @all_database_connections ||=
    all_database_connection_files
      .map { |file| DatabaseConnectionInfo.load_file(file) }
      .sort_by(&:order)
      .index_by(&:name)
      .with_indifferent_access.freeze
end

.all_database_namesObject



74
75
76
# File 'lib/gitlab/database.rb', line 74

def self.all_database_names
  all_database_connections.keys.map(&:to_s)
end

.all_gitlab_schema_filesObject



61
62
63
# File 'lib/gitlab/database.rb', line 61

def self.all_gitlab_schema_files
  Dir.glob(Rails.root.join("db/gitlab_schemas/*.yaml"))
end

.all_gitlab_schemasObject



78
79
80
81
82
83
84
# File 'lib/gitlab/database.rb', line 78

def self.all_gitlab_schemas
  @all_gitlab_schemas ||=
    all_gitlab_schema_files
      .map { |file| GitlabSchemaInfo.load_file(file) }
      .index_by(&:name)
      .with_indifferent_access.freeze
end

.all_uncached(&block) ⇒ Object



204
205
206
207
208
209
210
211
212
# File 'lib/gitlab/database.rb', line 204

def self.all_uncached(&block)
  # Calls to #uncached only disable caching for the current connection. Since the load balancer
  # can potentially upgrade from read to read-write mode (using a different connection), we specify
  # up-front that we'll explicitly use the primary for the duration of the operation.
  Gitlab::Database::LoadBalancing::Session.current.use_primary do
    base_models = database_base_models_using_load_balancing.values
    base_models.reduce(block) { |blk, model| -> { model.uncached(&blk) } }.call
  end
end

.allow_cross_joins_across_databases(url:) ⇒ Object



214
215
216
217
218
# File 'lib/gitlab/database.rb', line 214

def self.allow_cross_joins_across_databases(url:)
  # this method is implemented in:
  # spec/support/database/prevent_cross_joins.rb
  yield
end

.check_for_non_superuserObject

rubocop: disable CodeReuse/ActiveRecord



174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/gitlab/database.rb', line 174

def self.check_for_non_superuser
  user = PgUser.find_by('usename = CURRENT_USER')
  am_i_superuser = user.usesuper

  Gitlab::AppLogger.info(
    "Account details: User: \"#{user.usename}\", UseSuper: (#{am_i_superuser})"
  )

  raise 'Error: detected superuser' if am_i_superuser
rescue ActiveRecord::StatementInvalid
  raise 'User CURRENT_USER not found'
end

.database_base_modelsObject



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/gitlab/database.rb', line 86

def self.database_base_models
  # Note that we use ActiveRecord::Base here and not ApplicationRecord.
  # This is deliberate, as we also use these classes to apply load
  # balancing to, and the load balancer must be enabled for _all_ models
  # that inherit from ActiveRecord::Base; not just our own models that
  # inherit from ApplicationRecord.
  @database_base_models ||=
    all_database_connections
      .transform_values(&:connection_class)
      .compact.with_indifferent_access.freeze
end

.database_base_models_using_load_balancingObject

This returns a list of databases whose connection supports database load balancing. We can’t reuse the database_base_models since not all connections do support load balancing.



111
112
113
114
115
116
117
# File 'lib/gitlab/database.rb', line 111

def self.database_base_models_using_load_balancing
  @database_base_models_using_load_balancing ||=
    all_database_connections
      .select { |_, db| db.uses_load_balancing? }
      .transform_values(&:connection_class)
      .compact.with_indifferent_access.freeze
end

.database_base_models_with_gitlab_sharedObject

This returns a list of databases that contains all the gitlab_shared schema tables.



100
101
102
103
104
105
106
# File 'lib/gitlab/database.rb', line 100

def self.database_base_models_with_gitlab_shared
  @database_base_models_with_gitlab_shared ||=
    all_database_connections
      .select { |_, db| db.has_gitlab_shared? }
      .transform_values(&:connection_class)
      .compact.with_indifferent_access.freeze
end

.database_modeObject



158
159
160
161
162
163
164
165
166
# File 'lib/gitlab/database.rb', line 158

def self.database_mode
  if !has_config?(CI_DATABASE_NAME)
    MODE_SINGLE_DATABASE
  elsif has_database?(CI_DATABASE_NAME)
    MODE_MULTIPLE_DATABASES
  else
    MODE_SINGLE_DATABASE_CI_CONNECTION
  end
end

.db_config_for_connection(connection) ⇒ Object



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/gitlab/database.rb', line 271

def self.db_config_for_connection(connection)
  return unless connection

  # For a ConnectionProxy we want to avoid ambiguous db_config as it may
  # sometimes default to replica so we always return the primary config
  # instead.
  if connection.is_a?(::Gitlab::Database::LoadBalancing::ConnectionProxy)
    return connection.load_balancer.configuration.db_config
  end

  # During application init we might receive `NullPool`
  return unless connection.respond_to?(:pool) &&
    connection.pool.respond_to?(:db_config)

  connection.pool.db_config
end

.db_config_name(connection) ⇒ Object

At the moment, the connection can only be retrieved by Gitlab::Database::LoadBalancer#read or #read_write or from the ActiveRecord directly. Therefore, if the load balancer doesn’t recognize the connection, this method returns the primary role directly. In future, we may need to check for other sources. Expected returned names: main, main_replica, ci, ci_replica, unknown



295
296
297
298
# File 'lib/gitlab/database.rb', line 295

def self.db_config_name(connection)
  db_config = db_config_for_connection(connection)
  db_config&.name || 'unknown'
end

.db_config_names(with_schema:) ⇒ Object



236
237
238
239
240
241
242
243
244
245
246
# File 'lib/gitlab/database.rb', line 236

def self.db_config_names(with_schema:)
  db_config_names = ::ActiveRecord::Base.configurations
    .configs_for(env_name: Rails.env).map(&:name)
  return db_config_names unless with_schema

  schema_models = schemas_to_base_models.fetch(with_schema)
  db_config_names.select do |db_config_name|
    db_info = all_database_connections.fetch(db_config_name)
    schema_models.include?(db_info.connection_class)
  end
end

.db_config_share_with(db_config) ⇒ Object

If the ‘database_tasks: false` is being used, return the expected fallback database for this database configuration



302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/gitlab/database.rb', line 302

def self.db_config_share_with(db_config)
  # no sharing
  return if db_config.database_tasks?

  database_connection_info = all_database_connections[db_config.name]

  if database_connection_info
    database_connection_info.fallback_database&.to_s
  else
    # legacy behaviour
    'main'
  end
end

.default_pool_sizeObject

We configure the database connection pool size automatically based on the configured concurrency. We also add some headroom, to make sure we don’t run out of connections when more threads besides the ‘user-facing’ ones are running.

Read more about this in doc/development/database/client_side_connection_pool.md



138
139
140
141
142
143
# File 'lib/gitlab/database.rb', line 138

def self.default_pool_size
  headroom =
    (ENV["DB_POOL_HEADROOM"].presence || DEFAULT_POOL_HEADROOM).to_i

  Gitlab::Runtime.max_threads + headroom
end

.false_valueObject



196
197
198
# File 'lib/gitlab/database.rb', line 196

def self.false_value
  "'f'"
end

.gitlab_schemas_for_connection(connection) ⇒ Object

This returns all matching schemas that a given connection can use Since the ‘ActiveRecord::Base` might change the connection (from main to ci) This does not look at literal connection names, but rather compares models that are holders for a given db_config_name



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/gitlab/database.rb', line 252

def self.gitlab_schemas_for_connection(connection)
  db_config = self.db_config_for_connection(connection)

  # connection might not be yet adopted (returning NullPool, and no connection_klass)
  # in such cases it is fine to ignore such connections
  return unless db_config

  db_config_name = db_config.name.delete_suffix(LoadBalancing::LoadBalancer::REPLICA_SUFFIX)
  primary_model = self.database_base_models.fetch(db_config_name.to_sym)

  self.schemas_to_base_models.select do |_, child_models|
    child_models.any? do |child_model|
      child_model == primary_model || \
        # The model might indicate a child connection, ensure that this is enclosed in a `db_config`
        self.database_base_models[self.db_config_share_with(child_model.connection_db_config)] == primary_model
    end
  end.keys.map!(&:to_sym)
end

.has_config?(database_name) ⇒ Boolean

Database configured. Returns true even if the database is shared

Returns:

  • (Boolean)


146
147
148
149
150
# File 'lib/gitlab/database.rb', line 146

def self.has_config?(database_name)
  ActiveRecord::Base.configurations
    .configs_for(env_name: Rails.env, name: database_name.to_s, include_hidden: true)
    .present?
end

.has_database?(database_name) ⇒ Boolean

Database configured. Returns false if the database is shared

Returns:

  • (Boolean)


153
154
155
156
# File 'lib/gitlab/database.rb', line 153

def self.has_database?(database_name)
  db_config = ::Gitlab::Database.database_base_models[database_name]&.connection_db_config
  db_config.present? && db_config_share_with(db_config).nil?
end

.install_transaction_context_patches!Object



337
338
339
340
341
342
# File 'lib/gitlab/database.rb', line 337

def self.install_transaction_context_patches!
  ActiveRecord::ConnectionAdapters::TransactionManager
    .prepend(TransactionManagerContext)
  ActiveRecord::ConnectionAdapters::RealTransaction
    .prepend(RealTransactionContext)
end

.install_transaction_metrics_patches!Object

Monkeypatch rails with upgraded database observability



333
334
335
# File 'lib/gitlab/database.rb', line 333

def self.install_transaction_metrics_patches!
  ActiveRecord::Base.prepend(ActiveRecordBaseTransactionMetrics)
end

.randomObject

rubocop: enable CodeReuse/ActiveRecord



188
189
190
# File 'lib/gitlab/database.rb', line 188

def self.random
  "RANDOM()"
end

.read_minimum_migration_versionObject

Determines minimum viable migration version, determined by the timestamp of the earliest migration file.



326
327
328
329
330
# File 'lib/gitlab/database.rb', line 326

def self.read_minimum_migration_version
  Dir.open(
    Rails.root.join('db/migrate')
  ).filter_map { |f| /\A\d{14}/.match(f)&.to_s }.map(&:to_i).min
end

.read_only?Boolean

Returns:

  • (Boolean)


316
317
318
# File 'lib/gitlab/database.rb', line 316

def self.read_only?
  false
end

.read_write?Boolean

Returns:

  • (Boolean)


320
321
322
# File 'lib/gitlab/database.rb', line 320

def self.read_write?
  !read_only?
end

.sanitize_timestamp(timestamp) ⇒ Object



200
201
202
# File 'lib/gitlab/database.rb', line 200

def self.sanitize_timestamp(timestamp)
  MAX_TIMESTAMP_VALUE > timestamp ? timestamp : MAX_TIMESTAMP_VALUE.dup
end

.schemas_to_base_modelsObject

This returns a list of base models with connection associated for a given gitlab_schema



120
121
122
123
124
125
126
127
128
129
# File 'lib/gitlab/database.rb', line 120

def self.schemas_to_base_models
  @schemas_to_base_models ||=
    all_gitlab_schemas.transform_values do |schema|
      all_database_connections
        .values
        .select { |db| db.gitlab_schemas.include?(schema.name) }
        .filter_map { |db| db.connection_class_or_fallback(all_database_connections) }
        .uniq
    end.compact.with_indifferent_access.freeze
end

.true_valueObject



192
193
194
# File 'lib/gitlab/database.rb', line 192

def self.true_value
  "'t'"
end