pg_online_schema_change 0.9.6 → 0.9.7

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: 839fe414842291d9118a4115a56e06f1e0308ab3b7a740cafd9994314ded2d76
4
- data.tar.gz: 22e9639093bf386f8a1e554e15e8d83df5e3c6de340c372f181fa3b280aee98d
3
+ metadata.gz: e1838409c592e1497790a6e02f883b857851450181854baf660b9b7ee3664c6e
4
+ data.tar.gz: 4f7e58eeafb2413ec774988b3190391033e819a444a25da3b1ff0fcbf6bf64e4
5
5
  SHA512:
6
- metadata.gz: a160d19b3f1cb6655f70e0481b3293110deaee04d7a017ff9fe0c2b4d6100fd7d475520092db1b3bb5e068df5cb70243a00397a5cb1c2c259f2fe5b776b7e405
7
- data.tar.gz: 9e4543fde48359fdc12046ff019420aafe51732f5cd1332285b3762fac3dcb198acc7be4f5fc6f6f90b910532758eb4a5752a8c9835d1f394774e6f77eda3898
6
+ metadata.gz: c769f18ab1815fa543246fd18bb3157add074894f15371abb88e1af61e9381eade6850e4fba3a7d6d3701711594ed10a9018c7fe1c45a5ffdaf501891bf7e548
7
+ data.tar.gz: 84667ac77dab1d97478d51d9635dfcacd38e23ffe59ef6171863ca52d69294af19672bd89dba49a6d325b1c64c4e76a5dc8c57bf3dfee1120e2bd4bec1ca9e21
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [0.9.6] - 2023-11-04
2
+
3
+ - Fix and add links to caveats section in #130
4
+ - Refresh views across all schemas post swap in #134
5
+
1
6
  ## [0.9.5] - 2023-10-15
2
7
 
3
8
  - Validate one constraint at a time in #124
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pg_online_schema_change (0.9.6)
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.0-arm64-darwin)
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.1)
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
 
@@ -67,5 +67,9 @@ module PgOnlineSchemaChange
67
67
 
68
68
  @copy_statement = File.binread(file_path)
69
69
  end
70
+
71
+ def checkout_connection
72
+ PG.connect(dbname: dbname, host: host, user: username, password: password, port: port)
73
+ end
70
74
  end
71
75
  end
@@ -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
- Query.run(client.connection, "ANALYZE VERBOSE #{client.table_name};")
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgOnlineSchemaChange
4
- VERSION = "0.9.6"
4
+ VERSION = "0.9.7"
5
5
  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.6
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: 2023-11-04 00:00:00.000000000 Z
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: 2.7.0
314
+ version: 3.0.0
315
315
  required_rubygems_version: !ruby/object:Gem::Requirement
316
316
  requirements:
317
317
  - - ">="