Skip to content

Finalize conversion to bigint for push_event_payloads (take 2)

What does this MR do?

This MR is same as !64577 (merged), which change had to be reverted with !65112 (merged) in order to prevent problems with self-managed on 14.1.

Now we want to do this in 14.2.

On a high level, the operation takes the following steps:

  1. Ensure the migration of event_id to event_id_convert_to_bigint is completed.
  2. Copy indexes and FKs
  3. Swap columns

Cleanup (removing the old int columns and the triggers) will be done once events table conversion is also finalized. This leaves us with a trigger that copy values from bigint column to integer column, but this works fine, as long we do not hit the limit for integer.

Related to #288005 (closed).

Before merging

  • Announce in #g_delivery channeel on Slack that there is a post-deployment migration which will take approx. 132 minutes (probably less on production) introduced with this MR.

Database migrations

Timing

From !64577 (merged):

This is approximately matching what the migrations testing pipeline reports - 132 min (7917.6 s).

The above times are from DB Lab, from the production logs when !65112 (merged) was deployed to production we can see that the index creation took ~18 minutes, and the FK validation took ~14 minutes.

Up

$ bundle exec rails db:migrate:up VERSION=20210709024048
== 20210709024048 FinalizePushEventPayloadsBigintConversion2: migrating =======
-- transaction_open?()
   -> 0.0000s
-- index_exists?("push_event_payloads", :event_id_convert_to_bigint, {:unique=>true, :name=>"index_push_event_payloads_on_event_id_convert_to_bigint", :algorithm=>:concurrently})
   -> 0.0024s
-- execute("SET statement_timeout TO 0")
   -> 0.0008s
-- add_index("push_event_payloads", :event_id_convert_to_bigint, {:unique=>true, :name=>"index_push_event_payloads_on_event_id_convert_to_bigint", :algorithm=>:concurrently})
   -> 0.0147s
-- execute("RESET ALL")
   -> 0.0007s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("push_event_payloads")
   -> 0.0042s
-- execute("ALTER TABLE push_event_payloads\nADD CONSTRAINT fk_a5e47ac4c5\nFOREIGN KEY (event_id_convert_to_bigint)\nREFERENCES events (id)\nON DELETE CASCADE\nNOT VALID;\n")
   -> 0.0084s
-- execute("ALTER TABLE push_event_payloads VALIDATE CONSTRAINT fk_a5e47ac4c5;")
   -> 0.0116s
-- execute("LOCK TABLE push_event_payloads, events IN ACCESS EXCLUSIVE MODE")
   -> 0.0008s
-- quote_table_name("push_event_payloads")
   -> 0.0000s
-- quote_column_name(:event_id)
   -> 0.0000s
-- quote_column_name("event_id_tmp")
   -> 0.0000s
-- execute("ALTER TABLE \"push_event_payloads\" RENAME COLUMN \"event_id\" TO \"event_id_tmp\"")
   -> 0.0008s
-- quote_table_name("push_event_payloads")
   -> 0.0000s
-- quote_column_name(:event_id_convert_to_bigint)
   -> 0.0000s
-- quote_column_name(:event_id)
   -> 0.0000s
-- execute("ALTER TABLE \"push_event_payloads\" RENAME COLUMN \"event_id_convert_to_bigint\" TO \"event_id\"")
   -> 0.0011s
-- quote_table_name("push_event_payloads")
   -> 0.0000s
-- quote_column_name("event_id_tmp")
   -> 0.0000s
-- quote_column_name(:event_id_convert_to_bigint)
   -> 0.0000s
-- execute("ALTER TABLE \"push_event_payloads\" RENAME COLUMN \"event_id_tmp\" TO \"event_id_convert_to_bigint\"")
   -> 0.0007s
-- quote_table_name("trigger_07c94931164e")
   -> 0.0000s
-- execute("ALTER FUNCTION \"trigger_07c94931164e\" RESET ALL")
   -> 0.0008s
-- change_column_default("push_event_payloads", :event_id, nil)
   -> 0.0043s
-- change_column_default("push_event_payloads", :event_id_convert_to_bigint, 0)
   -> 0.0032s
-- execute("ALTER TABLE push_event_payloads DROP CONSTRAINT push_event_payloads_pkey")
   -> 0.0009s
-- rename_index("push_event_payloads", "index_push_event_payloads_on_event_id_convert_to_bigint", "push_event_payloads_pkey")
   -> 0.0008s
-- execute("ALTER TABLE push_event_payloads ADD CONSTRAINT push_event_payloads_pkey PRIMARY KEY USING INDEX push_event_payloads_pkey")
   -> 0.0012s
-- remove_foreign_key("push_event_payloads", {:name=>"fk_36c74129da"})
   -> 0.0039s
-- quote_table_name("push_event_payloads")
   -> 0.0000s
-- quote_column_name("fk_a5e47ac4c5")
   -> 0.0000s
-- quote_column_name("fk_36c74129da")
   -> 0.0000s
-- execute("ALTER TABLE \"push_event_payloads\"\nRENAME CONSTRAINT \"fk_a5e47ac4c5\" TO \"fk_36c74129da\"\n")
   -> 0.0011s
