pg_online_schema_change 0.2.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d69a5ecadf6f0c3b3c27bb2e16e163cfbc6526c4c83b5cbdf4ebef73be62cf9
4
- data.tar.gz: 5a8ac6b5491692d4680f40637550392ebe5e8a206e7e3b1729967a379231ee8a
3
+ metadata.gz: b14af6aa2b98ab8f1b2aab5ae0a8555e017f92531ce1214e50f2ac62ff354224
4
+ data.tar.gz: 66ba81f4e90f4dc612d863d043838fec8676e468924eeb5c39d21094d002e48a
5
5
  SHA512:
6
- metadata.gz: 5b8960dae33e3cf5bace38cb45cacaa555d16433b15703ffda2f2338b5076e716c23271d5f08d77f033cfbe9c6f2ea450e764a8ce934bb3ec9bfd9327cf89735
7
- data.tar.gz: f003a55abb25ad2bcecf5a4e3b2358bfac4b3c0c55c401f7500a8d92e2b5bd30ebb4891d934cec52a1449e65a4fd9d177a9f87a2493d72b3f949ef47493943e8
6
+ metadata.gz: a272a3749f8f053a528d859cc35b97b5fde7d6353a3c0c710500e35d33df6b4bc8526b18e855fd154b742eef8189b661e8e710a6b25221df6e47d55a47381a2e
7
+ data.tar.gz: c0dd7f41e204840b54b768df1f1e8486f79038bede199021ef13684c4b1369e3de43be6fbfd8f03b7ca652251c59a8a580ecefb235e00e54858d77f88a7334de
data/.rubocop.yml CHANGED
@@ -1,3 +1,5 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
1
3
  require:
2
4
  - rubocop-rspec
3
5
  - rubocop-packaging
@@ -14,71 +16,70 @@ AllCops:
14
16
  - "vendor/**/*"
15
17
 
16
18
  Layout/HashAlignment:
17
- EnforcedColonStyle:
18
- - table
19
- - key
20
- EnforcedHashRocketStyle:
21
- - table
22
- - key
19
+ EnforcedColonStyle: key
20
+ EnforcedHashRocketStyle: key
23
21
 
24
22
  Layout/SpaceAroundEqualsInParameterDefault:
25
- EnforcedStyle: no_space
23
+ EnforcedStyle: space
26
24
 
27
25
  Metrics/AbcSize:
28
- Max: 20
26
+ Enabled: true
27
+ Max: 40
29
28
  Exclude:
30
- - "test/**/*"
29
+ - "spec/**/*"
31
30
 
32
31
  Metrics/BlockLength:
32
+ Max: 100
33
33
  Exclude:
34
34
  - "*.gemspec"
35
35
  - "Rakefile"
36
+ - "spec/**/*"
36
37
 
37
38
  Metrics/ClassLength:
38
39
  Exclude:
39
40
  - "test/**/*"
40
41
 
41
42
  Metrics/MethodLength:
42
- Max: 18
43
+ Max: 30
43
44
  Exclude:
44
45
  - "test/**/*"
45
46
 
46
47
  Metrics/ParameterLists:
47
- Max: 6
48
+ Max: 5
48
49
 
49
50
  Naming/MemoizedInstanceVariableName:
50
- Enabled: false
51
+ Enabled: true
51
52
 
52
53
  Naming/VariableNumber:
53
- Enabled: false
54
-
55
- Rake/Desc:
56
- Enabled: false
54
+ Enabled: true
57
55
 
58
56
  Style/BarePercentLiterals:
59
57
  EnforcedStyle: percent_q
60
58
 
61
59
  Style/ClassAndModuleChildren:
62
- Enabled: false
60
+ Enabled: true
63
61
 
64
62
  Style/Documentation:
65
63
  Enabled: false
66
64
 
67
65
  Style/DoubleNegation:
68
- Enabled: false
66
+ Enabled: true
69
67
 
70
68
  Style/EmptyMethod:
71
- Enabled: false
69
+ Enabled: true
72
70
 
