Skip to content

Commit 8ce2c47

Browse files
committed
address review comments
1 parent 56fdf25 commit 8ce2c47

17 files changed

+288
-195
lines changed

src/current/_includes/molt/fetch-data-load-output.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
1. Check the output to observe `fetch` progress.
22

3+
{% if page.name == "migrate-load-replicate.md" %}
4+
<section class="filter-content" markdown="1" data-scope="oracle">
5+
The following message shows the appropriate values for the `--backfillFromSCN` and `--scn` replication flags to use when [starting Replicator](#start-replicator):
6+
7+
{% include_cached copy-clipboard.html %}
8+
~~~
9+
replication-only mode should include the following replicator flags: --backfillFromSCN 26685444 --scn 26685786
10+
~~~
11+
</section>
12+
{% endif %}
13+
314
A `starting fetch` message indicates that the task has started:
415

516
<section class="filter-content" markdown="1" data-scope="postgres">
@@ -16,7 +27,7 @@
1627

1728
<section class="filter-content" markdown="1" data-scope="oracle">
1829
~~~ json
19-
{"level":"info","type":"summary","num_tables":3,"cdc_cursor":"2358840","time":"2025-02-10T14:28:11-05:00","message":"starting fetch"}
30+
{"level":"info","type":"summary","num_tables":3,"cdc_cursor":"26685786","time":"2025-02-10T14:28:11-05:00","message":"starting fetch"}
2031
~~~
2132
</section>
2233

@@ -81,15 +92,4 @@
8192
~~~ json
8293
{"level":"info","type":"summary","fetch_id":"f5cb422f-4bb4-4bbd-b2ae-08c4d00d1e7c","num_tables":3,"tables":["migration_schema.employees","migration_schema.payments","migration_schema.payments"],"cdc_cursor":"2358840","net_duration_ms":6752.847625,"net_duration":"000h 00m 06s","time":"2024-03-18T12:30:37-04:00","message":"fetch complete"}
8394
~~~
84-
</section>
85-
86-
{% if page.name == "migrate-load-replicate.md" %}
87-
<section class="filter-content" markdown="1" data-scope="oracle">
88-
The following message shows the appropriate values for the `--backfillFromSCN` and `--scn` replication flags to use when [starting Replicator](#start-replicator):
89-
90-
{% include_cached copy-clipboard.html %}
91-
~~~
92-
replication-only mode should include the following replicator flags: --backfillFromSCN 26685444 --scn 26685786
93-
~~~
94-
</section>
95-
{% endif %}
95+
</section>

src/current/_includes/molt/migration-prepare-database.md

Lines changed: 18 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -129,118 +129,42 @@ GRANT SELECT, FLASHBACK ON migration_schema.tbl TO MIGRATION_USER;
129129
{% if page.name != "migrate-bulk-load.md" %}
130130
#### Configure source database for replication
131131

132-
<section class="filter-content" markdown="1" data-scope="postgres">
133132
{{site.data.alerts.callout_info}}
134-
Connect to the primary PostgreSQL instance, **not** a read replica. Read replicas cannot create or manage logical replication slots. Verify that you are connected to the primary server by running `SELECT pg_is_in_recovery();` and getting a `false` result.
133+
Connect to the primary instance (PostgreSQL primary, MySQL primary/master, or Oracle primary), **not** a replica. Replicas cannot provide the necessary replication checkpoints and transaction metadata required for ongoing replication.
135134
{{site.data.alerts.end}}
136135

136+
<section class="filter-content" markdown="1" data-scope="postgres">
137+
Verify that you are connected to the primary server by running `SELECT pg_is_in_recovery();` and getting a `false` result.
138+
137139
Enable logical replication by setting `wal_level` to `logical` in `postgresql.conf` or in the SQL shell. For example:
138140

139141
{% include_cached copy-clipboard.html %}
140142
~~~ sql
141143
ALTER SYSTEM SET wal_level = 'logical';
142144
~~~
143-
144-
Create a publication for the tables you want to replicate. Do this **before** creating the replication slot.
145-
146-
To create a publication for all tables:
147-
148-
{% include_cached copy-clipboard.html %}
149-
~~~ sql
150-
CREATE PUBLICATION molt_publication FOR ALL TABLES;
151-
~~~
152-
153-
To create a publication for specific tables:
154-
155-
{% include_cached copy-clipboard.html %}
156-
~~~ sql
157-
CREATE PUBLICATION molt_publication FOR TABLE employees, payments, orders;
158-
~~~
159-
160-
Create a logical replication slot:
161-
162-
{% include_cached copy-clipboard.html %}
163-
~~~ sql
164-
SELECT pg_create_logical_replication_slot('molt_slot', 'pgoutput');
165-
~~~
166-
167-
##### Verify logical replication setup
168-
169-
Verify the publication was created successfully:
170-
171-
{% include_cached copy-clipboard.html %}
172-
~~~ sql
173-
SELECT * FROM pg_publication;
174-
~~~
175-
176-
~~~
177-
oid | pubname | pubowner | puballtables | pubinsert | pubupdate | pubdelete | pubtruncate | pubviaroot
178-
-------+------------------+----------+--------------+-----------+-----------+-----------+-------------+------------
179-
59084 | molt_publication | 10 | t | t | t | t | t | f
180-
~~~
181-
182-
Verify the replication slot was created:
183-
184-
{% include_cached copy-clipboard.html %}
185-
~~~ sql
186-
SELECT * FROM pg_replication_slots;
187-
~~~
188-
189-
~~~
190-
slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn | wal_status | safe_wal_size | two_phase
191-
-----------+----------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------+------------+---------------+-----------
192-
molt_slot | pgoutput | logical | 16385 | molt | f | f | | | 2261 | 0/49913A20 | 0/49913A58 | reserved | | f
193-
~~~
194145
</section>
195146

196147
<section class="filter-content" markdown="1" data-scope="mysql">
197148
Enable [global transaction identifiers (GTID)](https://dev.mysql.com/doc/refman/8.0/en/replication-options-gtids.html) and configure binary logging. Set `binlog-row-metadata` or `binlog-row-image` to `full` to provide complete metadata for replication.
198149

150+
Configure binlog retention to ensure GTIDs remain available throughout the migration:
151+
152+
- MySQL 8.0.1+: Set `binlog_expire_logs_seconds` (default: 2592000 = 30 days) based on your migration timeline.
153+
- MySQL < 8.0: Set `expire_logs_days`, or manually manage retention by setting `max_binlog_size` and using `PURGE BINARY LOGS BEFORE NOW() - INTERVAL 1 HOUR` (adjusting the interval as needed). Force binlog rotation with `FLUSH BINARY LOGS` if needed.
154+
- Managed services: Refer to provider-specific configuration for [Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/mysql-stored-proc-configuring.html) or [Google Cloud SQL](https://cloud.google.com/sql/docs/mysql/flags#mysql-b).
155+
156+
{% comment %}
199157
{{site.data.alerts.callout_info}}
200-
GTID replication sends all database changes to Replicator. To limit replication to specific tables or schemas, use the `--table-filter` and `--schema-filter` flags in the `replicator` command.
158+
GTID replication sends all database changes to Replicator. To limit replication to specific tables or schemas, use a userscript.
201159
{{site.data.alerts.end}}
160+
{% endcomment %}
202161

203162
| Version | Configuration |
204163
|------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
205164
| MySQL 5.6 | `--gtid-mode=on`<br>`--enforce-gtid-consistency=on`<br>`--server-id={unique_id}`<br>`--log-bin=mysql-binlog`<br>`--binlog-format=row`<br>`--binlog-row-image=full`<br>`--log-slave-updates=ON` |
206165
| MySQL 5.7 | `--gtid-mode=on`<br>`--enforce-gtid-consistency=on`<br>`--binlog-row-image=full`<br>`--server-id={unique_id}`<br>`--log-bin=log-bin` |
207166
| MySQL 8.0+ | `--gtid-mode=on`<br>`--enforce-gtid-consistency=on`<br>`--binlog-row-metadata=full` |
208167
| MariaDB | `--log-bin`<br>`--server_id={unique_id}`<br>`--log-basename=master1`<br>`--binlog-format=row`<br>`--binlog-row-metadata=full` |
209-
210-
##### Verify MySQL GTID setup
211-
212-
Get the current GTID set to use as the starting point for replication:
213-
214-
{% include_cached copy-clipboard.html %}
215-
~~~ sql
216-
-- For MySQL < 8.0:
217-
SHOW MASTER STATUS;
218-
-- For MySQL 8.0+:
219-
SHOW BINARY LOG STATUS;
220-
~~~
221-
222-
~~~
223-
+---------------+----------+--------------+------------------+-------------------------------------------+
224-
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
225-
+---------------+----------+--------------+------------------+-------------------------------------------+
226-
| binlog.000005 | 197 | | | 77263736-7899-11f0-81a5-0242ac120002:1-38 |
227-
+---------------+----------+--------------+------------------+-------------------------------------------+
228-
~~~
229-
230-
Use the `Executed_Gtid_Set` value for the `--defaultGTIDSet` flag in MOLT Replicator.
231-
232-
To verify that a GTID set is valid and not purged, use the following queries:
233-
234-
{% include_cached copy-clipboard.html %}
235-
~~~ sql
236-
-- Verify the GTID set is in the executed set
237-
SELECT GTID_SUBSET('77263736-7899-11f0-81a5-0242ac120002:1-38', @@GLOBAL.gtid_executed) AS in_executed;
238-
239-
-- Verify the GTID set is not in the purged set
240-
SELECT GTID_SUBSET('77263736-7899-11f0-81a5-0242ac120002:1-38', @@GLOBAL.gtid_purged) AS in_purged;
241-
~~~
242-
243-
If `in_executed` returns `1` and `in_purged` returns `0`, the GTID set is valid for replication.
244168
</section>
245169

246170
<section class="filter-content" markdown="1" data-scope="oracle">
@@ -353,11 +277,11 @@ ON
353277
~~~
354278

355279
~~~
356-
GROUP# MEMBER START_SCN END_SCN
357-
_________ _________________________________________ ____________ ______________________
358-
3 /opt/oracle/oradata/ORCLCDB/redo03.log 1232896 9295429630892703743
359-
2 /opt/oracle/oradata/ORCLCDB/redo02.log 1155042 1232896
360-
1 /opt/oracle/oradata/ORCLCDB/redo01.log 1141934 1155042
280+
GROUP# MEMBER START_SCN END_SCN
281+
_________ _________________________________________ ____________ ______________________
282+
3 /opt/oracle/oradata/ORCLCDB/redo03.log 1232896 9295429630892703743
283+
2 /opt/oracle/oradata/ORCLCDB/redo02.log 1155042 1232896
284+
1 /opt/oracle/oradata/ORCLCDB/redo01.log 1141934 1155042
361285
362286
3 rows selected.
363287
~~~
@@ -377,24 +301,6 @@ CURRENT_SCN
377301
1 row selected.
378302
~~~
379303

380-
##### Get SCNs for replication startup
381-
382-
If you plan to use [initial data load](#start-fetch) followed by [replication](#start-replicator), obtain the correct SCNs **before** starting the initial data load to ensure no active transactions are missed. Run the following queries on the PDB in the order shown:
383-
384-
{% include_cached copy-clipboard.html %}
385-
~~~ sql
386-
-- Query the current SCN from Oracle
387-
SELECT CURRENT_SCN FROM V$DATABASE;
388-
389-
-- Query the starting SCN of the earliest active transaction
390-
SELECT MIN(t.START_SCNB) FROM V$TRANSACTION t;
391-
~~~
392-
393-
Use the results as follows:
394-
395-
- `--scn`: Use the result from the first query (current SCN)
396-
- `--backfillFromSCN`: Use the result from the second query (earliest active transaction SCN). If the second query returns no results, use the result from the first query instead.
397-
398304
Add the redo log files to LogMiner, using the redo log file paths you queried:
399305

400306
{% include_cached copy-clipboard.html %}

src/current/_includes/molt/molt-connection-strings.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ Define the connection strings for the [source](#source-connection-string) and [t
44

55
The `--source` flag specifies the connection string for the source database:
66

7+
{% if page.name != "migrate-bulk-load.md" %}
8+
{{site.data.alerts.callout_info}}
9+
The source connection **must** point to the primary instance (PostgreSQL primary, MySQL primary/master, or Oracle primary). Replicas cannot provide the necessary replication checkpoints and transaction metadata required for ongoing replication.
10+
{{site.data.alerts.end}}
11+
{% endif %}
12+
713
<section class="filter-content" markdown="1" data-scope="postgres">
814
~~~
915
--source 'postgres://{username}:{password}@{host}:{port}/{database}?sslmode=verify-full'
@@ -14,8 +20,6 @@ For example:
1420
~~~
1521
--source 'postgres://migration_user:password@localhost:5432/molt?sslmode=verify-full'
1622
~~~
17-
18-
The source connection must point to the PostgreSQL primary instance, not a read replica.
1923
</section>
2024

2125
<section class="filter-content" markdown="1" data-scope="mysql">

src/current/_includes/molt/molt-install.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ The following binaries are included:
1414
- `molt`
1515
- `replicator`
1616

17-
Both `molt` and `replicator` must be in your current **working directory**.
17+
{{site.data.alerts.callout_success}}
18+
For ease of use, keep both `molt` and `replicator` in your current **working directory**.
19+
{{site.data.alerts.end}}
1820

1921
To display the current version of each binary, run `molt --version` and `replicator --version`.
2022

src/current/_includes/molt/molt-limitations.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
{% if page.name != "migrate-bulk-load.md" %}
1818
#### Replicator limitations
1919

20-
<section class="filter-content" markdown="1" data-scope="postgres">
21-
- Replication modes require write access to the PostgreSQL primary instance. MOLT cannot create replication slots or run replication against a read replica.
22-
</section>
20+
- Replication modes require connection to the primary instance (PostgreSQL primary, MySQL primary/master, or Oracle primary). MOLT cannot obtain replication checkpoints or transaction metadata from replicas.
2321

2422
<section class="filter-content" markdown="1" data-scope="mysql">
2523
- MySQL replication is supported only with [GTID](https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html)-based configurations. Binlog-based features that do not use GTID are not supported.

src/current/_includes/molt/molt-setup.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,32 @@
3737

3838
{% include molt/migration-create-sql-user.md %}
3939

40+
{% if page.name != "migrate-bulk-load.md" %}
41+
### Configure GC TTL
42+
43+
Before starting the [initial data load](#start-fetch), configure the [garbage collection (GC) TTL]({% link {{ site.current_cloud_version }}/configure-replication-zones.md %}#gc-ttlseconds) on the source CockroachDB cluster to ensure that historical data remains available when replication begins. The GC TTL must be long enough to cover the full duration of the data load.
44+
45+
Increase the GC TTL before starting the data load. For example, to set the GC TTL to 24 hours:
46+
47+
{% include_cached copy-clipboard.html %}
48+
~~~ sql
49+
ALTER DATABASE defaultdb CONFIGURE ZONE USING gc.ttlseconds = 86400;
50+
~~~
51+
52+
{{site.data.alerts.callout_info}}
53+
The GC TTL duration must be higher than your expected time for the initial data load.
54+
{{site.data.alerts.end}}
55+
56+
Once replication has started successfully (which automatically protects its own data range), you can restore the GC TTL to its original value. For example, to restore to 5 minutes:
57+
58+
{% include_cached copy-clipboard.html %}
59+
~~~ sql
60+
ALTER DATABASE defaultdb CONFIGURE ZONE USING gc.ttlseconds = 300;
61+
~~~
62+
63+
For details, refer to [Protect Changefeed Data from Garbage Collection]({% link {{ site.current_cloud_version }}/protect-changefeed-data.md %}).
64+
{% endif %}
65+
4066
## Configure Fetch
4167

4268
When you run `molt fetch`, you can configure the following options for data load:
@@ -46,7 +72,7 @@ When you run `molt fetch`, you can configure the following options for data load
4672
- [Table handling mode](#table-handling-mode): Determine how existing target tables are initialized before load.
4773
- [Schema and table filtering](#schema-and-table-filtering): Specify schema and table names to migrate.
4874
- [Data load mode](#data-load-mode): Choose between `IMPORT INTO` and `COPY FROM`.
49-
- [Fetch metrics](#fetch-metrics): Configure metrics collection during the load.
75+
- [Fetch metrics](#fetch-metrics): Configure metrics collection during initial data load.
5076

5177
### Connection strings
5278

src/current/_includes/molt/molt-troubleshooting.md

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,11 @@ If you shut down `molt` or `replicator` unexpectedly (e.g., with `kill -9` or a
8787
<section class="filter-content" markdown="1" data-scope="postgres">
8888
##### Unable to create publication or slot
8989

90-
This error occurs when the source database does not support logical replication.
90+
This error occurs when logical replication is not supported.
9191

92-
**Resolution:** Verify that the source database supports logical replication by checking the `wal_level` parameter on PostgreSQL:
92+
**Resolution:** If you are connected to a replica, connect to the primary instance instead. Replicas cannot create or manage logical replication slots or publications.
93+
94+
Verify that the source database supports logical replication by checking the `wal_level` parameter on PostgreSQL:
9395

9496
{% include_cached copy-clipboard.html %}
9597
~~~ sql
@@ -154,23 +156,35 @@ run SELECT pg_create_logical_replication_slot('molt_slot', 'pgoutput'); in sourc
154156
~~~ sql
155157
SELECT pg_create_logical_replication_slot('molt_slot', 'pgoutput');
156158
~~~
159+
</section>
157160

158161
{% if page.name == "migrate-resume-replication.md" %}
159162
##### Resuming from stale location
160163

161-
**Resolution:** Clear the `_replicator.memo` table to remove stale LSN (log sequence number) checkpoints:
164+
<section class="filter-content" markdown="1" data-scope="postgres">
165+
For PostgreSQL, the replication slot on the source database tracks progress automatically. Clearing the memo table is only necessary if the replication slot was destroyed and you need to restart replication from a specific LSN.
166+
167+
**Resolution:** Clear the `_replicator.memo` table:
168+
</section>
169+
170+
<section class="filter-content" markdown="1" data-scope="mysql">
171+
**Resolution:** Clear the `_replicator.memo` table to remove stale GTID checkpoints:
172+
</section>
173+
174+
<section class="filter-content" markdown="1" data-scope="oracle">
175+
**Resolution:** Clear the `_replicator.memo` table to remove stale SCN (System Change Number) checkpoints:
176+
</section>
162177

163178
{% include_cached copy-clipboard.html %}
164179
~~~ sql
165180
DELETE FROM _replicator.memo WHERE true;
166181
~~~
167182
{% endif %}
168-
</section>
169183

170184
<section class="filter-content" markdown="1" data-scope="mysql">
171185
##### Repeated binlog syncing restarts
172186

173-
If Replicator repeatedly restarts binlog syncing, this indicates an invalid or purged GTID.
187+
If Replicator repeatedly restarts binlog syncing or starts replication from an unexpectedly old location, this indicates an invalid or purged GTID. When an invalid GTID is provided, the binlog syncer will fall back to the first valid GTID.
174188

175189
**Resolution:** Verify the GTID set is valid and **not** purged:
176190

@@ -209,6 +223,16 @@ If the GTID is purged or invalid, follow these steps:
209223
SHOW BINARY LOG STATUS;
210224
~~~
211225

226+
~~~
227+
+---------------+----------+--------------+------------------+-------------------------------------------+
228+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
229+
+---------------+----------+--------------+------------------+-------------------------------------------+
230+
| binlog.000005 | 197 | | | 77263736-7899-11f0-81a5-0242ac120002:1-38 |
231+
+---------------+----------+--------------+------------------+-------------------------------------------+
232+
~~~
233+
234+
Use the `Executed_Gtid_Set` value for the `--defaultGTIDSet` flag.
235+
212236
##### Invalid GTID format
213237

214238
Invalid GTIDs can occur when GTIDs are purged due to insufficient binlog retention, when connecting to a replica instead of the primary host, or when passing a GTID that has valid format but doesn't exist in the binlog history.
@@ -276,7 +300,7 @@ WARNING: warning during tryCommit: ERROR: duplicate key value violates unique co
276300
ERROR: maximum number of retries (10) exceeded
277301
~~~
278302

279-
**Resolution:** Check target database constraints and connection stability. MOLT Replicator will log warnings for each retry attempt and surface a final error after exhausting all retry attempts, then restart the apply loop to continue processing.
303+
**Resolution:** Check target database constraints and connection stability. MOLT Replicator will log warnings for each retry attempt. If you see warnings but no final error, the apply succeeded after retrying. If all retry attempts are exhausted, Replicator will surface a final error and restart the apply loop to continue processing.
280304

281305
##### CockroachDB changefeed connection issues
282306

0 commit comments

Comments
 (0)