== 20210709024048 FinalizePushEventPayloadsBigintConversion2: migrated (0.0990s) 

Down

$ bundle exec rails db:migrate:down VERSION=20210709024048
== 20210709024048 FinalizePushEventPayloadsBigintConversion2: reverting =======
-- transaction_open?()
   -> 0.0000s
-- index_exists?("push_event_payloads", :event_id_convert_to_bigint, {:unique=>true, :name=>"index_push_event_payloads_on_event_id_convert_to_bigint", :algorithm=>:concurrently})
   -> 0.0018s
-- execute("SET statement_timeout TO 0")
   -> 0.0006s
-- add_index("push_event_payloads", :event_id_convert_to_bigint, {:unique=>true, :name=>"index_push_event_payloads_on_event_id_convert_to_bigint", :algorithm=>:concurrently})
   -> 0.0038s
-- execute("RESET ALL")
   -> 0.0006s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("push_event_payloads")
   -> 0.0037s
-- execute("ALTER TABLE push_event_payloads\nADD CONSTRAINT fk_a5e47ac4c5\nFOREIGN KEY (event_id_convert_to_bigint)\nREFERENCES events (id)\nON DELETE CASCADE\nNOT VALID;\n")
   -> 0.0025s
-- execute("ALTER TABLE push_event_payloads VALIDATE CONSTRAINT fk_a5e47ac4c5;")
   -> 0.0032s
-- execute("LOCK TABLE push_event_payloads, events IN ACCESS EXCLUSIVE MODE")
   -> 0.0007s
-- quote_table_name("push_event_payloads")
   -> 0.0000s
-- quote_column_name(:event_id)
   -> 0.0000s
-- quote_column_name("event_id_tmp")
   -> 0.0000s
-- execute("ALTER TABLE \"push_event_payloads\" RENAME COLUMN \"event_id\" TO \"event_id_tmp\"")
   -> 0.0009s
-- quote_table_name("push_event_payloads")
   -> 0.0000s
-- quote_column_name(:event_id_convert_to_bigint)
   -> 0.0000s
-- quote_column_name(:event_id)
   -> 0.0000s
-- execute("ALTER TABLE \"push_event_payloads\" RENAME COLUMN \"event_id_convert_to_bigint\" TO \"event_id\"")
   -> 0.0008s
-- quote_table_name("push_event_payloads")
   -> 0.0000s
-- quote_column_name("event_id_tmp")
   -> 0.0000s
-- quote_column_name(:event_id_convert_to_bigint)
   -> 0.0000s
-- execute("ALTER TABLE \"push_event_payloads\" RENAME COLUMN \"event_id_tmp\" TO \"event_id_convert_to_bigint\"")
   -> 0.0007s
-- quote_table_name("trigger_07c94931164e")
   -> 0.0000s
-- execute("ALTER FUNCTION \"trigger_07c94931164e\" RESET ALL")
   -> 0.0009s
-- change_column_default("push_event_payloads", :event_id, nil)
   -> 0.0021s
-- change_column_default("push_event_payloads", :event_id_convert_to_bigint, 0)
   -> 0.0029s
-- execute("ALTER TABLE push_event_payloads DROP CONSTRAINT push_event_payloads_pkey")
   -> 0.0014s
-- rename_index("push_event_payloads", "index_push_event_payloads_on_event_id_convert_to_bigint", "push_event_payloads_pkey")
   -> 0.0009s
-- execute("ALTER TABLE push_event_payloads ADD CONSTRAINT push_event_payloads_pkey PRIMARY KEY USING INDEX push_event_payloads_pkey")
   -> 0.0009s
-- remove_foreign_key("push_event_payloads", {:name=>"fk_36c74129da"})
   -> 0.0033s
-- quote_table_name("push_event_payloads")
   -> 0.0000s
-- quote_column_name("fk_a5e47ac4c5")
   -> 0.0000s
-- quote_column_name("fk_36c74129da")
   -> 0.0000s
-- execute("ALTER TABLE \"push_event_payloads\"\nRENAME CONSTRAINT \"fk_a5e47ac4c5\" TO \"fk_36c74129da\"\n")
   -> 0.0007s
== 20210709024048 FinalizePushEventPayloadsBigintConversion2: reverted (0.0528s)

Database schema changes

 CREATE TABLE push_event_payloads (
     commit_count bigint NOT NULL,
-    event_id integer NOT NULL,
+    event_id_convert_to_bigint integer DEFAULT 0 NOT NULL,
     action smallint NOT NULL,
     ref_type smallint NOT NULL,
     commit_from bytea,
@@ -17446,7 +17446,7 @@ CREATE TABLE push_event_payloads (
     ref text,
     commit_title character varying(70),
     ref_count integer,
-    event_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
+    event_id bigint NOT NULL
 );

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

Does this MR contain changes to processing or storing of credentials or tokens, authorization and authentication methods or other items described in the security review guidelines? If not, then delete this Security section.

  • Label as security and @ mention @gitlab-com/gl-security/appsec
  • The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • Security reports checked/validated by a reviewer from the AppSec team

Related to #288005 (closed)

Edited by Krasimir Angelov

Merge request reports