73
71
  Style/FrozenStringLiteralComment:
74
- Enabled: false
72
+ Enabled: true
75
73
 
76
74
  Style/NumericPredicate:
77
- Enabled: false
75
+ Enabled: true
78
76
 
79
77
  Style/StringLiterals:
80
78
  EnforcedStyle: double_quotes
81
79
 
80
+ Style/StringLiteralsInInterpolation:
81
+ EnforcedStyle: double_quotes
82
+
82
83
  Style/TrivialAccessors:
83
84
  AllowPredicates: true
84
85
 
@@ -91,9 +92,41 @@ Style/TrailingCommaInArrayLiteral:
91
92
  Style/TrailingCommaInHashLiteral:
92
93
  EnforcedStyleForMultiline: comma
93
94
 
94
- Style/SpaceAroundEqualsInParameterDefault:
95
- EnforcedStyle: space
95
+ Layout/MultilineArrayBraceLayout:
96
+ Enabled: true
97
+ EnforcedStyle: symmetrical
96
98
 
97
- Style/MultilineHashBraceLayout:
99
+ Layout/MultilineHashBraceLayout:
98
100
  Enabled: true
99
101
  EnforcedStyle: symmetrical
102
+
103
+ Layout/MultilineAssignmentLayout:
104
+ Enabled: true
105
+ EnforcedStyle: same_line
106
+
107
+ Layout/FirstArrayElementIndentation:
108
+ Enabled: true
109
+ EnforcedStyle: consistent
110
+
111
+ Layout/FirstHashElementIndentation:
112
+ Enabled: true
113
+ EnforcedStyle: consistent
114
+
115
+ Layout/MultilineHashKeyLineBreaks:
116
+ Enabled: true
117
+
118
+ Layout/LineLength:
119
+ Enabled: true
120
+ Max: 250
121
+
122
+ Style/FormatStringToken:
123
+ Enabled: true
124
+ EnforcedStyle: template
125
+
126
+ RSpec/MessageSpies:
127
+ Enabled: true
128
+ EnforcedStyle: receive
129
+
130
+ RSpec/FilePath:
131
+ Enabled: true
132
+ SpecSuffixOnly: true
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,44 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2022-02-21 22:46:44 UTC using RuboCop version 1.23.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 2
10
+ # Configuration parameters: CountComments, CountAsOne.
11
+ Metrics/ClassLength:
12
+ Max: 233
13
+
14
+ # Offense count: 2
15
+ # Configuration parameters: IgnoredMethods.
16
+ Metrics/CyclomaticComplexity:
17
+ Max: 15
18
+
19
+ # Offense count: 2
20
+ # Configuration parameters: IgnoredMethods.
21
+ Metrics/PerceivedComplexity:
22
+ Max: 13
23
+
24
+ # Offense count: 1
25
+ Packaging/GemspecGit:
26
+ Exclude:
27
+ - 'pg_online_schema_change.gemspec'
28
+
29
+ # Offense count: 62
30
+ # Configuration parameters: CountAsOne.
31
+ RSpec/ExampleLength:
32
+ Max: 55
33
+
34
+ # Offense count: 38
35
+ RSpec/MultipleExpectations:
36
+ Max: 14
37
+
38
+ # Offense count: 6
39
+ # Configuration parameters: AllowedMethods.
40
+ # AllowedMethods: respond_to_missing?
41
+ Style/OptionalBooleanParameter:
42
+ Exclude:
43
+ - 'lib/pg_online_schema_change/query.rb'
44
+ - 'lib/pg_online_schema_change/replay.rb'
data/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
+ ## [0.4.0] - 2022-02-22
2
+ * Lint sourcecode, setup Rubocop proper and Lint in CI by @shayonj in https://github.com/shayonj/pg-osc/pull/46
3
+ * Uniquely identify operation_type column by @shayonj in https://github.com/shayonj/pg-osc/pull/50
4
+ * Introduce primary key on audit table for ordered reads by @shayonj in https://github.com/shayonj/pg-osc/pull/49
5
+ - This addresses an edge case with replay.
6
+ * Uniquely identify trigger_time column by @shayonj in https://github.com/shayonj/pg-osc/pull/51
7
+ * Abstract assertions into a helper function by @shayonj in https://github.com/shayonj/pg-osc/pull/52
8
+
9
+ ## [0.3.0] - 2022-02-21
10
+
11
+ - Explicitly call dependencies and bump dependencies by @shayonj https://github.com/shayonj/pg-osc/pull/44
12
+ - Introduce Dockerfile and release process https://github.com/shayonj/pg-osc/pull/45
13
+
1
14
  ## [0.2.0] - 2022-02-17
