ScheduleBackfillPushRulesIdInProjects fails if there are multiple rows in application_settings
On my local instance that installed the latest nightly build, I just tried running gitlab-rake db:migrate
, and it failed due to the migration introduced in !28286 (merged):
# sudo gitlab-rake db:migrate
== 20200204113225 ScheduleRecalculateProjectAuthorizationsThirdRun: migrating =
-- Scheduling RecalculateProjectAuthorizationsWithMinMaxUserId jobs
== 20200204113225 ScheduleRecalculateProjectAuthorizationsThirdRun: migrated (0.2954s)
== 20200325104755 AddPushRulesIdToProjectSettings: migrating ==================
-- add_column(:project_settings, :push_rule_id, :bigint)
-> 0.0355s
== 20200325104755 AddPushRulesIdToProjectSettings: migrated (0.0864s) =========
== 20200325104756 AddPushRulesForeignKeyToProjectSettings: migrating ==========
-- transaction_open?()
-> 0.0000s
-- index_exists?(:project_settings, :push_rule_id, {:unique=>true, :algorithm=>:concurrently})
-> 0.0069s
-- execute("SET statement_timeout TO 0")
-> 0.0007s
-- add_index(:project_settings, :push_rule_id, {:unique=>true, :algorithm=>:concurrently})
-> 0.1125s
-- execute("RESET ALL")
-> 0.0010s
-- transaction_open?()
-> 0.0000s
-- foreign_keys(:project_settings)
-> 0.0456s
-- execute("ALTER TABLE project_settings\nADD CONSTRAINT fk_413a953e20\nFOREIGN KEY (push_rule_id)\nREFERENCES push_rules (id)\nON DELETE CASCADE\nNOT VALID;\n")
-> 0.1017s
-- execute("SET statement_timeout TO 0")
-> 0.0007s
-- execute("ALTER TABLE project_settings VALIDATE CONSTRAINT fk_413a953e20;")
-> 0.0703s
-- execute("RESET ALL")
-> 0.0009s
== 20200325104756 AddPushRulesForeignKeyToProjectSettings: migrated (0.3489s) =
== 20200325104833 AddPushRulesIdToApplicationSettings: migrating ==============
-- add_column(:application_settings, :push_rule_id, :bigint)
-> 0.0017s
== 20200325104833 AddPushRulesIdToApplicationSettings: migrated (0.0042s) =====
== 20200325104834 AddPushRulesForeignKeyToApplicationSettings: migrating ======
-- transaction_open?()
-> 0.0000s
-- index_exists?(:application_settings, :push_rule_id, {:unique=>true, :algorithm=>:concurrently})
-> 0.0065s
-- execute("SET statement_timeout TO 0")
-> 0.0005s
-- add_index(:application_settings, :push_rule_id, {:unique=>true, :algorithm=>:concurrently})
-> 0.0130s
-- execute("RESET ALL")
-> 0.0005s
-- transaction_open?()
-> 0.0000s
-- foreign_keys(:application_settings)
-> 0.0060s
-- execute("ALTER TABLE application_settings\nADD CONSTRAINT fk_693b8795e4\nFOREIGN KEY (push_rule_id)\nREFERENCES push_rules (id)\nON DELETE SET NULL\nNOT VALID;\n")
-> 0.0107s
-- execute("SET statement_timeout TO 0")
-> 0.0007s
-- execute("ALTER TABLE application_settings VALIDATE CONSTRAINT fk_693b8795e4;")
-> 0.0035s
-- execute("RESET ALL")
-> 0.0006s
== 20200325104834 AddPushRulesForeignKeyToApplicationSettings: migrated (0.0474s)
== 20200325111432 AddIssuesCreateLimitToApplicationSettings: migrating ========
-- add_column(:application_settings, :issues_create_limit, :integer, {:default=>300, :null=>false})
-> 0.0091s
== 20200325111432 AddIssuesCreateLimitToApplicationSettings: migrated (0.0093s)
== 20200325162730 ScheduleBackfillPushRulesIdInProjects: migrating ============
-- execute("UPDATE application_settings SET push_rule_id = 9")
rake aborted!
StandardError: An error has occurred, all later migrations canceled:
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_application_settings_on_push_rule_id"
DETAIL: Key (push_rule_id)=(9) already exists.
/opt/gitlab/embedded/service/gitlab-rails/db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb:21:in `up'
/opt/gitlab/embedded/bin/bundle:23:in `load'
/opt/gitlab/embedded/bin/bundle:23:in `<main>'
Caused by:
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_application_settings_on_push_rule_id"
DETAIL: Key (push_rule_id)=(9) already exists.
/opt/gitlab/embedded/service/gitlab-rails/db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb:21:in `up'
/opt/gitlab/embedded/bin/bundle:23:in `load'
/opt/gitlab/embedded/bin/bundle:23:in `<main>'
Caused by:
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_application_settings_on_push_rule_id"
DETAIL: Key (push_rule_id)=(9) already exists.
/opt/gitlab/embedded/service/gitlab-rails/db/post_migrate/20200325162730_schedule_backfill_push_rules_id_in_projects.rb:21:in `up'
/opt/gitlab/embedded/bin/bundle:23:in `load'
/opt/gitlab/embedded/bin/bundle:23:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
This looks like it happens if the instance happens to have duplicate application_settings
. This happened long ago when we had a bug where multiple application_settings
were inserted.
gitlabhq_production=> select id, push_rule_id, created_at, updated_at from application_settings order by id;
id | push_rule_id | created_at | updated_at
----+--------------+----------------------------+----------------------------
1 | | 2017-02-06 20:49:09.216214 | 2019-12-09 21:37:29.287837
2 | | 2017-02-06 20:49:09.254403 | 2019-12-09 21:37:29.291537
3 | | 2017-02-06 20:49:09.372803 | 2019-12-09 21:37:29.297227
4 | | 2017-02-06 20:49:09.4092 | 2019-12-09 21:37:29.294251
5 | | 2017-02-06 20:49:09.519043 | 2020-03-26 17:25:50.787984
(5 rows)
Before, it wasn't a big deal since we always took the latest id
, but now that we are actually depending on this table to have one row, the unique index is failing.
dev.gitlab.org also has this problem:
gitlabhq_production=> select id, created_at, updated_at from application_settings order by id;
id | created_at | updated_at
----+----------------------------+----------------------------
1 | 2015-01-09 03:00:45.55412 | 2019-12-04 03:22:32.425003
2 | 2017-07-07 09:42:24.30994 | 2019-12-04 03:22:32.401102
3 | 2017-07-07 09:42:24.598087 | 2019-12-04 03:22:32.40349
4 | 2017-07-07 09:42:24.800332 | 2019-12-04 03:22:32.405854
5 | 2017-07-07 09:42:25.2129 | 2019-12-04 03:22:32.389287
6 | 2017-07-07 09:42:25.223187 | 2019-12-04 03:22:32.413069
7 | 2017-07-07 09:44:22.13386 | 2019-12-04 03:22:32.415555
8 | 2017-07-07 09:44:22.150257 | 2019-12-04 03:22:32.3674
9 | 2017-07-07 09:44:22.280643 | 2019-12-04 03:22:32.417921
10 | 2017-07-07 09:44:22.399299 | 2019-12-04 03:22:32.420296
11 | 2017-07-07 09:44:23.028125 | 2019-12-04 03:22:32.391625
12 | 2017-07-07 09:44:23.098763 | 2019-12-04 03:22:32.408206
13 | 2017-07-08 09:48:36.270305 | 2019-12-04 03:22:32.369904
14 | 2017-07-08 09:48:36.370462 | 2019-12-04 03:22:32.410581
15 | 2017-07-08 09:48:36.88248 | 2019-12-04 03:22:32.379547
16 | 2017-07-08 09:48:36.970432 | 2019-12-04 03:22:32.37225
17 | 2017-07-08 12:24:20.00659 | 2019-12-04 03:22:32.364074
18 | 2017-07-08 12:24:20.226801 | 2019-12-04 03:22:32.393988
19 | 2017-07-08 12:24:20.227876 | 2019-12-04 03:22:32.374616
20 | 2017-07-08 12:24:20.542347 | 2019-12-04 03:22:32.382088
21 | 2017-07-08 12:24:20.859801 | 2019-12-04 03:22:32.377013
22 | 2017-07-08 13:03:35.820201 | 2019-12-04 03:22:32.384526
23 | 2017-07-08 13:03:35.948099 | 2019-12-04 03:22:32.396392
24 | 2017-07-08 13:03:36.053212 | 2019-12-04 03:22:32.42266
25 | 2017-07-08 13:03:36.13958 | 2019-12-04 03:22:32.386914
26 | 2017-07-08 13:03:36.187089 | 2019-12-04 03:22:32.398749
27 | 2017-07-08 13:03:36.460217 | 2019-12-04 03:22:32.427465
(27 rows)
I think to fix this problem we might want to drop all other rows except the max(id)
.
/cc: @mksionek, @jprovaznik
Edited by Stan Hu