summaryrefslogtreecommitdiff
path: root/doc/development/what_requires_downtime.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/development/what_requires_downtime.md')
-rw-r--r--doc/development/what_requires_downtime.md67
1 files changed, 33 insertions, 34 deletions
diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md
index 9ece6eff41e..8ea9f70fc7a 100644
--- a/doc/development/what_requires_downtime.md
+++ b/doc/development/what_requires_downtime.md
@@ -5,38 +5,6 @@ GitLab offline, others do require a downtime period. This guide describes
various operations, their impact, and how to perform them without requiring
downtime.
-## Adding Columns
-
-You can safely add a new column to an existing table as long as it does **not**
-have a default value. For example, this query would not require downtime:
-
-```sql
-ALTER TABLE projects ADD COLUMN random_value int;
-```
-
-Add a column _with_ a default however does require downtime. For example,
-consider this query:
-
-```sql
-ALTER TABLE projects ADD COLUMN random_value int DEFAULT 42;
-```
-
-This requires updating every single row in the `projects` table so that
-`random_value` is set to `42` by default. This requires updating all rows and
-indexes in a table. This in turn acquires enough locks on the table for it to
-effectively block any other queries.
-
-Adding a column with a default value _can_ be done without requiring downtime
-when using the migration helper method
-`Gitlab::Database::MigrationHelpers#add_column_with_default`. This method works
-similar to `add_column` except it updates existing rows in batches without
-blocking access to the table being modified. See ["Adding Columns With Default
-Values"](migration_style_guide.md#adding-columns-with-default-values) for more
-information on how to use this method.
-
-Note that usage of `add_column_with_default` with `allow_null: false` to also add
-a `NOT NULL` constraint is [discouraged](https://gitlab.com/gitlab-org/gitlab/issues/38060).
-
## Dropping Columns
Removing columns is tricky because running GitLab processes may still be using
@@ -171,8 +139,39 @@ Adding or removing a NOT NULL clause (or another constraint) can typically be
done without requiring downtime. However, this does require that any application
changes are deployed _first_. Thus, changing the constraints of a column should
happen in a post-deployment migration.
-NOTE: Avoid using `change_column` as it produces inefficient query because it re-defines
-the whole column type. For example, to add a NOT NULL constraint, prefer `change_column_null`
+
+NOTE: Avoid using `change_column` as it produces an inefficient query because it re-defines
+the whole column type.
+
+To add a NOT NULL constraint, use the `add_not_null_constraint` migration helper:
+
+```ruby
+# A post-deployment migration in db/post_migrate
+class AddNotNull < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ def up
+ add_not_null_constraint :users, :username
+ end
+
+ def down
+ remove_not_null_constraint :users, :username
+ end
+end
+```
+
+If the column to be updated requires cleaning first (e.g. there are `NULL` values), you should:
+
+1. Add the `NOT NULL` constraint with `validate: false`
+
+ `add_not_null_constraint :users, :username, validate: false`
+
+1. Clean up the data with a data migration
+1. Validate the `NOT NULL` constraint with a followup migration
+
+ `validate_not_null_constraint :users, :username`
## Changing Column Types