2
15
 
3
- - Use ISOLATION LEVEL SERIALIZABLE ([#42](https://github.com/shayonj/pg-online-schema-change/pull/42)) (props to @jfrost)
16
+ - Use ISOLATION LEVEL SERIALIZABLE ([#42](https://github.com/shayonj/pg-osc/pull/42)) (props to @jfrost)
4
17
 
5
18
  ## [0.1.0] - 2022-02-16
6
19
 
@@ -10,4 +23,4 @@ pg-online-schema-change (`pg-osc`) is a tool for making schema changes (any `ALT
10
23
 
11
24
  `pg-osc` uses the concept of shadow table to perform schema changes. At a high level, it copies the contents from a primary table to a shadow table, performs the schema change on the shadow table and swaps the table names in the end while preserving all changes to the primary table using triggers (via audit table).
12
25
 
13
- Checkout [Readme](https://github.com/shayonj/pg-online-schema-change#readme) for more details.
26
+ Checkout [Readme](https://github.com/shayonj/pg-osc#readme) for more details.
data/Dockerfile ADDED
@@ -0,0 +1,5 @@
1
+ FROM ruby:3.0
2
+
3
+ ARG VERSION=0.2.0
4
+
5
+ RUN gem install pg_online_schema_change -v $VERSION
data/Gemfile CHANGED
@@ -3,16 +3,3 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
-
7
- gem "ougai", "~> 2.0.0"
8
- gem "pg", "~> 1.0"
9
- gem "pg_query", "~> 2.1.2"
10
- gem "pry"
11
- gem "rake", "~> 13.0"
12
- gem "rspec", "~> 3.0"
13
- gem "rubocop", "~> 1.23.0"
14
- gem "rubocop-packaging", "~> 0.5.1"
15
- gem "rubocop-performance", "~> 1.12.0"
16
- gem "rubocop-rake", "~> 0.6.0"
17
- gem "rubocop-rspec", "~> 2.7.0"
18
- gem "thor", "~> 1.1.0"
data/Gemfile.lock CHANGED
@@ -1,7 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pg_online_schema_change (0.1.0)
4
+ pg_online_schema_change (0.4.0)
5
+ ougai (~> 2.0.0)
6
+ pg (~> 1.3.2)
7
+ pg_query (~> 2.1.3)
8
+ thor (~> 1.2.1)
5
9
 
6
10
  GEM
7
11
  remote: https://rubygems.org/
@@ -9,18 +13,17 @@ GEM
9
13
  ast (2.4.2)
10
14
  coderay (1.1.3)
11
15
  diff-lcs (1.5.0)
12
- google-protobuf (3.19.2)
13
- google-protobuf (3.19.2-x86_64-linux)
16
+ google-protobuf (3.19.4)
14
17
  method_source (1.0.0)
15
- oj (3.13.10)
18
+ oj (3.13.11)
16
19
  ougai (2.0.0)
17
20
  oj (~> 3.10)
18
21
  parallel (1.21.0)
19
22
  parser (3.0.3.2)
20
23
  ast (~> 2.4.1)
21
- pg (1.2.3)
22
- pg_query (2.1.2)
23
- google-protobuf (>= 3.17.1)
24
+ pg (1.3.2)
25
+ pg_query (2.1.3)
26
+ google-protobuf (>= 3.19.2)
24
27
  pry (0.14.1)
25
28
  coderay (~> 1.1)
26
29
  method_source (~> 1.0)
@@ -62,7 +65,7 @@ GEM
62
65
  rubocop-rspec (2.7.0)
63
66
  rubocop (~> 1.19)
64
67
  ruby-progressbar (1.11.0)
65
- thor (1.1.0)
68
+ thor (1.2.1)
66
69
  unicode-display_width (2.1.0)
67
70
 
68
71
  PLATFORMS
@@ -70,11 +73,8 @@ PLATFORMS
70
73
  x86_64-linux
71
74
 
72
75
  DEPENDENCIES
73
- ougai (~> 2.0.0)
74
- pg (~> 1.0)
75
76
  pg_online_schema_change!
76
- pg_query (~> 2.1.2)
77
- pry
77
+ pry (~> 0.14.1)
78
78
  rake (~> 13.0)
79
79
  rspec (~> 3.0)
80
80
  rubocop (~> 1.23.0)
@@ -82,7 +82,6 @@ DEPENDENCIES
82
82
  rubocop-performance (~> 1.12.0)
83
83
  rubocop-rake (~> 0.6.0)
84
84
  rubocop-rspec (~> 2.7.0)
85
- thor (~> 1.1.0)
86
85
 
87
86
  BUNDLED WITH
88
87
  2.3.3
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
- # pg-online-schema-change / pg-osc
2
- [![CircleCI](https://circleci.com/gh/shayonj/pg-online-schema-change/tree/main.svg?style=shield)](https://circleci.com/gh/shayonj/pg-online-schema-change/tree/main)
1
+ # pg-osc
2
+
3
+ [![CircleCI](https://circleci.com/gh/shayonj/pg-osc/tree/main.svg?style=shield)](https://circleci.com/gh/shayonj/pg-osc/tree/main)
3
4
  [![Gem Version](https://badge.fury.io/rb/pg_online_schema_change.svg)](https://badge.fury.io/rb/pg_online_schema_change)
4
5
 
5
6
  pg-online-schema-change (`pg-osc`) is a tool for making schema changes (any `ALTER` statements) in Postgres tables with minimal locks, thus helping achieve zero downtime schema changes against production workloads.
@@ -10,6 +11,26 @@ pg-online-schema-change (`pg-osc`) is a tool for making schema changes (any `ALT
10
11
 
11
12
  ⚠️ Proceed with caution when using this on production like workloads. Best to try on similar setup or staging like environment first. Read on below for some examples and caveats.
12
13
 
14
+ ## Table of Contents
15
+
16
+ - [Installation](#installation)
17
+ - [Requirements](#requirements)
18
+ - [Usage](#usage)
19
+ - [Prominent features](#prominent-features)
20
+ - [Load test](#load-test)
21
+ - [Examples](#examples)
22
+ * [Renaming a column](#renaming-a-column)
23
+ * [Multiple ALTER statements](#multiple-alter-statements)
24
+ * [Kill other backends after 5s](#kill-other-backends-after-5s)
25
+ * [Backfill data](#backfill-data)
26
+ * [Running using Docker](#running-using-docker)
27
+ - [Caveats](#caveats)
28
+ - [How does it work](#how-does-it-work)
29
+ - [Development](#development)
30
+ - [Releasing](#releasing)
31
+ - [Contributing](#contributing)
32
+ - [License](#license)
33
+ - [Code of Conduct](#code-of-conduct)
13
34
  ## Installation
14
35
 
15
36
  Add this line to your application's Gemfile:
@@ -26,6 +47,13 @@ Or install it yourself as:
26
47
 
27
48
  $ gem install pg_online_schema_change
28
49
 
50
+ This will include all dependencies accordingly as well. Make sure the following requirements are satisfied.
51
+
52
+ Or via Docker:
53
+
54
+ docker pull shayonj/pg-osc:latest
55
+
56
+ https://hub.docker.com/r/shayonj/pg-osc
29
57
  ## Requirements
30
58
  - PostgreSQL 9.6 and later
31
59
  - Ruby 2.6 and later
@@ -48,13 +76,17 @@ Options:
48
76
  -u, --username=USERNAME # Username for the Database
49
77
  -p, --port=N # Port for the Database
50
78
  # Default: 5432
51
- -w, --password=PASSWORD # Password for the Database
79
+ -w, --password=PASSWORD # DEPRECATED: Password for the Database. Please pass PGPASSWORD environment variable instead.
52
80
  -v, [--verbose], [--no-verbose] # Emit logs in debug mode
53
81
  -f, [--drop], [--no-drop] # Drop the original table in the end after the swap
54
82
  -k, [--kill-backends], [--no-kill-backends] # Kill other competing queries/backends when trying to acquire lock for the shadow table creation and swap. It will wait for --wait-time-for-lock duration before killing backends and try upto 3 times.
55
83
  -w, [--wait-time-for-lock=N] # Time to wait before killing backends to acquire lock and/or retrying upto 3 times. It will kill backends if --kill-backends is true, otherwise try upto 3 times and exit if it cannot acquire a lock.
56
84
  # Default: 10
57
- -c, [--copy-statement=COPY_STATEMENT] # Takes a .sql file location where you can provide a custom query to be played (ex: backfills) when pg-osc copies data from the primary to the shadow table. More examples in README.
85
+ -c, [--copy-statement=COPY_STATEMENT] # Takes a .sql file location where you can provide a custom query to be played (ex: backfills) when pgosc copies data from the primary to the shadow table. More examples in README.
86
+ -b, [--pull-batch-count=N] # Number of rows to be replayed on each iteration after copy. This can be tuned for faster catch up and swap. Best used with delta-count.
87
+ # Default: 1000
88
+ -e, [--delta-count=N] # Indicates how many rows should be remaining before a swap should be performed. This can be tuned for faster catch up and swap, especially on highly volume tables. Best used with pull-batch-count.
89
+ # Default: 20
58
90
  ```
59
91
 
60
92
  ```
@@ -63,57 +95,38 @@ Usage:
63
95
 
64
96
  print the version
65
97
  ```
66
- ## How does it work
67
-
68
- - **Primary table**: A table against which a potential schema change is to be run
69
- - **Shadow table**: A copy of an existing primary table
70
- - **Audit table**: A table to store any updates/inserts/delete on a primary table
71
-
72
- ![how-it-works](diagrams/how-it-works.png)
73
-
74
-
75
- 1. Create an audit table to record changes made to the parent table.
76
- 2. Acquire a brief `ACCESS EXCLUSIVE` lock to add a trigger on the parent table (for inserts, updates, deletes) to the audit table.
77
- 3. Create a new shadow table and run ALTER/migration on the shadow table.
78
- 4. Copy all rows from the old table.
79
- 5. Build indexes on the new table.
80
- 6. Replay all changes accumulated in the audit table against the shadow table.
81
- - Delete rows in the audit table as they are replayed.
82
- 7. Once the delta (remaining rows) is ~20 rows, acquire an `ACCESS EXCLUSIVE` lock against the parent table within a transaction and:
83
- - swap table names (shadow table <> parent table).
84
- - update references in other tables (FKs) by dropping and re-creating the FKs with a `NOT VALID`.
85
- 8. Runs `ANALYZE` on the new table.
86
- 9. Validates all FKs that were added with `NOT VALID`.
87
- 10. Drop parent (now old) table (OPTIONAL).
88
-
89
98
  ## Prominent features
90
99
  - `pg-osc` supports when a column is being added, dropped or renamed with no data loss.
91
100
  - `pg-osc` acquires minimal locks throughout the process (read more below on the caveats).
92
101
  - Copies over indexes and Foreign keys.
93
102
  - Optionally drop or retain old tables in the end.
94
103
  - Backfill old/new columns as data is copied from primary table to shadow table, and then perform the swap. [Example](#backfill-data)
95
- - **TBD**: Ability to reverse the change with no data loss. [tracking issue](https://github.com/shayonj/pg-online-schema-change/issues/14)
104
+ - **TBD**: Ability to reverse the change with no data loss. [tracking issue](https://github.com/shayonj/pg-osc/issues/14)
105
+
106
+ ## Load test
107
+
108
+ [More about the preliminary load test figures here](docs/load-test.md)
96
109
 
97
110
  ## Examples
98
111
 
99
112
  ### Renaming a column
100
113
  ```
114
+ export PGPASSWORD=""
101
115
  pg-online-schema-change perform \
102
116
  --alter-statement 'ALTER TABLE books RENAME COLUMN email TO new_email' \
103
117
  --dbname "postgres" \
104
118
  --host "localhost" \
105
119
  --username "jamesbond" \
106
- --password "" \
107
120
  ```
108
121
 
109
122
  ### Multiple ALTER statements
110
123
  ```
124
+ export PGPASSWORD=""
111
125
  pg-online-schema-change perform \
112
126
  --alter-statement 'ALTER TABLE books ADD COLUMN "purchased" BOOLEAN DEFAULT FALSE; ALTER TABLE books RENAME COLUMN email TO new_email;' \
113
127
  --dbname "postgres" \
114
128
  --host "localhost" \
115
129
  --username "jamesbond" \
116
- --password "" \
117
130
  --drop
118
131
  ```
119
132
 
@@ -121,13 +134,30 @@ pg-online-schema-change perform \
121
134
  If the operation is being performed on a busy table, you can use `pg-osc`'s `kill-backend` functionality to kill other backends that may be competing with the `pg-osc` operation to acquire a lock for a brief while. The `ACCESS EXCLUSIVE` lock acquired by `pg-osc` is only held for a brief while and released after. You can tune how long `pg-osc` should wait before killing other backends (or if at all `pg-osc` should kill backends in the first place).
122
135
 
123
136
  ```
137
+ export PGPASSWORD=""
124
138
  pg-online-schema-change perform \
125
139
  --alter-statement 'ALTER TABLE books ADD COLUMN "purchased" BOOLEAN DEFAULT FALSE;' \
126
140
  --dbname "postgres" \
127
141
  --host "localhost" \
128
142
  --username "jamesbond" \
129
- --password "" \
130
- --wait-time-for-lock=5 \
143
+ --wait-time-for-lock 5 \
144
+ --kill-backends \
145
+ --drop
146
+ ```
147
+
148
+ ### Replaying larger workloads
149
+ If you have a table with high write volume, the default replay iteration may not suffice. That is - you may see that `pg-osc` is replaying 1000 rows (`pull-batch-count`) in one go from the audit table. `pg-osc` also waits until the remaining row count (`delta-count`) in audit table is 20 before making the swap. You can tune these values to be higher for faster catch up on these kind of workloads.
150
+
151
+ ```
152
+ export PGPASSWORD=""
153
+ pg-online-schema-change perform \
154
+ --alter-statement 'ALTER TABLE books ADD COLUMN "purchased" BOOLEAN DEFAULT FALSE;' \
155
+ --dbname "postgres" \
156
+ --host "localhost" \
157
+ --username "jamesbond" \
158
+ --pull-batch-count 2000
159
+ --delta-count 500
160
+ --wait-time-for-lock 5 \
131
161
  --kill-backends \
132
162
  --drop
133
163
  ```
@@ -156,11 +186,22 @@ pg-online-schema-change perform \
156
186
  --dbname "postgres" \
157
187
  --host "localhost" \
158
188
  --username "jamesbond" \
159
- --password "" \
160
189
  --copy-statement "/src/query.sql" \
161
190
  --drop
162
191
  ```
163
- ### Caveats
192
+
193
+ ### Running using Docker
194
+
195
+ ```
196
+ docker run --network host -it --rm shayonj/pg-osc:latest \
197
+ pg-online-schema-change perform \
198
+ --alter-statement 'ALTER TABLE books ADD COLUMN "purchased" BOOLEAN DEFAULT FALSE; ALTER TABLE books RENAME COLUMN email TO new_email;' \
199
+ --dbname "postgres" \
200
+ --host "localhost" \
201
+ --username "jamesbond" \
202
+ --drop
203
+ ```
204
+ ## Caveats
164
205
  - A primary key should exist on the table; without it, `pg-osc` will raise an exception
165
206
  - This is because - currently there is no other way to uniquely identify rows during replay.
166
207
  - `pg-osc` will acquire `ACCESS EXCLUSIVE` lock on the parent table twice during the operation.
@@ -175,6 +216,29 @@ pg-online-schema-change perform \
175
216
  - Can be fixed in future releases. Feel free to open a feature req.
176
217
  - Foreign keys are dropped & re-added to referencing tables with a `NOT VALID`. A follow on `VALIDATE CONSTRAINT` is run.
177
218
  - Ensures that integrity is maintained and re-introducing FKs doesn't acquire additional locks, hence the `NOT VALID`.
219
+ ## How does it work
220
+
221
+ - **Primary table**: A table against which a potential schema change is to be run
222
+ - **Shadow table**: A copy of an existing primary table
223
+ - **Audit table**: A table to store any updates/inserts/delete on a primary table
224
+
225
+ ![how-it-works](docs/how-it-works.png)
226
+
227
+
228
+ 1. Create an audit table to record changes made to the parent table.
229
+ 2. Acquire a brief `ACCESS EXCLUSIVE` lock to add a trigger on the parent table (for inserts, updates, deletes) to the audit table.
230
+ 3. Create a new shadow table and run ALTER/migration on the shadow table.
231
+ 4. Copy all rows from the old table.
232
+ 5. Build indexes on the new table.
233
+ 6. Replay all changes accumulated in the audit table against the shadow table.
234
+ - Delete rows in the audit table as they are replayed.
235
+ 7. Once the delta (remaining rows) is ~20 rows, acquire an `ACCESS EXCLUSIVE` lock against the parent table within a transaction and:
236
+ - swap table names (shadow table <> parent table).
237
+ - update references in other tables (FKs) by dropping and re-creating the FKs with a `NOT VALID`.
238
+ 8. Runs `ANALYZE` on the new table.
239
+ 9. Validates all FKs that were added with `NOT VALID`.
240
+ 10. Drop parent (now old) table (OPTIONAL).
241
+
178
242
  ## Development
179
243
 
180
244
  - Install ruby 3.0
@@ -195,16 +259,14 @@ To install this gem onto your local machine, run `bundle exec rake install`.
195
259
  ## Releasing
196
260
 
197
261
  - Bump version in `version.rb`
198
- - `git tag v0.1.0`
199
- - `git push origin --tags`
200
- - `gem build pg_online_schema_change.gemspec`
201
- - `gem push pg_online_schema_change-0.1.0.gem`
262
+ - Commit
263
+ - `./scripts/release.sh 0.2.0`
202
264
  - Update `CHANGELOG.md`
203
- - Create a new release - https://github.com/shayonj/pg-online-schema-change/releases/new
265
+ - Create a new release - https://github.com/shayonj/pg-osc/releases/new
204
266
 
205
267
  ## Contributing
206
268
 
207
- Bug reports and pull requests are welcome on GitHub at https://github.com/shayonj/pg-online-schema-change.
269
+ Bug reports and pull requests are welcome on GitHub at https://github.com/shayonj/pg-osc.
208
270
 
209
271
  ## License
210
272
 
@@ -212,4 +274,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
212
274
 
213
275
  ## Code of Conduct
214
276
 
215
- Everyone interacting in the PgOnlineSchemaChange project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/shayonj/pg-online-schema-change/blob/main/CODE_OF_CONDUCT.md).
277
+ Everyone interacting in the PgOnlineSchemaChange project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/shayonj/pg-osc/blob/main/CODE_OF_CONDUCT.md).