pg_online_schema_change 0.9.6 → 0.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +6 -3
- data/README.md +1 -1
- data/lib/pg_online_schema_change/client.rb +4 -0
- data/lib/pg_online_schema_change/orchestrate.rb +47 -12
- data/lib/pg_online_schema_change/query.rb +9 -0
- data/lib/pg_online_schema_change/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1838409c592e1497790a6e02f883b857851450181854baf660b9b7ee3664c6e
|
4
|
+
data.tar.gz: 4f7e58eeafb2413ec774988b3190391033e819a444a25da3b1ff0fcbf6bf64e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c769f18ab1815fa543246fd18bb3157add074894f15371abb88e1af61e9381eade6850e4fba3a7d6d3701711594ed10a9018c7fe1c45a5ffdaf501891bf7e548
|
7
|
+
data.tar.gz: 84667ac77dab1d97478d51d9635dfcacd38e23ffe59ef6171863ca52d69294af19672bd89dba49a6d325b1c64c4e76a5dc8c57bf3dfee1120e2bd4bec1ca9e21
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pg_online_schema_change (0.9.
|
4
|
+
pg_online_schema_change (0.9.7)
|
5
5
|
ougai (~> 2.0.0)
|
6
6
|
pg (>= 1.3.2, < 1.6.0)
|
7
7
|
pg_query (>= 2.1.3, < 4.3.0)
|
@@ -11,9 +11,11 @@ GEM
|
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
13
|
ast (2.4.2)
|
14
|
+
bigdecimal (3.1.5)
|
14
15
|
coderay (1.1.3)
|
15
16
|
diff-lcs (1.5.0)
|
16
|
-
google-protobuf (3.25.
|
17
|
+
google-protobuf (3.25.2-arm64-darwin)
|
18
|
+
google-protobuf (3.25.2-x86_64-linux)
|
17
19
|
haml (6.1.1)
|
18
20
|
temple (>= 0.8.2)
|
19
21
|
thor
|
@@ -21,7 +23,8 @@ GEM
|
|
21
23
|
json (2.6.3)
|
22
24
|
language_server-protocol (3.17.0.3)
|
23
25
|
method_source (1.0.0)
|
24
|
-
oj (3.16.
|
26
|
+
oj (3.16.3)
|
27
|
+
bigdecimal (>= 3.0)
|
25
28
|
ougai (2.0.0)
|
26
29
|
oj (~> 3.10)
|
27
30
|
parallel (1.23.0)
|
data/README.md
CHANGED
@@ -107,9 +107,9 @@ print the version
|
|
107
107
|
- `pg-osc` acquires minimal locks throughout the process (read more below on the [caveats](#few-things-to-keep-in-mind)).
|
108
108
|
- Copies over indexes and Foreign keys.
|
109
109
|
- Optionally drop or retain old tables in the end.
|
110
|
+
- Reduce bloat (since pg-osc creates a new table and drops the old one post swap).
|
110
111
|
- Tune how slow or fast should replays be from the audit/log table ([Replaying larger workloads](#replaying-larger-workloads)).
|
111
112
|
- Backfill old/new columns as data is copied from primary table to shadow table, and then perform the swap. [Example](#backfill-data)
|
112
|
-
- **TBD**: Ability to reverse the change with no data loss. [tracking issue](https://github.com/shayonj/pg-osc/issues/14)
|
113
113
|
|
114
114
|
## Load test
|
115
115
|
|
@@ -5,6 +5,7 @@ require "securerandom"
|
|
5
5
|
module PgOnlineSchemaChange
|
6
6
|
class Orchestrate
|
7
7
|
SWAP_STATEMENT_TIMEOUT = "5s"
|
8
|
+
TRACK_PROGRESS_INTERVAL = 60 # seconds
|
8
9
|
|
9
10
|
extend Helper
|
10
11
|
|
@@ -58,6 +59,10 @@ module PgOnlineSchemaChange
|
|
58
59
|
|
59
60
|
raise Error, "Parent table has no primary key, exiting..." if primary_key.nil?
|
60
61
|
|
62
|
+
logger.info("Performing some house keeping....")
|
63
|
+
run_analyze!
|
64
|
+
run_vacuum!
|
65
|
+
|
61
66
|
setup_audit_table!
|
62
67
|
|
63
68
|
setup_trigger!
|
@@ -159,6 +164,12 @@ module PgOnlineSchemaChange
|
|
159
164
|
end
|
160
165
|
|
161
166
|
def setup_shadow_table!
|
167
|
+
logger.info("Setting up shadow table", { shadow_table: shadow_table })
|
168
|
+
Query.run(
|
169
|
+
client.connection,
|
170
|
+
"SELECT create_table_all('#{client.table_name}', '#{shadow_table}');",
|
171
|
+
)
|
172
|
+
|
162
173
|
# re-uses transaction with serializable
|
163
174
|
# This ensures that all queries from here till copy_data run with serializable.
|
164
175
|
# This is to to ensure that once the trigger is added to the primay table
|
@@ -168,13 +179,6 @@ module PgOnlineSchemaChange
|
|
168
179
|
# adding the trigger, till the copy ends, since they all happen in the
|
169
180
|
# same serializable transaction.
|
170
181
|
Query.run(client.connection, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE", true)
|
171
|
-
logger.info("Setting up shadow table", { shadow_table: shadow_table })
|
172
|
-
|
173
|
-
Query.run(
|
174
|
-
client.connection,
|
175
|
-
"SELECT create_table_all('#{client.table_name}', '#{shadow_table}');",
|
176
|
-
true,
|
177
|
-
)
|
178
182
|
|
179
183
|
# update serials
|
180
184
|
Query.run(
|
@@ -208,19 +212,44 @@ module PgOnlineSchemaChange
|
|
208
212
|
)
|
209
213
|
Query.run(client.connection, "DELETE FROM #{audit_table}", true)
|
210
214
|
|
211
|
-
logger.info(
|
212
|
-
"Copying contents..",
|
213
|
-
{ shadow_table: shadow_table, parent_table: client.table_name },
|
214
|
-
)
|
215
215
|
if client.copy_statement
|
216
216
|
query = format(client.copy_statement, shadow_table: shadow_table)
|
217
217
|
return Query.run(client.connection, query, true)
|
218
218
|
end
|
219
219
|
|
220
|
+
logger.info(
|
221
|
+
"Copying contents..",
|
222
|
+
{ shadow_table: shadow_table, parent_table: client.table_name },
|
223
|
+
)
|
224
|
+
|
225
|
+
@copy_finished = false
|
226
|
+
log_progress
|
227
|
+
|
220
228
|
sql = Query.copy_data_statement(client, shadow_table, true)
|
221
229
|
Query.run(client.connection, sql, true)
|
222
230
|
ensure
|
223
231
|
Query.run(client.connection, "COMMIT;") # commit the serializable transaction
|
232
|
+
@copy_finished = true
|
233
|
+
end
|
234
|
+
|
235
|
+
def log_progress
|
236
|
+
new_connection = client.checkout_connection
|
237
|
+
source_table_size = Query.get_table_size(new_connection, client.schema, client.table_name)
|
238
|
+
|
239
|
+
Thread.new do
|
240
|
+
loop do
|
241
|
+
break if @copy_finished
|
242
|
+
|
243
|
+
shadow_table_size = Query.get_table_size(new_connection, client.schema, shadow_table)
|
244
|
+
progress = (shadow_table_size.to_f / source_table_size) * 100
|
245
|
+
logger.info("Estimated copy progress: #{progress.round(2)}% complete")
|
246
|
+
|
247
|
+
break if @copy_finished || progress >= 100
|
248
|
+
sleep(TRACK_PROGRESS_INTERVAL) unless ENV["CI"]
|
249
|
+
rescue StandardError => e
|
250
|
+
logger.info("Reporting progress failed: #{e.message}")
|
251
|
+
end
|
252
|
+
end
|
224
253
|
end
|
225
254
|
|
226
255
|
def replay_and_swap!
|
@@ -272,7 +301,13 @@ module PgOnlineSchemaChange
|
|
272
301
|
def run_analyze!
|
273
302
|
logger.info("Performing ANALYZE!")
|
274
303
|
|
275
|
-
|
304
|
+
client.connection.async_exec("ANALYZE VERBOSE #{client.schema}.#{client.table_name};")
|
305
|
+
end
|
306
|
+
|
307
|
+
def run_vacuum!
|
308
|
+
logger.info("Performing VACUUM!")
|
309
|
+
|
310
|
+
client.connection.async_exec("VACUUM VERBOSE #{client.schema}.#{client.table_name};")
|
276
311
|
end
|
277
312
|
|
278
313
|
def validate_constraints!
|
@@ -428,6 +428,15 @@ module PgOnlineSchemaChange
|
|
428
428
|
SELECT setval((select pg_get_serial_sequence('#{shadow_table}', '#{primary_key}')), (SELECT max(#{primary_key}) FROM #{table}));
|
429
429
|
SQL
|
430
430
|
end
|
431
|
+
|
432
|
+
def get_table_size(connection, schema, table_name)
|
433
|
+
size_query = "SELECT pg_table_size('#{schema}.#{table_name}');"
|
434
|
+
result = run(connection, size_query).first
|
435
|
+
result["pg_table_size"].to_i
|
436
|
+
rescue StandardError => e
|
437
|
+
logger.error("Error getting table size: #{e.message}")
|
438
|
+
0
|
439
|
+
end
|
431
440
|
end
|
432
441
|
end
|
433
442
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_online_schema_change
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shayon Mukherjee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ougai
|
@@ -311,7 +311,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
311
311
|
requirements:
|
312
312
|
- - ">="
|
313
313
|
- !ruby/object:Gem::Version
|
314
|
-
version:
|
314
|
+
version: 3.0.0
|
315
315
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
316
316
|
requirements:
|
317
317
|
- - ">="
|