Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/database/partitioning')
-rw-r--r--lib/gitlab/database/partitioning/monthly_strategy.rb4
-rw-r--r--lib/gitlab/database/partitioning/partition_manager.rb13
-rw-r--r--lib/gitlab/database/partitioning/sliding_list_strategy.rb53
3 files changed, 60 insertions, 10 deletions
diff --git a/lib/gitlab/database/partitioning/monthly_strategy.rb b/lib/gitlab/database/partitioning/monthly_strategy.rb
index 9c8cccb3dc6..0f08a47d754 100644
--- a/lib/gitlab/database/partitioning/monthly_strategy.rb
+++ b/lib/gitlab/database/partitioning/monthly_strategy.rb
@@ -40,6 +40,10 @@ module Gitlab
# No-op, required by the partition manager
end
+ def validate_and_fix
+ # No-op, required by the partition manager
+ end
+
private
def desired_partitions
diff --git a/lib/gitlab/database/partitioning/partition_manager.rb b/lib/gitlab/database/partitioning/partition_manager.rb
index 3ee9a193b45..aac91eaadb1 100644
--- a/lib/gitlab/database/partitioning/partition_manager.rb
+++ b/lib/gitlab/database/partitioning/partition_manager.rb
@@ -22,15 +22,13 @@ module Gitlab
connection_name: @connection_name
)
- # Double-checking before getting the lease:
- # The prevailing situation is no missing partitions and no extra partitions
- return if missing_partitions.empty? && extra_partitions.empty?
-
only_with_exclusive_lease(model, lease_key: MANAGEMENT_LEASE_KEY) do
- partitions_to_create = missing_partitions
- create(partitions_to_create) unless partitions_to_create.empty?
+ model.partitioning_strategy.validate_and_fix
+ partitions_to_create = missing_partitions
partitions_to_detach = extra_partitions
+
+ create(partitions_to_create) unless partitions_to_create.empty?
detach(partitions_to_detach) unless partitions_to_detach.empty?
end
rescue StandardError => e
@@ -119,7 +117,8 @@ module Gitlab
parent_table_identifier = "#{connection.current_schema}.#{partition.table}"
if (example_fk = PostgresForeignKey.by_referenced_table_identifier(parent_table_identifier).first)
- raise UnsafeToDetachPartitionError, "Cannot detach #{partition.partition_name}, it would block while checking foreign key #{example_fk.name} on #{example_fk.constrained_table_identifier}"
+ raise UnsafeToDetachPartitionError, "Cannot detach #{partition.partition_name}, it would block while " \
+ "checking foreign key #{example_fk.name} on #{example_fk.constrained_table_identifier}"
end
end
diff --git a/lib/gitlab/database/partitioning/sliding_list_strategy.rb b/lib/gitlab/database/partitioning/sliding_list_strategy.rb
index e9865fb91d6..5cf32d3272c 100644
--- a/lib/gitlab/database/partitioning/sliding_list_strategy.rb
+++ b/lib/gitlab/database/partitioning/sliding_list_strategy.rb
@@ -48,9 +48,12 @@ module Gitlab
default_value = current_default_value
if extra.any? { |p| p.value == default_value }
- Gitlab::AppLogger.error(message: "Inconsistent partition detected: partition with value #{current_default_value} should not be deleted because it's used as the default value.",
- partition_number: current_default_value,
- table_name: model.table_name)
+ Gitlab::AppLogger.error(
+ message: "Inconsistent partition detected: partition with value #{current_default_value} should " \
+ "not be deleted because it's used as the default value.",
+ partition_number: current_default_value,
+ table_name: model.table_name
+ )
extra = extra.reject { |p| p.value == default_value }
end
@@ -73,6 +76,42 @@ module Gitlab
current_partitions.empty?
end
+ def validate_and_fix
+ return unless Feature.enabled?(:fix_sliding_list_partitioning)
+ return if no_partitions_exist?
+
+ old_default_value = current_default_value
+ expected_default_value = active_partition.value
+
+ if old_default_value != expected_default_value
+ with_lock_retries do
+ model.connection.execute("LOCK TABLE #{model.table_name} IN ACCESS EXCLUSIVE MODE")
+
+ old_default_value = current_default_value
+ expected_default_value = active_partition.value
+
+ if old_default_value == expected_default_value
+ Gitlab::AppLogger.warn(
+ message: "Table partitions or partition key default value have been changed by another process",
+ table_name: table_name,
+ default_value: expected_default_value
+ )
+ raise ActiveRecord::Rollback
+ end
+
+ model.connection.change_column_default(model.table_name, partitioning_key, expected_default_value)
+ Gitlab::AppLogger.warn(
+ message: "Fixed default value of sliding_list_strategy partitioning_key",
+ column: partitioning_key,
+ table_name: table_name,
+ connection_name: model.connection.pool.db_config.name,
+ old_value: old_default_value,
+ new_value: expected_default_value
+ )
+ end
+ end
+ end
+
private
def current_default_value
@@ -95,6 +134,14 @@ module Gitlab
raise "Add #{partitioning_key} to #{model.name}.ignored_columns to use it with SlidingListStrategy"
end
end
+
+ def with_lock_retries(&block)
+ Gitlab::Database::WithLockRetries.new(
+ klass: self.class,
+ logger: Gitlab::AppLogger,
+ connection: model.connection
+ ).run(&block)
+ end
end
end
end