From 3521d6f924c6cbba042d95ab6211e7ca41c61cd7 Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Thu, 20 Nov 2025 14:42:45 -0500 Subject: [PATCH 01/15] Migration docs restructure --- src/current/_includes/molt/molt-docker.md | 2 +- .../molt/molt-drop-constraints-indexes.md | 2 +- src/current/_includes/molt/molt-install.md | 4 +- src/current/_includes/sidebar-data-v25.4.json | 1 + .../v25.4/sidebar-data/migrate-new.json | 234 +++++ .../_includes/v25.4/sidebar-data/migrate.json | 2 +- src/current/images/molt/molt_flows_1.svg | 856 +++++++++++++++ src/current/images/molt/molt_flows_2.svg | 699 +++++++++++++ src/current/molt/migrate-bulk-load.md | 10 +- .../molt/migration-considerations-cutover.md | 8 + .../molt/migration-considerations-phases.md | 174 +++ .../migration-considerations-replication.md | 8 + .../molt/migration-considerations-rollback.md | 8 + ...migration-considerations-transformation.md | 8 + .../migration-considerations-validation.md | 8 + src/current/molt/migration-considerations.md | 100 ++ src/current/molt/migration-overview.md | 87 +- src/current/molt/migration-strategy.md | 4 +- src/current/molt/molt-fetch-best-practices.md | 68 ++ src/current/molt/molt-fetch-flags.md | 84 ++ src/current/molt/molt-fetch-install.md | 49 + src/current/molt/molt-fetch-monitoring.md | 30 + src/current/molt/molt-fetch-overview.md | 140 +++ .../molt/molt-fetch-troubleshooting.md | 20 + src/current/molt/molt-fetch-usage.md | 667 ++++++++++++ src/current/molt/molt-fetch.md | 987 ------------------ 26 files changed, 3242 insertions(+), 1018 deletions(-) create mode 100644 src/current/_includes/v25.4/sidebar-data/migrate-new.json create mode 100644 src/current/images/molt/molt_flows_1.svg create mode 100644 src/current/images/molt/molt_flows_2.svg create mode 100644 src/current/molt/migration-considerations-cutover.md create mode 100644 src/current/molt/migration-considerations-phases.md create mode 100644 src/current/molt/migration-considerations-replication.md create mode 100644 src/current/molt/migration-considerations-rollback.md create mode 100644 src/current/molt/migration-considerations-transformation.md create mode 100644 src/current/molt/migration-considerations-validation.md create mode 100644 src/current/molt/migration-considerations.md create mode 100644 src/current/molt/molt-fetch-best-practices.md create mode 100644 src/current/molt/molt-fetch-flags.md create mode 100644 src/current/molt/molt-fetch-install.md create mode 100644 src/current/molt/molt-fetch-monitoring.md create mode 100644 src/current/molt/molt-fetch-overview.md create mode 100644 src/current/molt/molt-fetch-troubleshooting.md create mode 100644 src/current/molt/molt-fetch-usage.md diff --git a/src/current/_includes/molt/molt-docker.md b/src/current/_includes/molt/molt-docker.md index 0e02705974b..2c9133f5c65 100644 --- a/src/current/_includes/molt/molt-docker.md +++ b/src/current/_includes/molt/molt-docker.md @@ -2,7 +2,7 @@ MOLT Fetch, Verify, and Replicator are likely to run more slowly in a Docker container than on a local machine. To improve performance, increase the memory or compute resources, or both, on your Docker container. -{% if page.name == "molt-fetch.md" %} +{% if page.name == "molt-fetch.md" or page.name == "molt-fetch-install.md" %} #### Authentication When using MOLT Fetch with [cloud storage](#bucket-path), it is necessary to specify volumes and environment variables, as described in the following sections for [Google Cloud Storage](#google-cloud-storage) and [Amazon S3](#amazon-s3). diff --git a/src/current/_includes/molt/molt-drop-constraints-indexes.md b/src/current/_includes/molt/molt-drop-constraints-indexes.md index a6456d779fa..6f5a843591f 100644 --- a/src/current/_includes/molt/molt-drop-constraints-indexes.md +++ b/src/current/_includes/molt/molt-drop-constraints-indexes.md @@ -1,5 +1,5 @@ To optimize data load performance, drop all non-`PRIMARY KEY` [constraints]({% link {{ site.current_cloud_version }}/alter-table.md %}#drop-constraint) and [indexes]({% link {{site.current_cloud_version}}/drop-index.md %}) on the target CockroachDB database before migrating: -{% if page.name == "molt-fetch.md" %} +{% if page.name == "molt-fetch.md" or page.name == "molt-fetch-best-practices.md" %} - [`FOREIGN KEY`]({% link {{ site.current_cloud_version }}/foreign-key.md %}) - [`UNIQUE`]({% link {{ site.current_cloud_version }}/unique.md %}) - [Secondary indexes]({% link {{ site.current_cloud_version }}/schema-design-indexes.md %}) diff --git a/src/current/_includes/molt/molt-install.md b/src/current/_includes/molt/molt-install.md index 86b224ba26f..5caea9cd208 100644 --- a/src/current/_includes/molt/molt-install.md +++ b/src/current/_includes/molt/molt-install.md @@ -22,7 +22,7 @@ To display the current version of each binary, run `molt --version` and `replica For previous binaries, refer to the [MOLT version manifest](https://molt.cockroachdb.com/molt/cli/versions.html). {% if page.name != "molt.md" %}For release details, refer to the [MOLT changelog]({% link releases/molt.md %}).{% endif %} -{% if page.name == "molt-fetch.md" or page.name == "molt.md" %} +{% if page.name == "molt-fetch.md" or page.name == "molt.md" or page.name == "molt-fetch-install" %} {{site.data.alerts.callout_info}} MOLT Fetch is supported on Red Hat Enterprise Linux (RHEL) 9 and above. {{site.data.alerts.end}} @@ -55,7 +55,7 @@ docker pull cockroachdb/molt:oracle-latest ~~~ {% endif %} -{% if page.name != "molt-fetch.md" %} +{% if page.name != "molt-fetch.md" and page.name != "molt-fetch-install.md" %} #### MOLT Replicator [Docker images for MOLT Replicator](https://hub.docker.com/r/cockroachdb/replicator/tags) are also available as a standalone binary: diff --git a/src/current/_includes/sidebar-data-v25.4.json b/src/current/_includes/sidebar-data-v25.4.json index ab270e056d9..2b7178876fe 100644 --- a/src/current/_includes/sidebar-data-v25.4.json +++ b/src/current/_includes/sidebar-data-v25.4.json @@ -11,6 +11,7 @@ {% include_cached v25.4/sidebar-data/feature-overview.json %}, {% include_cached v25.4/sidebar-data/resilience.json %}, {% include_cached v25.4/sidebar-data/connect-to-cockroachdb.json %}, + {% include_cached v25.4/sidebar-data/migrate-new.json %}, {% include_cached v25.4/sidebar-data/migrate.json %}, {% include_cached v25.4/sidebar-data/cloud-deployments.json %}, {% include_cached v25.4/sidebar-data/self-hosted-deployments.json %}, diff --git a/src/current/_includes/v25.4/sidebar-data/migrate-new.json b/src/current/_includes/v25.4/sidebar-data/migrate-new.json new file mode 100644 index 00000000000..56535be6826 --- /dev/null +++ b/src/current/_includes/v25.4/sidebar-data/migrate-new.json @@ -0,0 +1,234 @@ +{ + "title": "Migrate NEW", + "is_top_level": true, + "items": [ + { + "title": "Overview", + "urls": [ + "/molt/migration-overview.html" + ] + }, + { + "title": "Migration Considerations", + "items": [ + { + "title": "Overview", + "urls": [ + "/molt/migration-considerations.html" + ] + }, + { + "title": "Migration Granularity", + "urls": [ + "/molt/migration-considerations-phases.html" + ] + }, + { + "title": "Continuous Replication", + "urls": [ + "/molt/migration-considerations-replication.html" + ] + }, + { + "title": "Data Transformation Strategy", + "urls": [ + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" + ] + }, + { + "title": "Cutover Plan", + "urls": [ + "/molt/migration-considerations-cutover.html" + ] + } + ] + }, + { + "title": "MOLT Tools", + "items": [ + { + "title": "Schema Conversion Tool", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Fetch", + "items": [ + { + "title": "Overview", + "urls": [ + "/molt/molt-fetch-overview.html" + ] + }, + { + "title": "Install MOLT Fetch", + "urls": [ + "/molt/molt-fetch-install.html" + ] + }, + { + "title": "Global Flags", + "urls": [ + "/molt/molt-fetch-flags.html" + ] + }, + { + "title": "Use MOLT Fetch", + "urls": [ + "/molt/molt-fetch-usage.html" + ] + }, + { + "title": "Monitoring", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } + ] + }, + { + "title": "Replicator", + "urls": [ + "/molt/molt-replicator.html" + ] + }, + { + "title": "Verify", + "urls": [ + "/molt/molt-verify.html" + ] + } + ] + }, + { + "title": "Migration Walkthroughs", + "items": [ + { + "title": "Migration with Downtime", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Near-zero Downtime Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Near-zero Downtime Migration with Failback", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, + { + "title": "Third-Party Migration Tools", + "items": [ + { + "title": "AWS DMS", + "urls": [ + "/${VERSION}/aws-dms.html" + ] + }, + { + "title": "Qlik Replicate", + "urls": [ + "/${VERSION}/qlik.html" + ] + }, + { + "title": "Striim", + "urls": [ + "/${VERSION}/striim.html" + ] + }, + { + "title": "Oracle GoldenGate", + "urls": [ + "/${VERSION}/goldengate.html" + ] + }, + { + "title": "Debezium", + "urls": [ + "/${VERSION}/debezium.html" + ] + } + ] + }, + { + "title": "Migrate Data Types", + "items": [ + { + "title": "Migrate from CSV", + "urls": [ + "/${VERSION}/migrate-from-csv.html" + ] + }, + { + "title": "Migrate from Avro", + "urls": [ + "/${VERSION}/migrate-from-avro.html" + ] + }, + { + "title": "Migrate from Shapefiles", + "urls": [ + "/${VERSION}/migrate-from-shapefiles.html" + ] + }, + { + "title": "Migrate from OpenStreetMap", + "urls": [ + "/${VERSION}/migrate-from-openstreetmap.html" + ] + }, + { + "title": "Migrate from GeoJSON", + "urls": [ + "/${VERSION}/migrate-from-geojson.html" + ] + }, + { + "title": "Migrate from GeoPackage", + "urls": [ + "/${VERSION}/migrate-from-geopackage.html" + ] + }, + { + "title": "Import Performance Best Practices", + "urls": [ + "/${VERSION}/import-performance-best-practices.html" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/current/_includes/v25.4/sidebar-data/migrate.json b/src/current/_includes/v25.4/sidebar-data/migrate.json index 77b969311fb..fa93667573b 100644 --- a/src/current/_includes/v25.4/sidebar-data/migrate.json +++ b/src/current/_includes/v25.4/sidebar-data/migrate.json @@ -1,5 +1,5 @@ { - "title": "Migrate", + "title": "Migrate OLD", "is_top_level": true, "items": [ { diff --git a/src/current/images/molt/molt_flows_1.svg b/src/current/images/molt/molt_flows_1.svg new file mode 100644 index 00000000000..c730a6f84ca --- /dev/null +++ b/src/current/images/molt/molt_flows_1.svg @@ -0,0 +1,856 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/current/images/molt/molt_flows_2.svg b/src/current/images/molt/molt_flows_2.svg new file mode 100644 index 00000000000..d965814883e --- /dev/null +++ b/src/current/images/molt/molt_flows_2.svg @@ -0,0 +1,699 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/current/molt/migrate-bulk-load.md b/src/current/molt/migrate-bulk-load.md index 666e5d1ac31..5f90f8c0b50 100644 --- a/src/current/molt/migrate-bulk-load.md +++ b/src/current/molt/migrate-bulk-load.md @@ -9,13 +9,19 @@ Perform a one-time bulk load of source data into CockroachDB. {% include molt/crdb-to-crdb-migration.md %} +## Migration sequence + +
+MOLT tooling overview +
+ {% include molt/molt-setup.md %} ## Start Fetch Perform the bulk load of the source data. -1. Run the [MOLT Fetch]({% link molt/molt-fetch.md %}) command to move the source data into CockroachDB. This example command passes the source and target connection strings [as environment variables](#secure-connections), writes [intermediate files](#intermediate-file-storage) to S3 storage, and uses the `truncate-if-exists` [table handling mode](#table-handling-mode) to truncate the target tables before loading data. It limits the migration to a single schema and filters for three specific tables. The [data load mode](#data-load-mode) defaults to `IMPORT INTO`. Include the `--ignore-replication-check` flag to skip replication checkpoint queries, which eliminates the need to configure the source database for logical replication. +1. Run the [MOLT Fetch]({% link molt/molt-fetch-overview.md %}) command to move the source data into CockroachDB. This example command passes the source and target connection strings [as environment variables](#secure-connections), writes [intermediate files](#intermediate-file-storage) to S3 storage, and uses the `truncate-if-exists` [table handling mode](#table-handling-mode) to truncate the target tables before loading data. It limits the migration to a single schema and filters for three specific tables. The [data load mode](#data-load-mode) defaults to `IMPORT INTO`. Include the `--ignore-replication-check` flag to skip replication checkpoint queries, which eliminates the need to configure the source database for logical replication.
{% include_cached copy-clipboard.html %} @@ -85,6 +91,6 @@ Perform a cutover by resuming application traffic, now to CockroachDB. - [Migration Overview]({% link molt/migration-overview.md %}) - [Migration Strategy]({% link molt/migration-strategy.md %}) - [MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}) -- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [MOLT Fetch]({% link molt/molt-fetch-overview.md %}) - [MOLT Verify]({% link molt/molt-verify.md %}) - [Migration Failback]({% link molt/migrate-failback.md %}) \ No newline at end of file diff --git a/src/current/molt/migration-considerations-cutover.md b/src/current/molt/migration-considerations-cutover.md new file mode 100644 index 00000000000..eac110f84d2 --- /dev/null +++ b/src/current/molt/migration-considerations-cutover.md @@ -0,0 +1,8 @@ +--- +title: Cutover Plan +summary: Learn about the different approaches to cutover, and how to think about this for your migration. +toc: true +docs_area: migrate +--- + +TBD \ No newline at end of file diff --git a/src/current/molt/migration-considerations-phases.md b/src/current/molt/migration-considerations-phases.md new file mode 100644 index 00000000000..e14a625fb0d --- /dev/null +++ b/src/current/molt/migration-considerations-phases.md @@ -0,0 +1,174 @@ +--- +title: Migration Granularity +summary: Learn how to think about phased data migration, and whether or not to approach your migration in phases. +toc: true +docs_area: migrate +--- + +Choosing between a **bulk migration** (migrating all data at once) and a **phased migration** (migrating data in slices) is one of the most important decisions in your CockroachDB migration plan. This page explains when to choose each approach, how to define phases, and how to use MOLT tools effectively in either context. For end-to-end sequencing, see []. + +In general: + +* Choose a **bulk migration** if you can fit the entire migration sequence within a planned downtime window, your data volume is modest, and external integrations are simple. + +* Choose a **phased migration** if your data volume is large or if need to limit risk and downtime blast radius, or you can naturally partition workload by tenant, service/domain, table/shard, geography, or time. Use MOLT Fetch for initial loads per slice, MOLT Replicator for ongoing changes, MOLT Verify for per-slice checks, and perform many small cutovers instead of one big bang. + +--- + +### How to think about “phases” +Here are some common ways to divide migrations: + +* **Per-tenant**: Multi-tenant apps route traffic and data per customer/tenant. Migrate a small cohort first (canary), then progressively larger cohorts. This aligns with access controls and isolates blast radius. + +* **Per-service/domain**: In microservice architectures, migrate data owned by a service or domain (e.g., billing, catalog) and route only that service to CockroachDB while others continue on the source. Requires clear data ownership and integration contracts. + +* **Per-table or shard**: Start with non-critical tables, large-but-isolated tables, or shard ranges. For monolith schemas, you can still phase by tables with few foreign-key dependencies and clear read/write paths. + +* **Per-region/market**: If traffic is regionally segmented, migrate one region/market at a time and validate latency, capacity, and routing rules before expanding. + +Tips for picking slices: + +* Prefer slices with clear routing keys (tenant_id, region_id) to simplify cutover and verification. + +* Start with lower-risk/impact slices to exercise the toolchain and runbooks before high-value cohorts. + +* Ensure each slice has an explicit rollback option and a measurable definition of “done” (schema parity, row counts/checksums, app SLOs). + +--- + +### Tradeoffs: Bulk vs. Phased +The table below captures the core differences. + +| Factor | Bulk migration | Phased migration | +|---|---|---| +| Downtime | Single, longer window; must fit full load + index build | Multiple short windows; can achieve minimal downtime per slice via replication | +| Risk | Higher blast radius if issues surface post-cutover | Lower blast radius; issues confined to a slice | +| Complexity | Simpler orchestration; one cutover | More orchestration; repeated verify and cutover steps | +| Validation | One-time, system-wide | Iterative per slice; faster feedback loops | +| Timeline | Shorter elapsed run if everything fits | Longer calendar time but safer path | +| Best for | Small/medium datasets, simple integrations, tolerant of planned downtime | Multi-tenant/sharded/microservice estates, low downtime tolerance, risk-averse programs | + +Bulk loads and minimal-downtime flows are supported natively by MOLT; see the dedicated flow pages for detailed steps. + +--- + +## MOLT toolkit support + +#### Bulk migration (all-at-once) +When: You can complete the full data load and post-load steps within the maintenance window. + +Tool pattern: + +1) **Schema conversion**: Generate CockroachDB DDL with the Schema Conversion Tool (SCT), apply DDL, and drop secondary indexes/constraints that slow load (you’ll rebuild later). + +2) **Initial load**: Run **MOLT Fetch** in data-load mode to bulk-ingest the entire dataset. + +3) **Pre-cutover verify**: Run **MOLT Verify** for row counts/checksums and schema parity before you expose the target to traffic. + +4) **Finalize schema**: Recreate indexes/constraints that were deferred to accelerate load. + +5) **Cutover**: Redirect application traffic to CockroachDB; no replication is required in a pure bulk flow. + +Notes: + +* If your “bulk” window is tight, consider “load then replicate” even for a single-shot migration; it reduces write pause during cutover by draining replication rather than loading everything during downtime. + +#### Phased migration (sliced) +When: You want to reduce risk, limit downtime blast radius, and/or leverage natural partitions (tenants/services/tables/shards/regions). + +Per-slice loop: + +1) **Define the slice**: Specify the routing key and all tables touched by the slice (including reference/lookup tables). Document read/write paths and dependencies. + +2) **Schema conversion once; parameterize per slice**: Run SCT to produce target DDL; apply once. If you need per-slice variants (e.g., tenant-specific objects), template them. + +3) **Initial load for the slice**: Use **MOLT Fetch** to move only the slice’s rows (via filters/selection); for large tables, consider range-based or predicate-based extraction. + +4) **Start continuous replication**: Enable **MOLT Replicator** to stream ongoing changes from source to CockroachDB for just that slice. Let lag stabilize. + +5) **Per-slice verification**: Run **MOLT Verify** focused on the slice (row counts, checksums, schema), and—optionally—semantic checks at the app layer (read-your-writes, idempotency behavior, latency). + +6) **Micro-cutover**: Pause writes for the slice (e.g., drain tenant/service traffic), wait for replication to drain, then route that slice to CockroachDB. Keep replication running temporarily for safety or to support failback policies. + +7) **Rinse and repeat**: Expand to the next slice as confidence grows. Keep a clear rollback runbook per slice. When all slices are moved, disable replication and decommission the source. + +Notes: + +* If business requires a back-out path during or after cutover, configure **failback** mode to replicate from CockroachDB back to the source until the rollback window expires. + +* Treat each slice as a rehearsal—tune cluster sizing, indexing, and app configuration iteratively based on observations. + +--- + +### Cutover considerations (both approaches) +Regardless of approach: + +* Plan and rehearse cutover, including DNS/connection string flips, credential rotation, feature flags, and cache invalidation paths. + +* For minimal downtime, combine “initial load + continuous replication,” then briefly pause writes to drain replication before finalizing cutover; the pause length depends on write volume and replication lag. + +* Define a clear rollback plan. With replicator failback, you can synchronize CockroachDB-side changes back to the source to restore service quickly if needed. + +--- + +### Choosing the right approach: a quick rubric +Score each item 1–5; higher totals favor phased migrations. + +* Data volume and size of indexes are too large for your maintenance window. + +* Application is mission-critical; downtime tolerance is near-zero or seconds. + +* Estate is naturally partitioned (tenants/services/shards/regions), enabling isolated routing. + +* High integration surface area (ETL, reporting, downstream consumers) increases change risk. + +* Organization prefers incremental risk and progressive validation over a one-time event. + +If your total is high, phase it. If your total is low and downtime is acceptable, bulk may be simpler. + +--- + +### Example blueprints + +#### Bulk (planned downtime) +* SCT -> apply DDL (defer secondary indexes) + +* Fetch (data-load) full dataset + +* Verify (counts/checksums) + +* Rebuild indexes; smoke test + +* Cutover all traffic to CockroachDB + +#### Phased (per-tenant) +* Choose 5 low-risk tenants as canary + +* SCT once; apply DDL + +* Fetch tenant rows; start Replicator for those tenants + +* Verify per tenant; drain and cut over tenant traffic + +* Repeat with larger cohorts; disable Replicator after final cohort + +--- + +### MOLT references +* Migration Overview: sequencing and tool roles. + +* Migration Strategy: planning downtime, validation, and cutover. + +* Migrate to CockroachDB: flow-specific guidance including bulk load, load and replicate, resume replication, and failback. + +--- + +### Appendix: FAQ +Q: Can I mix bulk and phased? +A: Yes. Many teams bulk-load non-critical/static tables during a short window, and phase live/critical tables with replication and micro-cutovers. + +Q: How do I pick the first slice? +A: Choose a slice with clear routing keys, moderate data volume, and limited dependencies—often a low-risk tenant or a service-owned table set. This maximizes learning with minimal blast radius. + +Q: When should I enable failback? +A: For mission-critical workloads or when organizational risk tolerance requires a rollback window after cutover. Keep failback replication running until SLAs are met and stakeholders sign off. diff --git a/src/current/molt/migration-considerations-replication.md b/src/current/molt/migration-considerations-replication.md new file mode 100644 index 00000000000..e90dc40e996 --- /dev/null +++ b/src/current/molt/migration-considerations-replication.md @@ -0,0 +1,8 @@ +--- +title: Continuous Replication +summary: Learn about continuous replication, and how it might be useful for a data migration. +toc: true +docs_area: migrate +--- + +TBD \ No newline at end of file diff --git a/src/current/molt/migration-considerations-rollback.md b/src/current/molt/migration-considerations-rollback.md new file mode 100644 index 00000000000..da38fa50b86 --- /dev/null +++ b/src/current/molt/migration-considerations-rollback.md @@ -0,0 +1,8 @@ +--- +title: Rollback Plan +summary: Learn why it might be useful to have a rollback plan in case something goes wrong in the middle of a migration. +toc: true +docs_area: migrate +--- + +TBD \ No newline at end of file diff --git a/src/current/molt/migration-considerations-transformation.md b/src/current/molt/migration-considerations-transformation.md new file mode 100644 index 00000000000..b911679ed09 --- /dev/null +++ b/src/current/molt/migration-considerations-transformation.md @@ -0,0 +1,8 @@ +--- +title: Data Transformation Strategy +summary: Learn about the different approaches to applying data transformations during a migration. +toc: true +docs_area: migrate +--- + +TBD \ No newline at end of file diff --git a/src/current/molt/migration-considerations-validation.md b/src/current/molt/migration-considerations-validation.md new file mode 100644 index 00000000000..dc5d50e7e39 --- /dev/null +++ b/src/current/molt/migration-considerations-validation.md @@ -0,0 +1,8 @@ +--- +title: Validation Strategy +summary: Learn what different validation strategies can be used when migrating data. +toc: true +docs_area: migrate +--- + +TBD \ No newline at end of file diff --git a/src/current/molt/migration-considerations.md b/src/current/molt/migration-considerations.md new file mode 100644 index 00000000000..4c4fd98ac24 --- /dev/null +++ b/src/current/molt/migration-considerations.md @@ -0,0 +1,100 @@ +--- +title: Migration Considerations +summary: Learn what to consider when making high-level decisions about a migration. +toc: true +docs_area: migrate +--- + +When planning a migration to CockroachDB, you need to make several high-level decisions that will shape your migration approach. This page provides an overview of key migration variables and the factors that influence them. Each variable has multiple options, and the combination you choose will largely define your migration strategy. + +For detailed migration sequencing and tool usage, see [Migration Overview]({% link molt/migration-overview.md %}). For detailed planning guidance, see [Migration Strategy]({% link molt/migration-strategy.md %}). + +## Migration variables + +Learn more about each migration variable by clicking the links in the left-hand column. + +| Variable | Description | Options | +|---|---|---| +| [**Migration granularity**]({% link molt/migration-considerations-phases.md %}) | Do you want to migrate all of your data at once, or do you want to split your data up into phases and migrate one phase at a time? | - All at once
- Phased | +| [**Continuous replication**]({% link molt/migration-considerations-replication.md %}) | After the initial data load (or after the initial load of each phase), do you want to stream further changes to that data from the source to the target? | - Bulk load only
- Continuous replication | +| [**Data transformation strategy**]({% link molt/migration-considerations-transformation.md %}) | If there are discrepancies between the source and target schema, how will you define those data transformations, and when will those transformations occur? | - No data transformation
- Transform at source
- Tranform in flight
- Transform at target | +| [**Validation strategy**]({% link molt/migration-considerations-validation.md %}) | How and when will you verify that the data in CockroachDB matches the source database? | - After initial load
During sync
After cutover
QA sign-off | +| [**Rollback plan**]({% link molt/migration-considerations-rollback.md %}) | What approach will you use to roll back the migration if issues arise during or after cutover? | - Dual-write
- Bidirectional replication
- Failback (reverse replication)
- Manual reconciliation | +| [**Cutover strategy**]({% link molt/migration-considerations-cutover.md %}) | How will you transition application traffic from the source database to CockroachDB? | - Big-bang cutover
- Minimal-downtime cutover (with replication)
- Progressive cutover (per-slice) | + +The combination of these variables largely defines your migration approach. While you'll typically choose one primary option for each variable, some migrations may involve a hybrid approach depending on your specific requirements. + +## Things to consider + +When deciding on the options for each migration variable, consider the following business and technical requirements: + +### Allowable downtime + +How much downtime can your application tolerate during the migration? This is one of the most critical factors in determining your migration approach: + +- **Planned downtime**: If you can take the application offline for several hours or more, a simpler bulk load approach may be sufficient. You can load all data during the downtime window, verify it, and then bring the application back online on CockroachDB. + +- **Minimal downtime**: If you need to minimize user impact (ideally to seconds or minutes), you'll need to use continuous replication to keep CockroachDB synchronized with the source database. Application writes are paused only briefly to allow the replication stream to drain before cutover. + +- **Zero downtime**: For mission-critical applications that cannot tolerate any downtime, consider a phased migration where you progressively move slices of data (e.g., per-tenant or per-service) while maintaining dual-write capabilities or bidirectional replication. + +Your downtime tolerance will influence your choices for data transfer approach, validation strategy, and cutover strategy. + +### Migration timeframe + +When do you need to complete the migration, and how does this timeline affect your approach? + +- **Shorter calendar time**: If you need to complete the migration quickly and can tolerate planned downtime, a bulk migration may be the fastest path. However, this concentrates risk into a single event. + +- **Longer calendar time**: If you have more time available, a phased migration allows you to reduce risk by migrating in smaller increments. This takes longer overall but provides faster feedback loops and the ability to adjust your approach based on early results. + +- **Team availability**: Consider when your migration team and stakeholders are available. Can you schedule a migration during off-peak hours or weekends? Do you need to coordinate with multiple teams? + +Your migration timeframe will influence whether you choose a bulk or phased approach, and how aggressively you can schedule cutover windows. + +### Risk tolerance + +How much risk is your organization willing to accept during the migration? + +- **Risk-averse**: Organizations with low risk tolerance should prefer phased migrations that limit the blast radius of any issues. Start with low-risk slices (e.g., a small cohort of tenants or a non-critical service), validate thoroughly, and progressively expand to higher-value workloads. + +- **Risk-tolerant**: If you're comfortable with higher risk and can recover quickly from issues, a bulk migration may be acceptable. This is especially true for development or staging environments, or for applications with strong rollback capabilities. + +- **Rollback requirements**: Does your organization require the ability to roll back the migration after cutover? This will influence your choice of rollback plan (e.g., failback replication vs. manual reconciliation). + +Your risk tolerance will influence your choices for migration granularity, rollback plan, and validation strategy. + +### Allowable migration complexity + +How complex of a migration can your team execute and maintain? + +- **Simple migrations**: Bulk migrations with planned downtime are generally simpler to orchestrate. They involve fewer moving parts and a single cutover event. This is best for teams with limited migration experience or smaller datasets. + +- **Complex migrations**: Phased migrations with continuous replication, per-slice validation, and progressive cutover require more sophisticated orchestration. You'll need to manage replication streams, coordinate multiple cutover windows, and maintain clear rollback runbooks for each slice. This is best for experienced teams managing large-scale or mission-critical migrations. + +- **Team expertise**: Consider your team's familiarity with the MOLT tools, CockroachDB, and migration best practices. Can you dedicate time for dry runs and rehearsals? Do you have monitoring and alerting in place? + +Your team's capacity and expertise will influence the complexity of the migration approach you can successfully execute. + +### Additional factors + +Other factors that may influence your migration decisions: + +- **Data volume**: Larger datasets may require phased migrations to fit within maintenance windows and to manage resource consumption during load. + +- **Application architecture**: Multi-tenant applications, microservices, and sharded databases are natural candidates for phased migrations. Monolithic applications may be better suited to bulk migrations. + +- **Integration surface area**: Applications with many downstream consumers (ETL pipelines, analytics tools, third-party integrations) may benefit from phased migrations to reduce the risk of integration issues. + +- **Compliance and regulatory requirements**: Some industries require specific validation, auditing, or rollback capabilities that will influence your migration approach. + +These factors, along with your specific business requirements and constraints, will help determine which options you choose for each migration variable. It's recommended to document your decisions and the reasoning behind them as part of your migration plan. + +## See also + +- [Migration Overview]({% link molt/migration-overview.md %}) +- [Migration Strategy]({% link molt/migration-strategy.md %}) +- [Bulk vs. Phased Migration]({% link molt/migration-considerations-phases.md %}) +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [MOLT Replicator]({% link molt/molt-replicator.md %}) +- [MOLT Verify]({% link molt/molt-verify.md %}) diff --git a/src/current/molt/migration-overview.md b/src/current/molt/migration-overview.md index 163dc26d8aa..07d901d9df5 100644 --- a/src/current/molt/migration-overview.md +++ b/src/current/molt/migration-overview.md @@ -5,7 +5,9 @@ toc: true docs_area: migrate --- -The MOLT (Migrate Off Legacy Technology) toolkit enables safe, minimal-downtime database migrations to CockroachDB. MOLT combines schema transformation, distributed data load, continuous replication, and row-level validation into a highly configurable workflow that adapts to diverse production environments. +A migration involves transfering data from a pre-existing **source** database onto a **target** CockroachDB cluster. Migrating data is a complex, multi-step process, and a data migration can take many different forms depending on your specific business and technical constraints. + +Cockroach Labs provides a MOLT (Migrate Off Legacy Technology) toolkit to aid in migrations. This page provides an overview of the following: @@ -15,22 +17,36 @@ This page provides an overview of the following: ## Migration sequence -{{site.data.alerts.callout_success}} -Before you begin the migration, review [Migration Strategy]({% link molt/migration-strategy.md %}). -{{site.data.alerts.end}} - A migration to CockroachDB generally follows this sequence: -MOLT tooling overview + + +1. **Assess and discover**: Inventory the source database, flag unsupported features, make a migration plan. +1. **Prepare the environment**: Configure networking, users and permissions, bucket locations, replication settings, and more. +1. **Convert the source schema**: Generate CockroachDB-compatible [DDL]({% link {{ site.current_cloud_version }}/sql-statements.md %}#data-definition-statements). Apply the converted schema to the target database. Drop constraints and indexes to facilitate data load. +1. **Stop application traffic**: Limit user read/write traffic to the source database. _This begins application downtime._ +1. **Load data into CockroachDB**: Bulk load the source data into the CockroachDB cluster. +1. **_(Optional)_ Replicate ongoing changes**: Keep CockroachDB in sync with the source. This may be necessary for migrations that minimize downtime. +1. **Finalize target schema**: Recreate indexes or constraints on CockroachDB that you previously dropped to facilitate data load. +1. **Verify data consistency**: Confirm that the CockroachDB data is consistent with the source. +1. **_(Optional)_ Enable failback**: Replicate data from the target back to the source, enabling a reversion to the source database in the event of migration failure. +1. **Cut over application traffic**: Resume normal application use, with the CockroachDB cluster as the target database. _This ends application downtime._ -1. Prepare the source database: Configure users, permissions, and replication settings as needed. -1. Convert the source schema: Use the [Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}) to generate CockroachDB-compatible [DDL]({% link {{ site.current_cloud_version }}/sql-statements.md %}#data-definition-statements). Apply the converted schema to the target database. Drop constraints and indexes to facilitate data load. -1. Load data into CockroachDB: Use [MOLT Fetch]({% link molt/molt-fetch.md %}) to bulk-ingest your source data. -1. (Optional) Verify consistency before replication: Use [MOLT Verify]({% link molt/molt-verify.md %}) to confirm that the data loaded into CockroachDB is consistent with the source. -1. Finalize target schema: Recreate indexes or constraints on CockroachDB that you previously dropped to facilitate data load. -1. Replicate ongoing changes: Enable continuous replication with [MOLT Replicator]({% link molt/molt-replicator.md %}) to keep CockroachDB in sync with the source. -1. Verify consistency before cutover: Use [MOLT Verify]({% link molt/molt-verify.md %}) to confirm that the CockroachDB data is consistent with the source. -1. Cut over to CockroachDB: Redirect application traffic to the CockroachDB cluster. +The MOLT (Migrate Off Legacy Technology) toolkit enables safe, minimal-downtime database migrations to CockroachDB. MOLT combines schema transformation, distributed data load, continuous replication, and row-level validation into a highly configurable workflow that adapts to diverse production environments. + + +
+MOLT tooling overview +
For more details, refer to [Migration flows](#migration-flows). @@ -110,7 +126,11 @@ The [MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}) - Column definition. - Row-level data. -## Migration flows + + +## Migration considerations + +You must decide how you want your migration to handle each of the following variables. These decisions will depend on your specific business and technical considerations. The MOLT toolkit supports any set of decisions made for the [supported source databases](#molt-tools). -### Bulk load +### Bulk vs. phased migration -For migrations that tolerate downtime, use MOLT Fetch in `data-load` mode to perform a one-time bulk load of source data into CockroachDB. Refer to [Bulk Load]({% link molt/migrate-bulk-load.md %}). +For smaller data stores, it's possible to migrate all of your data onto the target cluster at once. For larger data stores, it's recommended that you do so in phases. This -### Migrations with minimal downtime +Learn more about [phased migrations]({% link molt/migration-considerations-phases.md %}). -To minimize downtime during migration, use MOLT Fetch for initial data loading followed by MOLT Replicator for continuous replication. Instead of loading all data during a planned downtime window, you can run an initial load followed by continuous replication. Writes are paused only briefly to allow replication to drain before the final cutover. The duration of this pause depends on the volume of write traffic and the replication lag between the source and CockroachDB. +### Continuous replication -Refer to [Load and Replicate]({% link molt/migrate-load-replicate.md %}) for detailed instructions. +To minimize downtime during migration, use MOLT Fetch for initial data loading followed by MOLT Replicator for continuous replication. Instead of loading all data during a planned downtime window, you can run an initial load followed by continuous replication. Writes are paused only briefly to allow replication to drain before the final cutover. The duration of this pause depends on the volume of write traffic and the replication lag between the source and CockroachDB. Learn more about [continuous replication]({% link molt/migration-considerations-replication.md %}). -### Recovery and rollback strategies +### Rollback plan If the migration is interrupted or cutover must be aborted, MOLT Replicator provides safe recovery options: - Resume a previously interrupted replication stream. Refer to [Resume Replication]({% link molt/migrate-resume-replication.md %}). - Use failback mode to reverse the migration, synchronizing changes from CockroachDB back to the original source. This ensures data consistency on the source so that you can retry the migration later. Refer to [Migration Failback]({% link molt/migrate-failback.md %}). +### Validation strategy + +[] + +### Cutover plan + +*Cutover* is the process of switching application traffic from the source database to CockroachDB. Once the source data is fully migrated to CockroachDB, switch application traffic to the new database to end downtime. + +MOLT enables [migrations with minimal downtime]({% link molt/migration-overview.md %}#migrations-with-minimal-downtime), using [MOLT Replicator]({% link molt/molt-replicator.md %}) for continuous replication of source changes to CockroachDB. + +To safely cut over when using replication: + +1. Stop application traffic on the source database. +1. Wait for the replication stream to drain. +1. When your [monitoring](#set-up-monitoring-and-alerting) indicates that replication is idle, use [MOLT Verify]({% link molt/molt-verify.md %}) to validate the CockroachDB data. +1. Start application traffic on CockroachDB. + +When you are ready to migrate, refer to [Migration flows]({% link molt/migration-overview.md %}#migration-flows) for a summary of migration types. + ## See also - [Migration Strategy]({% link molt/migration-strategy.md %}) diff --git a/src/current/molt/migration-strategy.md b/src/current/molt/migration-strategy.md index eb2b46f65f5..780033568e5 100644 --- a/src/current/molt/migration-strategy.md +++ b/src/current/molt/migration-strategy.md @@ -147,7 +147,7 @@ To further minimize potential surprises when you conduct the migration, practice Performing a dry run is highly recommended. In addition to demonstrating how long the migration may take, a dry run also helps to ensure that team members understand what they need to do during the migration, and that changes to the application are coordinated. -## Cutover strategy + ## See also diff --git a/src/current/molt/molt-fetch-best-practices.md b/src/current/molt/molt-fetch-best-practices.md new file mode 100644 index 00000000000..873eca5b331 --- /dev/null +++ b/src/current/molt/molt-fetch-best-practices.md @@ -0,0 +1,68 @@ +--- +title: MOLT Fetch Best Practices +summary: Learn the best ways to run MOLT Fetch, considering individual business and technical constraints. +toc: true +docs_area: migrate +--- + +## Security + +Cockroach Labs strongly recommends the following security practices. + +### Connection security + +{% include molt/molt-secure-connection-strings.md %} + +{{site.data.alerts.callout_info}} +By default, insecure connections (i.e., `sslmode=disable` on PostgreSQL; `sslmode` not set on MySQL) are disallowed. When using an insecure connection, `molt fetch` returns an error. To override this check, you can enable the `--allow-tls-mode-disable` flag. Do this **only** when testing, or if a secure SSL/TLS connection to the source or target database is not possible. +{{site.data.alerts.end}} + +### Cloud storage security + +{% include molt/fetch-secure-cloud-storage.md %} + +## Best practices + +### Test and validate + +To verify that your connections and configuration work properly, run MOLT Fetch in a staging environment before migrating any data in production. Use a test or development environment that closely resembles production. + +### Configure the source database and connection + +- To prevent connections from terminating prematurely during the [data export phase](#data-export-phase), set the following to high values on the source database: + + - **Maximum allowed number of connections.** MOLT Fetch can export data across multiple connections. The number of connections it will create is the number of shards ([`--export-concurrency`](#global-flags)) multiplied by the number of tables ([`--table-concurrency`](#global-flags)) being exported concurrently. + + {{site.data.alerts.callout_info}} + With the default numerical range sharding, only tables with [primary key]({% link {{ site.current_cloud_version }}/primary-key.md %}) types of [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) can be sharded. PostgreSQL users can enable [`--use-stats-based-sharding`](#global-flags) to use statistics-based sharding for tables with primary keys of any data type. For details, refer to [Table sharding](#table-sharding). + {{site.data.alerts.end}} + + - **Maximum lifetime of a connection.** + +- If a PostgreSQL database is set as a [source](#source-and-target-databases), ensure that [`idle_in_transaction_session_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT) on PostgreSQL is either disabled or set to a value longer than the duration of the [data export phase](#data-export-phase). Otherwise, the connection will be prematurely terminated. To estimate the time needed to export the PostgreSQL tables, you can perform a dry run and sum the value of [`molt_fetch_table_export_duration_ms`](#monitoring) for all exported tables. + +### Optimize performance + +- {% include molt/molt-drop-constraints-indexes.md %} + +- For PostgreSQL sources using [`--use-stats-based-sharding`](#global-flags), run [`ANALYZE`]({% link {{ site.current_cloud_version }}/create-statistics.md %}) on source tables before migration to ensure optimal shard distribution. This is especially important for large tables where even distribution can significantly improve export performance. + +- To prevent memory outages during `READ COMMITTED` [data export](#data-export-phase) of tables with large rows, estimate the amount of memory used to export a table: + + ~~~ + --row-batch-size * --export-concurrency * average size of the table rows + ~~~ + + If you are exporting more than one table at a time (i.e., [`--table-concurrency`](#global-flags) is set higher than `1`), add the estimated memory usage for the tables with the largest row sizes. Ensure that you have sufficient memory to run `molt fetch`, and adjust `--row-batch-size` accordingly. For details on how concurrency and sharding interact, refer to [Table sharding](#table-sharding). + +- If a table in the source database is much larger than the other tables, [filter and export the largest table](#schema-and-table-selection) in its own `molt fetch` task. Repeat this for each of the largest tables. Then export the remaining tables in another task. + +- Ensure that the machine running MOLT Fetch is large enough to handle the amount of data being migrated. Fetch performance can sometimes be limited by available resources, but should always be making progress. To identify possible resource constraints, observe the `molt_fetch_rows_exported` [metric](#monitoring) for decreases in the number of rows being processed. You can use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view metrics. For details on optimizing export performance through sharding, refer to [Table sharding](#table-sharding). + +### Import and continuation handling + +- When using [`IMPORT INTO`](#data-load-mode) during the [data import phase](#data-import-phase) to load tables into CockroachDB, if the fetch task terminates before the import job completes, the hanging import job on the target database will keep the table offline. To make this table accessible again, [manually resume or cancel the job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs). Then resume `molt fetch` using [continuation](#fetch-continuation), or restart the task from the beginning. + +## See also + +- X diff --git a/src/current/molt/molt-fetch-flags.md b/src/current/molt/molt-fetch-flags.md new file mode 100644 index 00000000000..48913756236 --- /dev/null +++ b/src/current/molt/molt-fetch-flags.md @@ -0,0 +1,84 @@ +--- +title: MOLT Fetch Flags +summary: Reference doc for all of the commands and flags to be used with MOLT Fetch. +toc: true +docs_area: migrate +--- + + +## Commands + +| Command | Usage | +|---------|---------------------------------------------------------------------------------------------------| +| `fetch` | Start the fetch task. This loads data from a source database to a target CockroachDB database. | + +### Subcommands + +| Command | Usage | +|--------------|----------------------------------------------------------------------| +| `tokens list` | List active [continuation tokens](#list-active-continuation-tokens). | + +## Flags + +### Global flags + +| Flag | Description | +|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--source` | (Required) Connection string used to connect to the Oracle PDB (in a CDB/PDB architecture) or to a standalone database (non‑CDB). For details, refer to [Source and target databases](#source-and-target-databases). | +| `--source-cdb` | Connection string for the Oracle container database (CDB) when using a multitenant (CDB/PDB) architecture. Omit this flag on a non‑multitenant Oracle database. For details, refer to [Source and target databases](#source-and-target-databases). | +| `--target` | (Required) Connection string for the target database. For details, refer to [Source and target databases](#source-and-target-databases). | +| `--allow-tls-mode-disable` | Allow insecure connections to databases. Secure SSL/TLS connections should be used by default. This should be enabled **only** if secure SSL/TLS connections to the source or target database are not possible. | +| `--assume-role` | Service account to use for assume role authentication. `--use-implicit-auth` must be included. For example, `--assume-role='user-test@cluster-ephemeral.iam.gserviceaccount.com' --use-implicit-auth`. For details, refer to [Cloud Storage Authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}). | +| `--bucket-path` | The path within the [cloud storage](#bucket-path) bucket where intermediate files are written (e.g., `'s3://bucket/path'` or `'gs://bucket/path'`). Only the URL path is used; query parameters (e.g., credentials) are ignored. To pass in query parameters, use the appropriate flags: `--assume-role`, `--import-region`, `--use-implicit-auth`. | +| `--case-sensitive` | Toggle case sensitivity when comparing table and column names on the source and target. To disable case sensitivity, set `--case-sensitive=false`. If `=` is **not** included (e.g., `--case-sensitive false`), the flag is interpreted as `--case-sensitive` (i.e., `--case-sensitive=true`).

**Default:** `false` | +| `--cleanup` | Whether to delete intermediate files after moving data using [cloud or local storage](#data-path). **Note:** Cleanup does not occur on [continuation](#fetch-continuation). | +| `--compression` | Compression method for data when using [`IMPORT INTO`](#data-load-mode) (`gzip`/`none`).

**Default:** `gzip` | +| `--continuation-file-name` | Restart fetch at the specified filename if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation](#fetch-continuation). | +| `--continuation-token` | Restart fetch at a specific table, using the specified continuation token, if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation](#fetch-continuation). | +| `--crdb-pts-duration` | The duration for which each timestamp used in data export from a CockroachDB source is protected from garbage collection. This ensures that the data snapshot remains consistent. For example, if set to `24h`, each timestamp is protected for 24 hours from the initiation of the export job. This duration is extended at regular intervals specified in `--crdb-pts-refresh-interval`.

**Default:** `24h0m0s` | +| `--crdb-pts-refresh-interval` | The frequency at which the protected timestamp's validity is extended. This interval maintains protection of the data snapshot until data export from a CockroachDB source is completed. For example, if set to `10m`, the protected timestamp's expiration will be extended by the duration specified in `--crdb-pts-duration` (e.g., `24h`) every 10 minutes while export is not complete.

**Default:** `10m0s` | +| `--direct-copy` | Enables [direct copy](#direct-copy), which copies data directly from source to target without using an intermediate store. | +| `--export-concurrency` | Number of shards to export at a time per table, each on a dedicated thread. This controls how many shards are created for each individual table during the [data export phase](#data-export-phase) and is distinct from `--table-concurrency`, which controls how many tables are processed simultaneously. The total number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`. Tables can be sharded with a range-based or stats-based mechanism. For details, refer to [Table sharding](#table-sharding).

**Default:** `4` | +| `--export-retry-max-attempts` | Maximum number of retry attempts for source export queries when connection failures occur. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `3` | +| `--export-retry-max-duration` | Maximum total duration for retrying source export queries. If `0`, no time limit is enforced. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `5m0s` | +| `--filter-path` | Path to a JSON file defining row-level filters for the [data import phase](#data-import-phase). Refer to [Selective data movement](#selective-data-movement). | +| `--fetch-id` | Restart fetch task corresponding to the specified ID. If `--continuation-file-name` or `--continuation-token` are not specified, fetch restarts for all failed tables. | +| `--flush-rows` | Number of rows before the source data is flushed to intermediate files. **Note:** If `--flush-size` is also specified, the fetch behavior is based on the flag whose criterion is met first. | +| `--flush-size` | Size (in bytes) before the source data is flushed to intermediate files. **Note:** If `--flush-rows` is also specified, the fetch behavior is based on the flag whose criterion is met first. | +| `--ignore-replication-check` | Skip querying for replication checkpoints such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle. This option is intended for use during bulk load migrations or when doing a one-time data export from a read replica. | +| `--import-batch-size` | The number of files to be imported at a time to the target database during the [data import phase](#data-import-phase). This applies only when using [`IMPORT INTO`](#data-load-mode) for data movement. **Note:** Increasing this value can improve the performance of full-scan queries on the target database shortly after fetch completes, but very high values are not recommended. If any individual file in the import batch fails, you must [retry](#fetch-continuation) the entire batch.

**Default:** `1000` | +| `--import-region` | The region of the [cloud storage](#bucket-path) bucket. This applies only to [Amazon S3 buckets](#bucket-path). Set this flag only if you need to specify an `AWS_REGION` explicitly when using [`IMPORT INTO`](#data-load-mode) for data movement. For example, `--import-region=ap-south-1`. | +| `--local-path` | The path within the [local file server](#local-path) where intermediate files are written (e.g., `data/migration/cockroach`). `--local-path-listen-addr` must be specified. | +| `--local-path-crdb-access-addr` | Address of a [local file server](#local-path) that is **publicly accessible**. This flag is only necessary if CockroachDB cannot reach the local address specified with `--local-path-listen-addr` (e.g., when moving data to a CockroachDB {{ site.data.products.cloud }} deployment). `--local-path` and `--local-path-listen-addr` must be specified.

**Default:** Value of `--local-path-listen-addr`. | +| `--local-path-listen-addr` | Write intermediate files to a [local file server](#local-path) at the specified address (e.g., `'localhost:3000'`). `--local-path` must be specified. | +| `--log-file` | Write messages to the specified log filename. If no filename is provided, messages write to `fetch-{datetime}.log`. If `"stdout"` is provided, messages write to `stdout`. | +| `--logging` | Level at which to log messages (`trace`/`debug`/`info`/`warn`/`error`/`fatal`/`panic`).

**Default:** `info` | +| `--metrics-listen-addr` | Address of the Prometheus metrics endpoint, which has the path `{address}/metrics`. For details on important metrics to monitor, refer to [Monitoring](#monitoring).

**Default:** `'127.0.0.1:3030'` | +| `--mode` | Configure the MOLT Fetch behavior: `data-load`, `export-only`, or `import-only`. For details, refer to [Fetch mode](#fetch-mode).

**Default:** `data-load` | +| `--non-interactive` | Run the fetch task without interactive prompts. This is recommended **only** when running `molt fetch` in an automated process (i.e., a job or continuous integration). | +| `--pprof-listen-addr` | Address of the pprof endpoint.

**Default:** `'127.0.0.1:3031'` | +| `--row-batch-size` | Number of rows per shard to export at a time. For details on sharding, refer to [Table sharding](#table-sharding). See also [Best practices](#best-practices).

**Default:** `100000` | +| `--schema-filter` | Move schemas that match a specified [regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | +| `--skip-pk-check` | Skip primary-key matching to allow data load when source or target tables have missing or mismatched primary keys. Disables sharding and bypasses `--export-concurrency` and `--row-batch-size` settings. Refer to [Skip primary key matching](#skip-primary-key-matching).

**Default:** `false` | +| `--table-concurrency` | Number of tables to export at a time. The number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`.

**Default:** `4` | +| `--table-exclusion-filter` | Exclude tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

This value **cannot** be set to `'.*'`, which would cause every table to be excluded.

**Default:** Empty string | +| `--table-filter` | Move tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | +| `--table-handling` | How tables are initialized on the target database (`none`/`drop-on-target-and-recreate`/`truncate-if-exists`). For details, see [Target table handling](#target-table-handling).

**Default:** `none` | +| `--transformations-file` | Path to a JSON file that defines transformations to be performed on the target schema during the fetch task. Refer to [Transformations](#transformations). | +| `--type-map-file` | Path to a JSON file that contains explicit type mappings for automatic schema creation, when enabled with `--table-handling drop-on-target-and-recreate`. For details on the JSON format and valid type mappings, see [type mapping](#type-mapping). | +| `--use-console-writer` | Use the console writer, which has cleaner log output but introduces more latency.

**Default:** `false` (log as structured JSON) | +| `--use-copy` | Use [`COPY FROM`](#data-load-mode) to move data. This makes tables queryable during data load, but is slower than using `IMPORT INTO`. For details, refer to [Data movement](#data-load-mode). | +| `--use-implicit-auth` | Use [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}) for [cloud storage](#bucket-path) URIs. | +| `--use-stats-based-sharding` | Enable statistics-based sharding for PostgreSQL sources. This allows sharding of tables with primary keys of any data type and can create more evenly distributed shards compared to the default numerical range sharding. Requires PostgreSQL 11+ and access to `pg_stats`. For details, refer to [Table sharding](#table-sharding). | + + +### `tokens list` flags + +| Flag | Description | +|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------| +| `--conn-string` | (Required) Connection string for the target database. For details, see [List active continuation tokens](#list-active-continuation-tokens). | +| `-n`, `--num-results` | Number of results to return. | + +## See also + +- X \ No newline at end of file diff --git a/src/current/molt/molt-fetch-install.md b/src/current/molt/molt-fetch-install.md new file mode 100644 index 00000000000..a8b720d1e94 --- /dev/null +++ b/src/current/molt/molt-fetch-install.md @@ -0,0 +1,49 @@ +--- +title: MOLT Fetch Installation +summary: Learn how to install the MOLT Fetch tool to move data from a source database to CockroachDB. +toc: true +docs_area: migrate +--- + +## Prerequisites + +### Supported databases + +The following source databases are supported: + +- PostgreSQL 11-16 +- MySQL 5.7, 8.0 and later +- Oracle Database 19c (Enterprise Edition) and 21c (Express Edition) + +### Database configuration + +Ensure that the source and target schemas are identical, unless you enable automatic schema creation with the [`drop-on-target-and-recreate`](#target-table-handling) option. If you are creating the target schema manually, review the behaviors in [Mismatch handling](#mismatch-handling). + +{{site.data.alerts.callout_info}} +MOLT Fetch does not support migrating sequences. If your source database contains sequences, refer to the [guidance on indexing with sequential keys]({% link {{site.current_cloud_version}}/sql-faqs.md %}#how-do-i-generate-unique-slowly-increasing-sequential-numbers-in-cockroachdb). If a sequential key is necessary in your CockroachDB table, you must create it manually. After using MOLT Fetch to load the data onto the target, but before cutover, make sure to update each sequence's current value using [`setval()`]({% link {{site.current_cloud_version}}/functions-and-operators.md %}#sequence-functions) so that new inserts continue from the correct point. +{{site.data.alerts.end}} + +If you plan to use cloud storage for the data migration, follow the steps in [Cloud storage security](#cloud-storage-security). + +### User permissions + +The SQL user running MOLT Fetch requires specific privileges on both the source and target databases: + +| Database | Required Privileges | Details | +|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------| +| PostgreSQL source | | [Create PostgreSQL migration user]({% link molt/migrate-bulk-load.md %}#create-migration-user-on-source-database) | +| MySQL source | | [Create MySQL migration user]({% link molt/migrate-bulk-load.md %}?filters=mysql#create-migration-user-on-source-database) | +| Oracle source | | [Create Oracle migration user]({% link molt/migrate-bulk-load.md %}?filters=oracle#create-migration-user-on-source-database) | +| CockroachDB target | | [Create CockroachDB user]({% link molt/migrate-bulk-load.md %}#create-the-sql-user) | + +## Installation + +{% include molt/molt-install.md %} + +### Docker usage + +{% include molt/molt-docker.md %} + +## See also + +- X \ No newline at end of file diff --git a/src/current/molt/molt-fetch-monitoring.md b/src/current/molt/molt-fetch-monitoring.md new file mode 100644 index 00000000000..18d98b836fe --- /dev/null +++ b/src/current/molt/molt-fetch-monitoring.md @@ -0,0 +1,30 @@ +--- +title: MOLT Fetch Monitoring +summary: Learn how to use the monitoring functionality made available with MOLT Fetch. +toc: true +docs_area: migrate +--- + +## Monitoring + +### Metrics + +By default, MOLT Fetch exports [Prometheus](https://prometheus.io/) metrics at `127.0.0.1:3030/metrics`. You can configure this endpoint with the `--metrics-listen-addr` [flag](#global-flags). + +Cockroach Labs recommends monitoring the following metrics: + +| Metric Name | Description | +|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------| +| `molt_fetch_num_tables` | Number of tables that will be moved from the source. | +| `molt_fetch_num_task_errors` | Number of errors encountered by the fetch task. | +| `molt_fetch_overall_duration` | Duration (in seconds) of the fetch task. | +| `molt_fetch_rows_exported` | Number of rows that have been exported from a table. For example:
`molt_fetch_rows_exported{table="public.users"}` | +| `molt_fetch_rows_imported` | Number of rows that have been imported from a table. For example:
`molt_fetch_rows_imported{table="public.users"}` | +| `molt_fetch_table_export_duration_ms` | Duration (in milliseconds) of a table's export. For example:
`molt_fetch_table_export_duration_ms{table="public.users"}` | +| `molt_fetch_table_import_duration_ms` | Duration (in milliseconds) of a table's import. For example:
`molt_fetch_table_import_duration_ms{table="public.users"}` | + +You can also use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view the preceding metrics. + +## See also + +- X \ No newline at end of file diff --git a/src/current/molt/molt-fetch-overview.md b/src/current/molt/molt-fetch-overview.md new file mode 100644 index 00000000000..d71ffaba7ba --- /dev/null +++ b/src/current/molt/molt-fetch-overview.md @@ -0,0 +1,140 @@ +--- +title: MOLT Fetch Overview +summary: Learn how to use the MOLT Fetch tool to move data from a source database to CockroachDB. +toc: true +docs_area: migrate +--- + +MOLT Fetch moves data from a source database into CockroachDB as part of a [database migration]({% link molt/migration-overview.md %}). + +MOLT Fetch uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to move the source data to cloud storage (Google Cloud Storage, Amazon S3, or Azure Blob Storage), a local file server, or local memory. Once the data is exported, MOLT Fetch loads the data into a target CockroachDB database. For details, refer to [Migration phases](#migration-phases). + +## Terminology + +- *Shard*: A portion of a table's data exported concurrently during the data export phase. Tables are divided into shards to enable parallel processing. For details, refer to [Table sharding](#table-sharding). +- *Continuation token*: An identifier that marks the progress of a fetch task. Used to resume data loading from the point of interruption if a fetch task fails. For details, refer to [Fetch continuation](#fetch-continuation). +- *Intermediate files*: Temporary data files written to cloud storage or a local file server during the data export phase. These files are used to stage exported data before importing it into CockroachDB during the data import phase. For details, refer to [Data path](#data-path). + + +## Migration phases + +MOLT Fetch operates in distinct phases to move data from source databases to CockroachDB. For details on available modes, refer to [Fetch mode](#fetch-mode). + +### Data export phase + +MOLT Fetch connects to the source database and exports table data to intermediate storage. Data is written to [cloud storage](#bucket-path) (Amazon S3, Google Cloud Storage, Azure Blob Storage), a [local file server](#local-path), or [directly to CockroachDB memory](#direct-copy). Multiple tables and table shards can be exported simultaneously using [`--table-concurrency`](#global-flags) and [`--export-concurrency`](#global-flags), with large tables divided into shards for parallel processing. For details, refer to: + +- [Fetch mode](#fetch-mode) +- [Table sharding](#table-sharding) + +### Data import phase + +MOLT Fetch loads the exported data into the target CockroachDB database. The process uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) (faster, tables offline during import) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) (slower, tables remain queryable) to move data. Data files are imported in configurable batches using [`--import-batch-size`](#global-flags), and target tables can be automatically created, truncated, or left unchanged based on [`--table-handling`](#global-flags) settings. For details, refer to: + +- [Data movement](#data-load-mode) +- [Target table handling](#target-table-handling) + +## Common workflows + +### Bulk data load + +To perform a bulk data load migration from your source database to CockroachDB, run the `molt fetch` command with the required flags. + +Specify the source and target database connections. For connection string formats, refer to [Source and target databases](#source-and-target-databases): + +{% include_cached copy-clipboard.html %} +~~~ +--source $SOURCE +--target $TARGET +~~~ + +Specify how to move data to CockroachDB. Use [cloud storage](#bucket-path) for intermediate file storage: + +{% include_cached copy-clipboard.html %} +~~~ +--bucket-path 's3://bucket/path' +~~~ + +Alternatively, use a [local file server](#local-path) for intermediate storage: + +{% include_cached copy-clipboard.html %} +~~~ +--local-path /migration/data/cockroach +--local-path-listen-addr 'localhost:3000' +~~~ + +Alternatively, use [direct copy](#direct-copy) to move data directly without intermediate storage: + +{% include_cached copy-clipboard.html %} +~~~ +--direct-copy +~~~ + +Optionally, filter which schemas and tables to migrate. By default, all schemas and tables are migrated. For details, refer to [Schema and table selection](#schema-and-table-selection): + +{% include_cached copy-clipboard.html %} +~~~ +--schema-filter 'public' +--table-filter '.*user.*' +~~~ + +Specify how to handle target tables. By default, `--table-handling` is set to `none`, which loads data without changing existing data in the tables. For details, refer to [Target table handling](#target-table-handling): + +{% include_cached copy-clipboard.html %} +~~~ +--table-handling truncate-if-exists +~~~ + +When performing a bulk load without subsequent replication, use `--ignore-replication-check` to skip querying for replication checkpoints (such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle). This is appropriate when: + +- Performing a one-time data migration with no plan to replicate ongoing changes. +- Exporting data from a read replica where replication checkpoints are unavailable. + +{% include_cached copy-clipboard.html %} +~~~ +--ignore-replication-check +~~~ + +At minimum, the `molt fetch` command should include the source, target, data path, and `--ignore-replication-check` flags: + +{% include_cached copy-clipboard.html %} +~~~ shell +molt fetch \ +--source $SOURCE \ +--target $TARGET \ +--bucket-path 's3://bucket/path' \ +--ignore-replication-check +~~~ + +For detailed steps, refer to [Bulk load migration]({% link molt/migrate-bulk-load.md %}). + +### Load before replication + +To perform an initial data load before setting up ongoing replication with [MOLT Replicator]({% link molt/molt-replicator.md %}), run the `molt fetch` command without `--ignore-replication-check`. This captures replication checkpoints during the data load. + +The workflow is the same as [Bulk data load](#bulk-data-load), except: + +- Exclude `--ignore-replication-check`. MOLT Fetch will query and record replication checkpoints. +- After the data load completes, check the [CDC cursor](#cdc-cursor) in the output for the checkpoint value to use with MOLT Replicator. + +At minimum, the `molt fetch` command should include the source, target, and data path flags: + +{% include_cached copy-clipboard.html %} +~~~ shell +molt fetch \ +--source $SOURCE \ +--target $TARGET \ +--bucket-path 's3://bucket/path' +~~~ + +The output will include a `cdc_cursor` value at the end of the fetch task: + +~~~ json +{"level":"info","type":"summary","fetch_id":"735a4fe0-c478-4de7-a342-cfa9738783dc","num_tables":1,"tables":["public.employees"],"cdc_cursor":"b7f9e0fa-2753-1e1f-5d9b-2402ac810003:3-21","net_duration_ms":4879.890041,"net_duration":"000h 00m 04s","time":"2024-03-18T12:37:02-04:00","message":"fetch complete"} +~~~ + +Use this `cdc_cursor` value when starting MOLT Replicator to ensure replication begins from the correct position. For detailed steps, refer to [Load and replicate]({% link molt/migrate-load-replicate.md %}). + +## See also + +- X \ No newline at end of file diff --git a/src/current/molt/molt-fetch-troubleshooting.md b/src/current/molt/molt-fetch-troubleshooting.md new file mode 100644 index 00000000000..20d9fe9bad8 --- /dev/null +++ b/src/current/molt/molt-fetch-troubleshooting.md @@ -0,0 +1,20 @@ +--- +title: MOLT Fetch Troubleshooting +summary: Learn how to troubleshoot MOLT Fetch, how to handle errors. +toc: true +docs_area: migrate +--- + +## Troubleshooting + +
+ + + +
+ +{% include molt/molt-troubleshooting-fetch.md %} + +## See also + +- X diff --git a/src/current/molt/molt-fetch-usage.md b/src/current/molt/molt-fetch-usage.md new file mode 100644 index 00000000000..d949a6cad2c --- /dev/null +++ b/src/current/molt/molt-fetch-usage.md @@ -0,0 +1,667 @@ +--- +title: MOLT Fetch Usage +summary: Learn how to use MOLT Fetch, including the main flags and commands. +toc: true +docs_area: migrate +--- + +## Usage + +The following sections describe how to use the `molt fetch` [flags](#flags). + +### Source and target databases + +{{site.data.alerts.callout_success}} +Follow the recommendations in [Connection security](#connection-security). +{{site.data.alerts.end}} + +`--source` specifies the connection string of the source database. + +PostgreSQL or CockroachDB connection string: + +{% include_cached copy-clipboard.html %} +~~~ +--source 'postgresql://{username}:{password}@{host}:{port}/{database}' +~~~ + +MySQL connection string: + +{% include_cached copy-clipboard.html %} +~~~ +--source 'mysql://{username}:{password}@{protocol}({host}:{port})/{database}' +~~~ + +Oracle connection string: + +{% include_cached copy-clipboard.html %} +~~~ +--source 'oracle://{username}:{password}@{host}:{port}/{service_name}' +~~~ + +For Oracle Multitenant databases, `--source-cdb` specifies the container database (CDB) connection. `--source` specifies the pluggable database (PDB): + +{% include_cached copy-clipboard.html %} +~~~ +--source 'oracle://{username}:{password}@{host}:{port}/{pdb_service_name}' +--source-cdb 'oracle://{username}:{password}@{host}:{port}/{cdb_service_name}' +~~~ + +`--target` specifies the [CockroachDB connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url): + +{% include_cached copy-clipboard.html %} +~~~ +--target 'postgresql://{username}:{password}@{host}:{port}/{database}' +~~~ + +### Fetch mode + +`--mode` specifies the MOLT Fetch behavior. + +`data-load` (default) instructs MOLT Fetch to load the source data into CockroachDB: + +{% include_cached copy-clipboard.html %} +~~~ +--mode data-load +~~~ + +`export-only` instructs MOLT Fetch to export the source data to the specified [cloud storage](#bucket-path) or [local file server](#local-path). It does not load the data into CockroachDB: + +{% include_cached copy-clipboard.html %} +~~~ +--mode export-only +~~~ + +`import-only` instructs MOLT Fetch to load the source data in the specified [cloud storage](#bucket-path) or [local file server](#local-path) into the CockroachDB target: + +{% include_cached copy-clipboard.html %} +~~~ +--mode import-only +~~~ + +### Data load mode + +MOLT Fetch can use either [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to load data into CockroachDB. + +By default, MOLT Fetch uses `IMPORT INTO`: + +- `IMPORT INTO` achieves the highest throughput, but [requires taking the CockroachDB tables **offline**]({% link {{site.current_cloud_version}}/import-into.md %}#considerations) to achieve its import speed. Tables are taken back online once an [import job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs) completes successfully. See [Best practices](#best-practices). +- `IMPORT INTO` supports compression using the `--compression` flag, which reduces the amount of storage used. + +`--use-copy` configures MOLT Fetch to use `COPY FROM`: + +- `COPY FROM` enables your tables to remain online and accessible. However, it is slower than using [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}). +- `COPY FROM` does not support compression. + +{{site.data.alerts.callout_info}} +`COPY FROM` is also used for [direct copy](#direct-copy). +{{site.data.alerts.end}} + +### Table sharding + +During the [data export phase](#data-export-phase), MOLT Fetch can divide large tables into multiple shards for concurrent export. + +To control the number of shards created per table, use the `--export-concurrency` flag. For example: + +{% include_cached copy-clipboard.html %} +~~~ +--export-concurrency=4 +~~~ + +{{site.data.alerts.callout_success}} +For performance considerations with concurrency settings, refer to [Best practices](#best-practices). +{{site.data.alerts.end}} + +Two sharding mechanisms are available: + +- **Range-based sharding (default):** Tables are divided based on numerical ranges found in primary key values. Only tables with [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) primary keys can use range-based sharding. Tables with other primary key data types export as a single shard. + +- **Stats-based sharding (PostgreSQL only):** Enable with [`--use-stats-based-sharding`](#global-flags) for PostgreSQL 11+ sources. Tables are divided by analyzing the [`pg_stats`](https://www.postgresql.org/docs/current/view-pg-stats.htm) view to create more evenly distributed shards, up to a maximum of 200 shards. Primary keys of any data type are supported. + +Stats-based sharding requires that the user has `SELECT` permissions on source tables and on each table's `pg_stats` view. The latter permission is automatically granted to users that can read the table. + +To optimize stats-based sharding, run [`ANALYZE`](https://www.postgresql.org/docs/current/sql-analyze.html) on source tables before migration to ensure that table statistics are up-to-date and shards are evenly distributed. This requires `MAINTAIN` or `OWNER` permissions on the table. You can analyze specific primary key columns or the entire table. For example: + +{% include_cached copy-clipboard.html %} +~~~ sql +ANALYZE table_name(PK1, PK2, PK3); +~~~ + +{% include_cached copy-clipboard.html %} +~~~ sql +ANALYZE table_name; +~~~ + +Large tables may take time to analyze, but `ANALYZE` can run in the background. You can run `ANALYZE` with `MAINTAIN` or `OWNER` privileges during migration preparation, then perform the actual migration with standard `SELECT` privileges. + +{{site.data.alerts.callout_info}} +Migration without running `ANALYZE` will still work, but shard distribution may be less even. +{{site.data.alerts.end}} + +When using `--use-stats-based-sharding`, monitor the log output for each table you want to migrate. + +If stats-based sharding is successful on a table, MOLT logs the following `INFO` message: + +~~~ +Stats based sharding enabled for table {table_name} +~~~ + +If stats-based sharding fails on a table, MOLT logs the following `WARNING` message and defaults to range-based sharding: + +~~~ +Warning: failed to shard table {table_name} using stats based sharding: {reason_for_failure}, falling back to non stats based sharding +~~~ + +The number of shards is dependent on the number of distinct values in the first primary key column of the table to be migrated. If this is different from the number of shards requested with `--export-concurrency`, MOLT logs the following `WARNING` and continues with the migration: + +~~~ +number of shards formed: {num_shards_formed} is not equal to number of shards requested: {num_shards_requested} for table {table_name} +~~~ + +Because stats-based sharding analyzes the entire table, running `--use-stats-based-sharding` with [`--filter-path`](#global-flags) (refer to [Selective data movement](#selective-data-movement)) will cause imbalanced shards to form. + +### Data path + +MOLT Fetch can move the source data to CockroachDB via [cloud storage](#bucket-path), a [local file server](#local-path), or [directly](#direct-copy) without an intermediate store. + +#### Bucket path + +{{site.data.alerts.callout_success}} +Only the path specified in `--bucket-path` is used. Query parameters, such as credentials, are ignored. To authenticate cloud storage, follow the steps in [Secure cloud storage](#cloud-storage-security). +{{site.data.alerts.end}} + +`--bucket-path` instructs MOLT Fetch to write intermediate files to a path within [Google Cloud Storage](https://cloud.google.com/storage/docs/buckets), [Amazon S3](https://aws.amazon.com/s3/), or [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) to which you have the necessary permissions. Use additional [flags](#global-flags), shown in the following examples, to specify authentication or region parameters as required for bucket access. + +Connect to a Google Cloud Storage bucket with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#google-cloud-storage-implicit) and [assume role]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#set-up-google-cloud-storage-assume-role): + +{% include_cached copy-clipboard.html %} +~~~ +--bucket-path 'gs://migration/data/cockroach' +--assume-role 'user-test@cluster-ephemeral.iam.gserviceaccount.com' +--use-implicit-auth +~~~ + +Connect to an Amazon S3 bucket and explicitly specify the `ap_south-1` region: + +{% include_cached copy-clipboard.html %} +~~~ +--bucket-path 's3://migration/data/cockroach' +--import-region 'ap-south-1' +~~~ + +{{site.data.alerts.callout_info}} +When `--import-region` is set, `IMPORT INTO` must be used for [data movement](#data-load-mode). +{{site.data.alerts.end}} + +Connect to an Azure Blob Storage container with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}?filters=azure#azure-blob-storage-implicit-authentication): + +{% include_cached copy-clipboard.html %} +~~~ +--bucket-path 'azure-blob://migration/data/cockroach' +--use-implicit-auth +~~~ + +#### Local path + +`--local-path` instructs MOLT Fetch to write intermediate files to a path within a [local file server]({% link {{site.current_cloud_version}}/use-a-local-file-server.md %}). `local-path-listen-addr` specifies the address of the local file server. For example: + +{% include_cached copy-clipboard.html %} +~~~ +--local-path /migration/data/cockroach +--local-path-listen-addr 'localhost:3000' +~~~ + +In some cases, CockroachDB will not be able to use the local address specified by `--local-path-listen-addr`. This will depend on where CockroachDB is deployed, the runtime OS, and the source dialect. + +For example, if you are migrating to CockroachDB {{ site.data.products.cloud }}, such that the {{ site.data.products.cloud }} cluster is in a different physical location than the machine running `molt fetch`, then CockroachDB cannot reach an address such as `localhost:3000`. In these situations, use `--local-path-crdb-access-addr` to specify an address for the local file server that is **publicly accessible**. For example: + +{% include_cached copy-clipboard.html %} +~~~ +--local-path /migration/data/cockroach +--local-path-listen-addr 'localhost:3000' +--local-path-crdb-access-addr '44.55.66.77:3000' +~~~ + +{{site.data.alerts.callout_success}} +[Cloud storage](#bucket-path) is often preferable to a local file server, which can require considerable disk space. +{{site.data.alerts.end}} + +#### Direct copy + +`--direct-copy` specifies that MOLT Fetch should use `COPY FROM` to move the source data directly to CockroachDB without an intermediate store: + +- Because the data is held in memory, the machine must have sufficient RAM for the data currently in flight: + + ~~~ + average size of each row * --row-batch-size * --export-concurrency * --table-concurrency + ~~~ + +- Direct copy does not support compression or [continuation](#fetch-continuation). +- The [`--use-copy`](#data-load-mode) flag is redundant with `--direct-copy`. + +### Schema and table selection + +By default, MOLT Fetch moves all data from the [`--source`](#source-and-target-databases) database to CockroachDB. Use the following flags to move a subset of data. + +`--schema-filter` specifies a range of schema objects to move to CockroachDB, formatted as a POSIX regex string. For example, to move every table in the source database's `public` schema: + +{% include_cached copy-clipboard.html %} +~~~ +--schema-filter 'public' +~~~ + +`--table-filter` and `--table-exclusion-filter` specify tables to include and exclude from the migration, respectively, formatted as POSIX regex strings. For example, to move every source table that has "user" in the table name and exclude every source table that has "temp" in the table name: + +{% include_cached copy-clipboard.html %} +~~~ +--table-filter '.*user.*' --table-exclusion-filter '.*temp.*' +~~~ + +### Selective data movement + +Use `--filter-path` to specify the path to a JSON file that defines row-level filtering for data load. This enables you to move a subset of data in a table, rather than all data in the table. To apply row-level filters during replication, use [MOLT Replicator]({% link molt/molt-replicator.md %}) with userscripts. + +{% include_cached copy-clipboard.html %} +~~~ +--filter-path 'data-filter.json' +~~~ + +The JSON file should contain one or more entries in `filters`, each with a `resource_specifier` (`schema` and `table`) and a SQL expression `expr`. For example, the following example exports only rows from `public.t1` where `v > 100`: + +~~~ json +{ + "filters": [ + { + "resource_specifier": { + "schema": "public", + "table": "t1" + }, + "expr": "v > 100" + } + ] +} +~~~ + +`expr` is case-sensitive and must be valid in your source dialect. For example, when using Oracle as the source, quote all identifiers and escape embedded quotes: + +~~~ json +{ + "filters": [ + { + "resource_specifier": { + "schema": "C##FETCHORACLEFILTERTEST", + "table": "FILTERTBL" + }, + "expr": "ABS(\"X\") > 10 AND CEIL(\"X\") < 100 AND FLOOR(\"X\") > 0 AND ROUND(\"X\", 2) < 100.00 AND TRUNC(\"X\", 0) > 0 AND MOD(\"X\", 2) = 0 AND FLOOR(\"X\" / 3) > 1" + } + ] +} +~~~ + +{{site.data.alerts.callout_info}} +If the expression references columns that are not indexed, MOLT Fetch will emit a warning like: `filter expression ‘v > 100' contains column ‘v' which is not indexed. This may lead to performance issues.` +{{site.data.alerts.end}} + +{% comment %} +#### `--filter-path` userscript for replication + +To use `--filter-path` with replication, create and save a TypeScript userscript (e.g., `filter-script.ts`). The following script ensures that only rows where `v > 100` are replicated to `defaultdb.public.t1`: + +{% include_cached copy-clipboard.html %} +~~~ ts +import * as api from "replicator@v1"; +function disp(doc, meta) { + if (Number(doc.v) > 100) { + return { "defaultdb.public.t1" : [ doc ] }; + } +} +// Always put target schema. +api.configureSource("defaultdb.public", { + deletesTo: disp, + dispatch: disp, +}); +~~~ + +Apply the userscript with the `--userscript` replication flag: + +{% include_cached copy-clipboard.html %} +~~~ +--userscript 'filter-script.ts' +~~~ +{% endcomment %} + +### Target table handling + +`--table-handling` defines how MOLT Fetch loads data on the CockroachDB tables that [match the selection](#schema-and-table-selection). + +To load the data without changing the existing data in the tables, use `none`: + +{% include_cached copy-clipboard.html %} +~~~ +--table-handling none +~~~ + +To [truncate]({% link {{site.current_cloud_version}}/truncate.md %}) tables before loading the data, use `truncate-if-exists`: + +{% include_cached copy-clipboard.html %} +~~~ +--table-handling truncate-if-exists +~~~ + +To drop existing tables and create new tables before loading the data, use `drop-on-target-and-recreate`: + +{% include_cached copy-clipboard.html %} +~~~ +--table-handling drop-on-target-and-recreate +~~~ + +When using the `drop-on-target-and-recreate` option, MOLT Fetch creates a new CockroachDB table to load the source data if one does not already exist. To guide the automatic schema creation, you can [explicitly map source types to CockroachDB types](#type-mapping). `drop-on-target-and-recreate` does **not** create indexes or constraints other than [`PRIMARY KEY`]({% link {{site.current_cloud_version}}/primary-key.md %}) and [`NOT NULL`]({% link {{site.current_cloud_version}}/not-null.md %}). + +#### Mismatch handling + +If either [`none`](#target-table-handling) or [`truncate-if-exists`](#target-table-handling) is set, `molt fetch` loads data into the existing tables on the target CockroachDB database. If the target schema mismatches the source schema, `molt fetch` will exit early in certain cases, and will need to be re-run from the beginning. For details, refer to [Fetch exits early due to mismatches](#fetch-exits-early-due-to-mismatches). + +{{site.data.alerts.callout_info}} +This does not apply when [`drop-on-target-and-recreate`](#target-table-handling) is specified, since this option automatically creates a compatible CockroachDB schema. +{{site.data.alerts.end}} + +#### Skip primary key matching + +`--skip-pk-check` removes the [requirement that source and target tables share matching primary keys](#fetch-exits-early-due-to-mismatches) for data load. When this flag is set: + +- The data load proceeds even if the source or target table lacks a primary key, or if their primary key columns do not match. +- [Table sharding](#table-sharding) is disabled. Each table is exported in a single batch within one shard, bypassing `--export-concurrency` and `--row-batch-size`. As a result, memory usage and execution time may increase due to full table scans. +- If the source table contains duplicate rows but the target has [`PRIMARY KEY`]({% link {{ site.current_cloud_version }}/primary-key.md %}) or [`UNIQUE`]({% link {{ site.current_cloud_version }}/unique.md %}) constraints, duplicate rows are deduplicated during import. + +When `--skip-pk-check` is set, all tables are treated as if they lack a primary key, and are thus exported in a single unsharded batch. To avoid performance issues, use this flag with `--table-filter` to target only tables **without** a primary key. + +For example: + +{% include_cached copy-clipboard.html %} +~~~ shell +molt fetch \ + --mode data-load \ + --table-filter 'nopktbl' \ + --skip-pk-check +~~~ + +Example log output when `--skip-pk-check` is enabled: + +~~~json +{"level":"info","message":"sharding is skipped for table public.nopktbl - flag skip-pk-check is specified and thus no PK for source table is specified"} +~~~ + +#### Type mapping + +If [`drop-on-target-and-recreate`](#target-table-handling) is set, MOLT Fetch automatically creates a CockroachDB schema that is compatible with the source data. The column types are determined as follows: + +- PostgreSQL types are mapped to existing CockroachDB [types]({% link {{site.current_cloud_version}}/data-types.md %}) that have the same [`OID`]({% link {{site.current_cloud_version}}/oid.md %}). +- The following MySQL types are mapped to corresponding CockroachDB types: + + | MySQL type | CockroachDB type | Notes | + |-----------------------------------------------------|-------------------------------------------------------------------------------------------|--------------------------------------------------------------| + | `CHAR`, `CHARACTER`, `VARCHAR`, `NCHAR`, `NVARCHAR` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | + | `TINYTEXT`, `TEXT`, `MEDIUMTEXT`, `LONGTEXT` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | + | `GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | + | `LINESTRING` | [`LINESTRING`]({% link {{site.current_cloud_version}}/linestring.md %}) | Spatial type (PostGIS-style) | + | `POINT` | [`POINT`]({% link {{site.current_cloud_version}}/point.md %}) | Spatial type (PostGIS-style) | + | `POLYGON` | [`POLYGON`]({% link {{site.current_cloud_version}}/polygon.md %}) | Spatial type (PostGIS-style) | + | `MULTIPOINT` | [`MULTIPOINT`]({% link {{site.current_cloud_version}}/multipoint.md %}) | Spatial type (PostGIS-style) | + | `MULTILINESTRING` | [`MULTILINESTRING`]({% link {{site.current_cloud_version}}/multilinestring.md %}) | Spatial type (PostGIS-style) | + | `MULTIPOLYGON` | [`MULTIPOLYGON`]({% link {{site.current_cloud_version}}/multipolygon.md %}) | Spatial type (PostGIS-style) | + | `GEOMETRYCOLLECTION`, `GEOMCOLLECTION` | [`GEOMETRYCOLLECTION`]({% link {{site.current_cloud_version}}/geometrycollection.md %}) | Spatial type (PostGIS-style) | + | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | + | `TINYINT`, `INT1` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | + | `BLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `SMALLINT`, `INT2` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | + | `MEDIUMINT`, `INT`, `INTEGER`, `INT4` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | + | `BIGINT`, `INT8` | [`INT`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | + | `FLOAT` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | + | `DOUBLE` | [`FLOAT`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | + | `DECIMAL`, `NUMERIC`, `REAL` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | + | `BINARY`, `VARBINARY` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `DATETIME` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time (no time zone) | + | `TIMESTAMP` | [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time with time zone | + | `TIME` | [`TIME`]({% link {{site.current_cloud_version}}/time.md %}) | Time of day (no date) | + | `BIT` | [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) | Variable-length bit array | + | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | + | `TINYBLOB`, `MEDIUMBLOB`, `LONGBLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `BOOL`, `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | + +- The following Oracle types are mapped to CockroachDB types: + + | Oracle type(s) | CockroachDB type | Notes | + |---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| + | `NCHAR`, `CHAR`, `CHARACTER` | [`CHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`CHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Fixed-length character; falls back to unbounded if length not specified | + | `VARCHAR`, `VARCHAR2`, `NVARCHAR2` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | + | `STRING` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | + | `SMALLINT` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | + | `INTEGER`, `INT`, `SIMPLE_INTEGER` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | + | `LONG` | [`INT8`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | + | `FLOAT`, `BINARY_FLOAT`, `REAL` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | + | `DOUBLE`, `BINARY_DOUBLE` | [`FLOAT8`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | + | `DEC`, `NUMBER`, `DECIMAL`, `NUMERIC` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %})(p, s) or [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | + | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | + | `BLOB`, `RAW`, `LONG RAW` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | + | `CLOB`, `NCLOB` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as large text | + | `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | + | `TIMESTAMP` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) or [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | If `WITH TIME ZONE` → `TIMESTAMPTZ`, else `TIMESTAMP` | + | `ROWID`, `UROWID` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as opaque identifier | + | `SDO_GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | + | `XMLTYPE` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Stored as text | + +- To override the default mappings for automatic schema creation, you can map source to target CockroachDB types explicitly. These are defined in the JSON file indicated by the `--type-map-file` flag. The allowable custom mappings are valid CockroachDB aliases, casts, and the following mappings specific to MOLT Fetch and [Verify]({% link molt/molt-verify.md %}): + + - [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) <> [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) + - [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) <> [`UUID`]({% link {{site.current_cloud_version}}/uuid.md %}) + - [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) <> [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) + - [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) + - [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) <> [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) + - [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) + - [`INET`]({% link {{site.current_cloud_version}}/inet.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) + +`--type-map-file` specifies the path to the JSON file containing the explicit type mappings. For example: + +{% include_cached copy-clipboard.html %} +~~~ +--type-map-file 'type-mappings.json' +~~~ + +The following JSON example defines two type mappings: + +~~~ json + [ + { + "table": "public.t1", + "column_type_map": [ + { + "column": "*", + "source_type": "int", + "crdb_type": "INT2" + }, + { + "column": "name", + "source_type": "varbit", + "crdb_type": "string" + } + ] + } +] +~~~ + +- `table` specifies the table that will use the custom type mappings in `column_type_map`. The value is written as `{schema}.{table}`. +- `column` specifies the column that will use the custom type mapping. If `*` is specified, then all columns in the `table` with the matching `source_type` are converted. +- `source_type` specifies the source type to be mapped. +- `crdb_type` specifies the target CockroachDB [type]({% link {{ site.current_cloud_version }}/data-types.md %}) to be mapped. + +### Transformations + +You can define transformation rules to be performed on the target schema during the fetch task. These can be used to: + +- Map [computed columns]({% link {{ site.current_cloud_version }}/computed-columns.md %}) to a target schema. +- Map [partitioned tables]({% link {{ site.current_cloud_version }}/partitioning.md %}) to a single target table. +- Rename tables on the target schema. + +Transformation rules are defined in the JSON file indicated by the `--transformations-file` flag. For example: + +{% include_cached copy-clipboard.html %} +~~~ +--transformations-file 'transformation-rules.json' +~~~ + +The following JSON example defines two transformation rules: + +~~~ json +{ + "transforms": [ + { + "id": 1, + "resource_specifier": { + "schema": ".*", + "table": ".*" + }, + "column_exclusion_opts": { + "add_computed_def": true, + "column": "^age$" + } + }, + { + "id": 2, + "resource_specifier": { + "schema": "public", + "table": "charges_part.*" + }, + "table_rename_opts": { + "value": "charges" + } + } + ] +} +~~~ + +- `resource_specifier` configures the following options for transformation rules: + - `schema` specifies the schemas to be affected by the transformation rule, formatted as a POSIX regex string. + - `table` specifies the tables to be affected by the transformation rule, formatted as a POSIX regex string. +- `column_exclusion_opts` configures the following options for column exclusions and computed columns: + - `column` specifies source columns to exclude from being mapped to regular columns on the target schema. It is formatted as a POSIX regex string. + - `add_computed_def`, when set to `true`, specifies that each matching `column` should be mapped to a [computed column]({% link {{ site.current_cloud_version }}/computed-columns.md %}) on the target schema. Instead of being moved from the source, the column data is generated on the target using [`ALTER TABLE ... ADD COLUMN`]({% link {{ site.current_cloud_version }}/alter-table.md %}#add-column) and the computed column definition from the source schema. This assumes that all matching columns are computed columns on the source. + {{site.data.alerts.callout_danger}} + Columns that match the `column` regex will **not** be moved to CockroachDB if `add_computed_def` is omitted or set to `false` (default), or if a matching column is a non-computed column. + {{site.data.alerts.end}} +- `table_rename_opts` configures the following option for table renaming: + - `value` specifies the table name to which the matching `resource_specifier` is mapped. If only one source table matches `resource_specifier`, it is renamed to `table_rename_opts.value` on the target. If more than one table matches `resource_specifier` (i.e., an n-to-1 mapping), the fetch task assumes that all matching tables are [partitioned tables]({% link {{ site.current_cloud_version }}/partitioning.md %}) with the same schema, and moves their data to a table named `table_rename_opts.value` on the target. Otherwise, the task will error. + + Additionally, in an n-to-1 mapping situation: + + - Specify [`--use-copy`](#data-load-mode) or [`--direct-copy`](#direct-copy) for data movement. This is because the data from the source tables is loaded concurrently into the target table. + - Create the target table schema manually, and do **not** use [`--table-handling drop-on-target-and-recreate`](#target-table-handling) for target table handling. + +The preceding JSON example therefore defines two rules: + +- Rule `1` maps all source `age` columns on the source database to [computed columns]({% link {{ site.current_cloud_version }}/computed-columns.md %}) on CockroachDB. This assumes that all matching `age` columns are defined as computed columns on the source. +- Rule `2` maps all table names with prefix `charges_part` from the source database to a single `charges` table on CockroachDB (i.e., an n-to-1 mapping). This assumes that all matching `charges_part.*` tables have the same schema. + +Each rule is applied in the order it is defined. If two rules overlap, the later rule will override the earlier rule. + +To verify that the logging shows that the computed columns are being created: + +When running `molt fetch`, set `--logging debug` and look for `ALTER TABLE ... ADD COLUMN` statements with the `STORED` or `VIRTUAL` keywords in the log output: + +~~~ json +{"level":"debug","time":"2024-07-22T12:01:51-04:00","message":"running: ALTER TABLE IF EXISTS public.computed ADD COLUMN computed_col INT8 NOT NULL AS ((col1 + col2)) STORED"} +~~~ + +After running `molt fetch`, issue a `SHOW CREATE TABLE` statement on CockroachDB: + +{% include_cached copy-clipboard.html %} +~~~ sql +SHOW CREATE TABLE computed; +~~~ + +~~~ + table_name | create_statement +-------------+------------------------------------------------------------------- + computed | CREATE TABLE public.computed ( + ... + | computed_col INT8 NOT NULL AS (col1 + col2) STORED + | ) +~~~ + +### Fetch continuation + +If MOLT Fetch fails while loading data into CockroachDB from intermediate files, it exits with an error message, fetch ID, and [continuation token](#list-active-continuation-tokens) for each table that failed to load on the target database. You can use this information to continue the task from the *continuation point* where it was interrupted. + +Continuation is only possible under the following conditions: + +- All data has been exported from the source database into intermediate files on [cloud](#bucket-path) or [local storage](#local-path). +- The *initial load* of source data into the target CockroachDB database is incomplete. + +{{site.data.alerts.callout_info}} +Only one fetch ID and set of continuation tokens, each token corresponding to a table, are active at any time. See [List active continuation tokens](#list-active-continuation-tokens). +{{site.data.alerts.end}} + +To retry all data starting from the continuation point, reissue the `molt fetch` command and include the `--fetch-id`. + +{% include_cached copy-clipboard.html %} +~~~ +--fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 +~~~ + +To retry a specific table that failed, include both `--fetch-id` and `--continuation-token`. The latter flag specifies a token string that corresponds to a specific table on the source database. A continuation token is written in the `molt fetch` output for each failed table. If the fetch task encounters a subsequent error, it generates a new token for each failed table. See [List active continuation tokens](#list-active-continuation-tokens). + +{{site.data.alerts.callout_info}} +This will retry only the table that corresponds to the continuation token. If the fetch task succeeds, there may still be source data that is not yet loaded into CockroachDB. +{{site.data.alerts.end}} + +{% include_cached copy-clipboard.html %} +~~~ +--fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 +--continuation-token 011762e5-6f70-43f8-8e15-58b4de10a007 +~~~ + +To retry all data starting from a specific file, include both `--fetch-id` and `--continuation-file-name`. The latter flag specifies the filename of an intermediate file in [cloud or local storage](#data-path). All filenames are prepended with `part_` and have the `.csv.gz` or `.csv` extension, depending on compression type (gzip by default). For example: + +{% include_cached copy-clipboard.html %} +~~~ +--fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 +--continuation-file-name part_00000003.csv.gz +~~~ + +{{site.data.alerts.callout_info}} +Continuation is not possible when using [direct copy](#direct-copy). +{{site.data.alerts.end}} + +#### List active continuation tokens + +To view all active continuation tokens, issue a `molt fetch tokens list` command along with `--conn-string`, which specifies the [connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url) for the target CockroachDB database. For example: + +{% include_cached copy-clipboard.html %} +~~~ shell +molt fetch tokens list \ +--conn-string 'postgres://root@localhost:26257/defaultdb?sslmode=verify-full' +~~~ + +~~~ ++--------------------------------------+--------------------------------------+------------------+----------------------+ +| ID | FETCH ID | TABLE NAME | FILE NAME | ++--------------------------------------+--------------------------------------+------------------+----------------------+ +| f6f0284c-d9c1-43c9-8fde-af609d0dbd82 | 66443597-5689-4df3-a7b9-9fc5e27180eb | public.employees | part_00000001.csv.gz | ++--------------------------------------+--------------------------------------+------------------+----------------------+ +Continuation Tokens. +~~~ + +### CDC cursor + +A change data capture (CDC) cursor is written to the output as `cdc_cursor` at the beginning and end of the fetch task. For example: + +~~~ json +{"level":"info","type":"summary","fetch_id":"735a4fe0-c478-4de7-a342-cfa9738783dc","num_tables":1,"tables":["public.employees"],"cdc_cursor":"b7f9e0fa-2753-1e1f-5d9b-2402ac810003:3-21","net_duration_ms":4879.890041,"net_duration":"000h 00m 04s","time":"2024-03-18T12:37:02-04:00","message":"fetch complete"} +~~~ + +Use the `cdc_cursor` value as the checkpoint for MySQL or Oracle replication with [MOLT Replicator]({% link molt/molt-replicator.md %}#replication-checkpoints). + +You can also use the `cdc_cursor` value with an external change data capture (CDC) tool to continuously replicate subsequent changes from the source database to CockroachDB. + +## See also + +- X \ No newline at end of file diff --git a/src/current/molt/molt-fetch.md b/src/current/molt/molt-fetch.md index 02052c16583..754d04b3c32 100644 --- a/src/current/molt/molt-fetch.md +++ b/src/current/molt/molt-fetch.md @@ -5,993 +5,6 @@ toc: true docs_area: migrate --- -MOLT Fetch moves data from a source database into CockroachDB as part of a [database migration]({% link molt/migration-overview.md %}). - -MOLT Fetch uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to move the source data to cloud storage (Google Cloud Storage, Amazon S3, or Azure Blob Storage), a local file server, or local memory. Once the data is exported, MOLT Fetch loads the data into a target CockroachDB database. For details, refer to [Migration phases](#migration-phases). - -## Terminology - -- *Shard*: A portion of a table's data exported concurrently during the data export phase. Tables are divided into shards to enable parallel processing. For details, refer to [Table sharding](#table-sharding). -- *Continuation token*: An identifier that marks the progress of a fetch task. Used to resume data loading from the point of interruption if a fetch task fails. For details, refer to [Fetch continuation](#fetch-continuation). -- *Intermediate files*: Temporary data files written to cloud storage or a local file server during the data export phase. These files are used to stage exported data before importing it into CockroachDB during the data import phase. For details, refer to [Data path](#data-path). - -## Prerequisites - -### Supported databases - -The following source databases are supported: - -- PostgreSQL 11-16 -- MySQL 5.7, 8.0 and later -- Oracle Database 19c (Enterprise Edition) and 21c (Express Edition) - -### Database configuration - -Ensure that the source and target schemas are identical, unless you enable automatic schema creation with the [`drop-on-target-and-recreate`](#target-table-handling) option. If you are creating the target schema manually, review the behaviors in [Mismatch handling](#mismatch-handling). - -{{site.data.alerts.callout_info}} -MOLT Fetch does not support migrating sequences. If your source database contains sequences, refer to the [guidance on indexing with sequential keys]({% link {{site.current_cloud_version}}/sql-faqs.md %}#how-do-i-generate-unique-slowly-increasing-sequential-numbers-in-cockroachdb). If a sequential key is necessary in your CockroachDB table, you must create it manually. After using MOLT Fetch to load the data onto the target, but before cutover, make sure to update each sequence's current value using [`setval()`]({% link {{site.current_cloud_version}}/functions-and-operators.md %}#sequence-functions) so that new inserts continue from the correct point. -{{site.data.alerts.end}} - -If you plan to use cloud storage for the data migration, follow the steps in [Cloud storage security](#cloud-storage-security). - -### User permissions - -The SQL user running MOLT Fetch requires specific privileges on both the source and target databases: - -| Database | Required Privileges | Details | -|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------| -| PostgreSQL source | | [Create PostgreSQL migration user]({% link molt/migrate-bulk-load.md %}#create-migration-user-on-source-database) | -| MySQL source | | [Create MySQL migration user]({% link molt/migrate-bulk-load.md %}?filters=mysql#create-migration-user-on-source-database) | -| Oracle source | | [Create Oracle migration user]({% link molt/migrate-bulk-load.md %}?filters=oracle#create-migration-user-on-source-database) | -| CockroachDB target | | [Create CockroachDB user]({% link molt/migrate-bulk-load.md %}#create-the-sql-user) | - -## Installation - -{% include molt/molt-install.md %} - -### Docker usage - -{% include molt/molt-docker.md %} - -## Migration phases - -MOLT Fetch operates in distinct phases to move data from source databases to CockroachDB. For details on available modes, refer to [Fetch mode](#fetch-mode). - -### Data export phase - -MOLT Fetch connects to the source database and exports table data to intermediate storage. Data is written to [cloud storage](#bucket-path) (Amazon S3, Google Cloud Storage, Azure Blob Storage), a [local file server](#local-path), or [directly to CockroachDB memory](#direct-copy). Multiple tables and table shards can be exported simultaneously using [`--table-concurrency`](#global-flags) and [`--export-concurrency`](#global-flags), with large tables divided into shards for parallel processing. For details, refer to: - -- [Fetch mode](#fetch-mode) -- [Table sharding](#table-sharding) - -### Data import phase - -MOLT Fetch loads the exported data into the target CockroachDB database. The process uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) (faster, tables offline during import) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) (slower, tables remain queryable) to move data. Data files are imported in configurable batches using [`--import-batch-size`](#global-flags), and target tables can be automatically created, truncated, or left unchanged based on [`--table-handling`](#global-flags) settings. For details, refer to: - -- [Data movement](#data-load-mode) -- [Target table handling](#target-table-handling) - -## Commands - -| Command | Usage | -|---------|---------------------------------------------------------------------------------------------------| -| `fetch` | Start the fetch task. This loads data from a source database to a target CockroachDB database. | - -### Subcommands - -| Command | Usage | -|--------------|----------------------------------------------------------------------| -| `tokens list` | List active [continuation tokens](#list-active-continuation-tokens). | - -## Flags - -### Global flags - -| Flag | Description | -|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `--source` | (Required) Connection string used to connect to the Oracle PDB (in a CDB/PDB architecture) or to a standalone database (non‑CDB). For details, refer to [Source and target databases](#source-and-target-databases). | -| `--source-cdb` | Connection string for the Oracle container database (CDB) when using a multitenant (CDB/PDB) architecture. Omit this flag on a non‑multitenant Oracle database. For details, refer to [Source and target databases](#source-and-target-databases). | -| `--target` | (Required) Connection string for the target database. For details, refer to [Source and target databases](#source-and-target-databases). | -| `--allow-tls-mode-disable` | Allow insecure connections to databases. Secure SSL/TLS connections should be used by default. This should be enabled **only** if secure SSL/TLS connections to the source or target database are not possible. | -| `--assume-role` | Service account to use for assume role authentication. `--use-implicit-auth` must be included. For example, `--assume-role='user-test@cluster-ephemeral.iam.gserviceaccount.com' --use-implicit-auth`. For details, refer to [Cloud Storage Authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}). | -| `--bucket-path` | The path within the [cloud storage](#bucket-path) bucket where intermediate files are written (e.g., `'s3://bucket/path'` or `'gs://bucket/path'`). Only the URL path is used; query parameters (e.g., credentials) are ignored. To pass in query parameters, use the appropriate flags: `--assume-role`, `--import-region`, `--use-implicit-auth`. | -| `--case-sensitive` | Toggle case sensitivity when comparing table and column names on the source and target. To disable case sensitivity, set `--case-sensitive=false`. If `=` is **not** included (e.g., `--case-sensitive false`), the flag is interpreted as `--case-sensitive` (i.e., `--case-sensitive=true`).

**Default:** `false` | -| `--cleanup` | Whether to delete intermediate files after moving data using [cloud or local storage](#data-path). **Note:** Cleanup does not occur on [continuation](#fetch-continuation). | -| `--compression` | Compression method for data when using [`IMPORT INTO`](#data-load-mode) (`gzip`/`none`).

**Default:** `gzip` | -| `--continuation-file-name` | Restart fetch at the specified filename if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation](#fetch-continuation). | -| `--continuation-token` | Restart fetch at a specific table, using the specified continuation token, if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation](#fetch-continuation). | -| `--crdb-pts-duration` | The duration for which each timestamp used in data export from a CockroachDB source is protected from garbage collection. This ensures that the data snapshot remains consistent. For example, if set to `24h`, each timestamp is protected for 24 hours from the initiation of the export job. This duration is extended at regular intervals specified in `--crdb-pts-refresh-interval`.

**Default:** `24h0m0s` | -| `--crdb-pts-refresh-interval` | The frequency at which the protected timestamp's validity is extended. This interval maintains protection of the data snapshot until data export from a CockroachDB source is completed. For example, if set to `10m`, the protected timestamp's expiration will be extended by the duration specified in `--crdb-pts-duration` (e.g., `24h`) every 10 minutes while export is not complete.

**Default:** `10m0s` | -| `--direct-copy` | Enables [direct copy](#direct-copy), which copies data directly from source to target without using an intermediate store. | -| `--export-concurrency` | Number of shards to export at a time per table, each on a dedicated thread. This controls how many shards are created for each individual table during the [data export phase](#data-export-phase) and is distinct from `--table-concurrency`, which controls how many tables are processed simultaneously. The total number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`. Tables can be sharded with a range-based or stats-based mechanism. For details, refer to [Table sharding](#table-sharding).

**Default:** `4` | -| `--export-retry-max-attempts` | Maximum number of retry attempts for source export queries when connection failures occur. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `3` | -| `--export-retry-max-duration` | Maximum total duration for retrying source export queries. If `0`, no time limit is enforced. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `5m0s` | -| `--filter-path` | Path to a JSON file defining row-level filters for the [data import phase](#data-import-phase). Refer to [Selective data movement](#selective-data-movement). | -| `--fetch-id` | Restart fetch task corresponding to the specified ID. If `--continuation-file-name` or `--continuation-token` are not specified, fetch restarts for all failed tables. | -| `--flush-rows` | Number of rows before the source data is flushed to intermediate files. **Note:** If `--flush-size` is also specified, the fetch behavior is based on the flag whose criterion is met first. | -| `--flush-size` | Size (in bytes) before the source data is flushed to intermediate files. **Note:** If `--flush-rows` is also specified, the fetch behavior is based on the flag whose criterion is met first. | -| `--ignore-replication-check` | Skip querying for replication checkpoints such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle. This option is intended for use during bulk load migrations or when doing a one-time data export from a read replica. | -| `--import-batch-size` | The number of files to be imported at a time to the target database during the [data import phase](#data-import-phase). This applies only when using [`IMPORT INTO`](#data-load-mode) for data movement. **Note:** Increasing this value can improve the performance of full-scan queries on the target database shortly after fetch completes, but very high values are not recommended. If any individual file in the import batch fails, you must [retry](#fetch-continuation) the entire batch.

**Default:** `1000` | -| `--import-region` | The region of the [cloud storage](#bucket-path) bucket. This applies only to [Amazon S3 buckets](#bucket-path). Set this flag only if you need to specify an `AWS_REGION` explicitly when using [`IMPORT INTO`](#data-load-mode) for data movement. For example, `--import-region=ap-south-1`. | -| `--local-path` | The path within the [local file server](#local-path) where intermediate files are written (e.g., `data/migration/cockroach`). `--local-path-listen-addr` must be specified. | -| `--local-path-crdb-access-addr` | Address of a [local file server](#local-path) that is **publicly accessible**. This flag is only necessary if CockroachDB cannot reach the local address specified with `--local-path-listen-addr` (e.g., when moving data to a CockroachDB {{ site.data.products.cloud }} deployment). `--local-path` and `--local-path-listen-addr` must be specified.

**Default:** Value of `--local-path-listen-addr`. | -| `--local-path-listen-addr` | Write intermediate files to a [local file server](#local-path) at the specified address (e.g., `'localhost:3000'`). `--local-path` must be specified. | -| `--log-file` | Write messages to the specified log filename. If no filename is provided, messages write to `fetch-{datetime}.log`. If `"stdout"` is provided, messages write to `stdout`. | -| `--logging` | Level at which to log messages (`trace`/`debug`/`info`/`warn`/`error`/`fatal`/`panic`).

**Default:** `info` | -| `--metrics-listen-addr` | Address of the Prometheus metrics endpoint, which has the path `{address}/metrics`. For details on important metrics to monitor, refer to [Monitoring](#monitoring).

**Default:** `'127.0.0.1:3030'` | -| `--mode` | Configure the MOLT Fetch behavior: `data-load`, `export-only`, or `import-only`. For details, refer to [Fetch mode](#fetch-mode).

**Default:** `data-load` | -| `--non-interactive` | Run the fetch task without interactive prompts. This is recommended **only** when running `molt fetch` in an automated process (i.e., a job or continuous integration). | -| `--pprof-listen-addr` | Address of the pprof endpoint.

**Default:** `'127.0.0.1:3031'` | -| `--row-batch-size` | Number of rows per shard to export at a time. For details on sharding, refer to [Table sharding](#table-sharding). See also [Best practices](#best-practices).

**Default:** `100000` | -| `--schema-filter` | Move schemas that match a specified [regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | -| `--skip-pk-check` | Skip primary-key matching to allow data load when source or target tables have missing or mismatched primary keys. Disables sharding and bypasses `--export-concurrency` and `--row-batch-size` settings. Refer to [Skip primary key matching](#skip-primary-key-matching).

**Default:** `false` | -| `--table-concurrency` | Number of tables to export at a time. The number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`.

**Default:** `4` | -| `--table-exclusion-filter` | Exclude tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

This value **cannot** be set to `'.*'`, which would cause every table to be excluded.

**Default:** Empty string | -| `--table-filter` | Move tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | -| `--table-handling` | How tables are initialized on the target database (`none`/`drop-on-target-and-recreate`/`truncate-if-exists`). For details, see [Target table handling](#target-table-handling).

**Default:** `none` | -| `--transformations-file` | Path to a JSON file that defines transformations to be performed on the target schema during the fetch task. Refer to [Transformations](#transformations). | -| `--type-map-file` | Path to a JSON file that contains explicit type mappings for automatic schema creation, when enabled with `--table-handling drop-on-target-and-recreate`. For details on the JSON format and valid type mappings, see [type mapping](#type-mapping). | -| `--use-console-writer` | Use the console writer, which has cleaner log output but introduces more latency.

**Default:** `false` (log as structured JSON) | -| `--use-copy` | Use [`COPY FROM`](#data-load-mode) to move data. This makes tables queryable during data load, but is slower than using `IMPORT INTO`. For details, refer to [Data movement](#data-load-mode). | -| `--use-implicit-auth` | Use [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}) for [cloud storage](#bucket-path) URIs. | -| `--use-stats-based-sharding` | Enable statistics-based sharding for PostgreSQL sources. This allows sharding of tables with primary keys of any data type and can create more evenly distributed shards compared to the default numerical range sharding. Requires PostgreSQL 11+ and access to `pg_stats`. For details, refer to [Table sharding](#table-sharding). | - - -### `tokens list` flags - -| Flag | Description | -|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------| -| `--conn-string` | (Required) Connection string for the target database. For details, see [List active continuation tokens](#list-active-continuation-tokens). | -| `-n`, `--num-results` | Number of results to return. | - - -## Usage - -The following sections describe how to use the `molt fetch` [flags](#flags). - -### Source and target databases - -{{site.data.alerts.callout_success}} -Follow the recommendations in [Connection security](#connection-security). -{{site.data.alerts.end}} - -`--source` specifies the connection string of the source database. - -PostgreSQL or CockroachDB connection string: - -{% include_cached copy-clipboard.html %} -~~~ ---source 'postgresql://{username}:{password}@{host}:{port}/{database}' -~~~ - -MySQL connection string: - -{% include_cached copy-clipboard.html %} -~~~ ---source 'mysql://{username}:{password}@{protocol}({host}:{port})/{database}' -~~~ - -Oracle connection string: - -{% include_cached copy-clipboard.html %} -~~~ ---source 'oracle://{username}:{password}@{host}:{port}/{service_name}' -~~~ - -For Oracle Multitenant databases, `--source-cdb` specifies the container database (CDB) connection. `--source` specifies the pluggable database (PDB): - -{% include_cached copy-clipboard.html %} -~~~ ---source 'oracle://{username}:{password}@{host}:{port}/{pdb_service_name}' ---source-cdb 'oracle://{username}:{password}@{host}:{port}/{cdb_service_name}' -~~~ - -`--target` specifies the [CockroachDB connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url): - -{% include_cached copy-clipboard.html %} -~~~ ---target 'postgresql://{username}:{password}@{host}:{port}/{database}' -~~~ - -### Fetch mode - -`--mode` specifies the MOLT Fetch behavior. - -`data-load` (default) instructs MOLT Fetch to load the source data into CockroachDB: - -{% include_cached copy-clipboard.html %} -~~~ ---mode data-load -~~~ - -`export-only` instructs MOLT Fetch to export the source data to the specified [cloud storage](#bucket-path) or [local file server](#local-path). It does not load the data into CockroachDB: - -{% include_cached copy-clipboard.html %} -~~~ ---mode export-only -~~~ - -`import-only` instructs MOLT Fetch to load the source data in the specified [cloud storage](#bucket-path) or [local file server](#local-path) into the CockroachDB target: - -{% include_cached copy-clipboard.html %} -~~~ ---mode import-only -~~~ - -### Data load mode - -MOLT Fetch can use either [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to load data into CockroachDB. - -By default, MOLT Fetch uses `IMPORT INTO`: - -- `IMPORT INTO` achieves the highest throughput, but [requires taking the CockroachDB tables **offline**]({% link {{site.current_cloud_version}}/import-into.md %}#considerations) to achieve its import speed. Tables are taken back online once an [import job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs) completes successfully. See [Best practices](#best-practices). -- `IMPORT INTO` supports compression using the `--compression` flag, which reduces the amount of storage used. - -`--use-copy` configures MOLT Fetch to use `COPY FROM`: - -- `COPY FROM` enables your tables to remain online and accessible. However, it is slower than using [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}). -- `COPY FROM` does not support compression. - -{{site.data.alerts.callout_info}} -`COPY FROM` is also used for [direct copy](#direct-copy). -{{site.data.alerts.end}} - -### Table sharding - -During the [data export phase](#data-export-phase), MOLT Fetch can divide large tables into multiple shards for concurrent export. - -To control the number of shards created per table, use the `--export-concurrency` flag. For example: - -{% include_cached copy-clipboard.html %} -~~~ ---export-concurrency=4 -~~~ - -{{site.data.alerts.callout_success}} -For performance considerations with concurrency settings, refer to [Best practices](#best-practices). -{{site.data.alerts.end}} - -Two sharding mechanisms are available: - -- **Range-based sharding (default):** Tables are divided based on numerical ranges found in primary key values. Only tables with [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) primary keys can use range-based sharding. Tables with other primary key data types export as a single shard. - -- **Stats-based sharding (PostgreSQL only):** Enable with [`--use-stats-based-sharding`](#global-flags) for PostgreSQL 11+ sources. Tables are divided by analyzing the [`pg_stats`](https://www.postgresql.org/docs/current/view-pg-stats.htm) view to create more evenly distributed shards, up to a maximum of 200 shards. Primary keys of any data type are supported. - -Stats-based sharding requires that the user has `SELECT` permissions on source tables and on each table's `pg_stats` view. The latter permission is automatically granted to users that can read the table. - -To optimize stats-based sharding, run [`ANALYZE`](https://www.postgresql.org/docs/current/sql-analyze.html) on source tables before migration to ensure that table statistics are up-to-date and shards are evenly distributed. This requires `MAINTAIN` or `OWNER` permissions on the table. You can analyze specific primary key columns or the entire table. For example: - -{% include_cached copy-clipboard.html %} -~~~ sql -ANALYZE table_name(PK1, PK2, PK3); -~~~ - -{% include_cached copy-clipboard.html %} -~~~ sql -ANALYZE table_name; -~~~ - -Large tables may take time to analyze, but `ANALYZE` can run in the background. You can run `ANALYZE` with `MAINTAIN` or `OWNER` privileges during migration preparation, then perform the actual migration with standard `SELECT` privileges. - -{{site.data.alerts.callout_info}} -Migration without running `ANALYZE` will still work, but shard distribution may be less even. -{{site.data.alerts.end}} - -When using `--use-stats-based-sharding`, monitor the log output for each table you want to migrate. - -If stats-based sharding is successful on a table, MOLT logs the following `INFO` message: - -~~~ -Stats based sharding enabled for table {table_name} -~~~ - -If stats-based sharding fails on a table, MOLT logs the following `WARNING` message and defaults to range-based sharding: - -~~~ -Warning: failed to shard table {table_name} using stats based sharding: {reason_for_failure}, falling back to non stats based sharding -~~~ - -The number of shards is dependent on the number of distinct values in the first primary key column of the table to be migrated. If this is different from the number of shards requested with `--export-concurrency`, MOLT logs the following `WARNING` and continues with the migration: - -~~~ -number of shards formed: {num_shards_formed} is not equal to number of shards requested: {num_shards_requested} for table {table_name} -~~~ - -Because stats-based sharding analyzes the entire table, running `--use-stats-based-sharding` with [`--filter-path`](#global-flags) (refer to [Selective data movement](#selective-data-movement)) will cause imbalanced shards to form. - -### Data path - -MOLT Fetch can move the source data to CockroachDB via [cloud storage](#bucket-path), a [local file server](#local-path), or [directly](#direct-copy) without an intermediate store. - -#### Bucket path - -{{site.data.alerts.callout_success}} -Only the path specified in `--bucket-path` is used. Query parameters, such as credentials, are ignored. To authenticate cloud storage, follow the steps in [Secure cloud storage](#cloud-storage-security). -{{site.data.alerts.end}} - -`--bucket-path` instructs MOLT Fetch to write intermediate files to a path within [Google Cloud Storage](https://cloud.google.com/storage/docs/buckets), [Amazon S3](https://aws.amazon.com/s3/), or [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) to which you have the necessary permissions. Use additional [flags](#global-flags), shown in the following examples, to specify authentication or region parameters as required for bucket access. - -Connect to a Google Cloud Storage bucket with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#google-cloud-storage-implicit) and [assume role]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#set-up-google-cloud-storage-assume-role): - -{% include_cached copy-clipboard.html %} -~~~ ---bucket-path 'gs://migration/data/cockroach' ---assume-role 'user-test@cluster-ephemeral.iam.gserviceaccount.com' ---use-implicit-auth -~~~ - -Connect to an Amazon S3 bucket and explicitly specify the `ap_south-1` region: - -{% include_cached copy-clipboard.html %} -~~~ ---bucket-path 's3://migration/data/cockroach' ---import-region 'ap-south-1' -~~~ - -{{site.data.alerts.callout_info}} -When `--import-region` is set, `IMPORT INTO` must be used for [data movement](#data-load-mode). -{{site.data.alerts.end}} - -Connect to an Azure Blob Storage container with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}?filters=azure#azure-blob-storage-implicit-authentication): - -{% include_cached copy-clipboard.html %} -~~~ ---bucket-path 'azure-blob://migration/data/cockroach' ---use-implicit-auth -~~~ - -#### Local path - -`--local-path` instructs MOLT Fetch to write intermediate files to a path within a [local file server]({% link {{site.current_cloud_version}}/use-a-local-file-server.md %}). `local-path-listen-addr` specifies the address of the local file server. For example: - -{% include_cached copy-clipboard.html %} -~~~ ---local-path /migration/data/cockroach ---local-path-listen-addr 'localhost:3000' -~~~ - -In some cases, CockroachDB will not be able to use the local address specified by `--local-path-listen-addr`. This will depend on where CockroachDB is deployed, the runtime OS, and the source dialect. - -For example, if you are migrating to CockroachDB {{ site.data.products.cloud }}, such that the {{ site.data.products.cloud }} cluster is in a different physical location than the machine running `molt fetch`, then CockroachDB cannot reach an address such as `localhost:3000`. In these situations, use `--local-path-crdb-access-addr` to specify an address for the local file server that is **publicly accessible**. For example: - -{% include_cached copy-clipboard.html %} -~~~ ---local-path /migration/data/cockroach ---local-path-listen-addr 'localhost:3000' ---local-path-crdb-access-addr '44.55.66.77:3000' -~~~ - -{{site.data.alerts.callout_success}} -[Cloud storage](#bucket-path) is often preferable to a local file server, which can require considerable disk space. -{{site.data.alerts.end}} - -#### Direct copy - -`--direct-copy` specifies that MOLT Fetch should use `COPY FROM` to move the source data directly to CockroachDB without an intermediate store: - -- Because the data is held in memory, the machine must have sufficient RAM for the data currently in flight: - - ~~~ - average size of each row * --row-batch-size * --export-concurrency * --table-concurrency - ~~~ - -- Direct copy does not support compression or [continuation](#fetch-continuation). -- The [`--use-copy`](#data-load-mode) flag is redundant with `--direct-copy`. - -### Schema and table selection - -By default, MOLT Fetch moves all data from the [`--source`](#source-and-target-databases) database to CockroachDB. Use the following flags to move a subset of data. - -`--schema-filter` specifies a range of schema objects to move to CockroachDB, formatted as a POSIX regex string. For example, to move every table in the source database's `public` schema: - -{% include_cached copy-clipboard.html %} -~~~ ---schema-filter 'public' -~~~ - -`--table-filter` and `--table-exclusion-filter` specify tables to include and exclude from the migration, respectively, formatted as POSIX regex strings. For example, to move every source table that has "user" in the table name and exclude every source table that has "temp" in the table name: - -{% include_cached copy-clipboard.html %} -~~~ ---table-filter '.*user.*' --table-exclusion-filter '.*temp.*' -~~~ - -### Selective data movement - -Use `--filter-path` to specify the path to a JSON file that defines row-level filtering for data load. This enables you to move a subset of data in a table, rather than all data in the table. To apply row-level filters during replication, use [MOLT Replicator]({% link molt/molt-replicator.md %}) with userscripts. - -{% include_cached copy-clipboard.html %} -~~~ ---filter-path 'data-filter.json' -~~~ - -The JSON file should contain one or more entries in `filters`, each with a `resource_specifier` (`schema` and `table`) and a SQL expression `expr`. For example, the following example exports only rows from `public.t1` where `v > 100`: - -~~~ json -{ - "filters": [ - { - "resource_specifier": { - "schema": "public", - "table": "t1" - }, - "expr": "v > 100" - } - ] -} -~~~ - -`expr` is case-sensitive and must be valid in your source dialect. For example, when using Oracle as the source, quote all identifiers and escape embedded quotes: - -~~~ json -{ - "filters": [ - { - "resource_specifier": { - "schema": "C##FETCHORACLEFILTERTEST", - "table": "FILTERTBL" - }, - "expr": "ABS(\"X\") > 10 AND CEIL(\"X\") < 100 AND FLOOR(\"X\") > 0 AND ROUND(\"X\", 2) < 100.00 AND TRUNC(\"X\", 0) > 0 AND MOD(\"X\", 2) = 0 AND FLOOR(\"X\" / 3) > 1" - } - ] -} -~~~ - -{{site.data.alerts.callout_info}} -If the expression references columns that are not indexed, MOLT Fetch will emit a warning like: `filter expression ‘v > 100' contains column ‘v' which is not indexed. This may lead to performance issues.` -{{site.data.alerts.end}} - -{% comment %} -#### `--filter-path` userscript for replication - -To use `--filter-path` with replication, create and save a TypeScript userscript (e.g., `filter-script.ts`). The following script ensures that only rows where `v > 100` are replicated to `defaultdb.public.t1`: - -{% include_cached copy-clipboard.html %} -~~~ ts -import * as api from "replicator@v1"; -function disp(doc, meta) { - if (Number(doc.v) > 100) { - return { "defaultdb.public.t1" : [ doc ] }; - } -} -// Always put target schema. -api.configureSource("defaultdb.public", { - deletesTo: disp, - dispatch: disp, -}); -~~~ - -Apply the userscript with the `--userscript` replication flag: - -{% include_cached copy-clipboard.html %} -~~~ ---userscript 'filter-script.ts' -~~~ -{% endcomment %} - -### Target table handling - -`--table-handling` defines how MOLT Fetch loads data on the CockroachDB tables that [match the selection](#schema-and-table-selection). - -To load the data without changing the existing data in the tables, use `none`: - -{% include_cached copy-clipboard.html %} -~~~ ---table-handling none -~~~ - -To [truncate]({% link {{site.current_cloud_version}}/truncate.md %}) tables before loading the data, use `truncate-if-exists`: - -{% include_cached copy-clipboard.html %} -~~~ ---table-handling truncate-if-exists -~~~ - -To drop existing tables and create new tables before loading the data, use `drop-on-target-and-recreate`: - -{% include_cached copy-clipboard.html %} -~~~ ---table-handling drop-on-target-and-recreate -~~~ - -When using the `drop-on-target-and-recreate` option, MOLT Fetch creates a new CockroachDB table to load the source data if one does not already exist. To guide the automatic schema creation, you can [explicitly map source types to CockroachDB types](#type-mapping). `drop-on-target-and-recreate` does **not** create indexes or constraints other than [`PRIMARY KEY`]({% link {{site.current_cloud_version}}/primary-key.md %}) and [`NOT NULL`]({% link {{site.current_cloud_version}}/not-null.md %}). - -#### Mismatch handling - -If either [`none`](#target-table-handling) or [`truncate-if-exists`](#target-table-handling) is set, `molt fetch` loads data into the existing tables on the target CockroachDB database. If the target schema mismatches the source schema, `molt fetch` will exit early in certain cases, and will need to be re-run from the beginning. For details, refer to [Fetch exits early due to mismatches](#fetch-exits-early-due-to-mismatches). - -{{site.data.alerts.callout_info}} -This does not apply when [`drop-on-target-and-recreate`](#target-table-handling) is specified, since this option automatically creates a compatible CockroachDB schema. -{{site.data.alerts.end}} - -#### Skip primary key matching - -`--skip-pk-check` removes the [requirement that source and target tables share matching primary keys](#fetch-exits-early-due-to-mismatches) for data load. When this flag is set: - -- The data load proceeds even if the source or target table lacks a primary key, or if their primary key columns do not match. -- [Table sharding](#table-sharding) is disabled. Each table is exported in a single batch within one shard, bypassing `--export-concurrency` and `--row-batch-size`. As a result, memory usage and execution time may increase due to full table scans. -- If the source table contains duplicate rows but the target has [`PRIMARY KEY`]({% link {{ site.current_cloud_version }}/primary-key.md %}) or [`UNIQUE`]({% link {{ site.current_cloud_version }}/unique.md %}) constraints, duplicate rows are deduplicated during import. - -When `--skip-pk-check` is set, all tables are treated as if they lack a primary key, and are thus exported in a single unsharded batch. To avoid performance issues, use this flag with `--table-filter` to target only tables **without** a primary key. - -For example: - -{% include_cached copy-clipboard.html %} -~~~ shell -molt fetch \ - --mode data-load \ - --table-filter 'nopktbl' \ - --skip-pk-check -~~~ - -Example log output when `--skip-pk-check` is enabled: - -~~~json -{"level":"info","message":"sharding is skipped for table public.nopktbl - flag skip-pk-check is specified and thus no PK for source table is specified"} -~~~ - -#### Type mapping - -If [`drop-on-target-and-recreate`](#target-table-handling) is set, MOLT Fetch automatically creates a CockroachDB schema that is compatible with the source data. The column types are determined as follows: - -- PostgreSQL types are mapped to existing CockroachDB [types]({% link {{site.current_cloud_version}}/data-types.md %}) that have the same [`OID`]({% link {{site.current_cloud_version}}/oid.md %}). -- The following MySQL types are mapped to corresponding CockroachDB types: - - | MySQL type | CockroachDB type | Notes | - |-----------------------------------------------------|-------------------------------------------------------------------------------------------|--------------------------------------------------------------| - | `CHAR`, `CHARACTER`, `VARCHAR`, `NCHAR`, `NVARCHAR` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | - | `TINYTEXT`, `TEXT`, `MEDIUMTEXT`, `LONGTEXT` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | - | `GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | - | `LINESTRING` | [`LINESTRING`]({% link {{site.current_cloud_version}}/linestring.md %}) | Spatial type (PostGIS-style) | - | `POINT` | [`POINT`]({% link {{site.current_cloud_version}}/point.md %}) | Spatial type (PostGIS-style) | - | `POLYGON` | [`POLYGON`]({% link {{site.current_cloud_version}}/polygon.md %}) | Spatial type (PostGIS-style) | - | `MULTIPOINT` | [`MULTIPOINT`]({% link {{site.current_cloud_version}}/multipoint.md %}) | Spatial type (PostGIS-style) | - | `MULTILINESTRING` | [`MULTILINESTRING`]({% link {{site.current_cloud_version}}/multilinestring.md %}) | Spatial type (PostGIS-style) | - | `MULTIPOLYGON` | [`MULTIPOLYGON`]({% link {{site.current_cloud_version}}/multipolygon.md %}) | Spatial type (PostGIS-style) | - | `GEOMETRYCOLLECTION`, `GEOMCOLLECTION` | [`GEOMETRYCOLLECTION`]({% link {{site.current_cloud_version}}/geometrycollection.md %}) | Spatial type (PostGIS-style) | - | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | - | `TINYINT`, `INT1` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | - | `BLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `SMALLINT`, `INT2` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | - | `MEDIUMINT`, `INT`, `INTEGER`, `INT4` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | - | `BIGINT`, `INT8` | [`INT`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | - | `FLOAT` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | - | `DOUBLE` | [`FLOAT`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | - | `DECIMAL`, `NUMERIC`, `REAL` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | - | `BINARY`, `VARBINARY` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `DATETIME` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time (no time zone) | - | `TIMESTAMP` | [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time with time zone | - | `TIME` | [`TIME`]({% link {{site.current_cloud_version}}/time.md %}) | Time of day (no date) | - | `BIT` | [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) | Variable-length bit array | - | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | - | `TINYBLOB`, `MEDIUMBLOB`, `LONGBLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `BOOL`, `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | - -- The following Oracle types are mapped to CockroachDB types: - - | Oracle type(s) | CockroachDB type | Notes | - |---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| - | `NCHAR`, `CHAR`, `CHARACTER` | [`CHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`CHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Fixed-length character; falls back to unbounded if length not specified | - | `VARCHAR`, `VARCHAR2`, `NVARCHAR2` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | - | `STRING` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | - | `SMALLINT` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | - | `INTEGER`, `INT`, `SIMPLE_INTEGER` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | - | `LONG` | [`INT8`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | - | `FLOAT`, `BINARY_FLOAT`, `REAL` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | - | `DOUBLE`, `BINARY_DOUBLE` | [`FLOAT8`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | - | `DEC`, `NUMBER`, `DECIMAL`, `NUMERIC` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %})(p, s) or [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | - | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | - | `BLOB`, `RAW`, `LONG RAW` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | - | `CLOB`, `NCLOB` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as large text | - | `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | - | `TIMESTAMP` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) or [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | If `WITH TIME ZONE` → `TIMESTAMPTZ`, else `TIMESTAMP` | - | `ROWID`, `UROWID` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as opaque identifier | - | `SDO_GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | - | `XMLTYPE` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Stored as text | - -- To override the default mappings for automatic schema creation, you can map source to target CockroachDB types explicitly. These are defined in the JSON file indicated by the `--type-map-file` flag. The allowable custom mappings are valid CockroachDB aliases, casts, and the following mappings specific to MOLT Fetch and [Verify]({% link molt/molt-verify.md %}): - - - [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) <> [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) - - [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) <> [`UUID`]({% link {{site.current_cloud_version}}/uuid.md %}) - - [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) <> [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) - - [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) - - [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) <> [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) - - [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) - - [`INET`]({% link {{site.current_cloud_version}}/inet.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) - -`--type-map-file` specifies the path to the JSON file containing the explicit type mappings. For example: - -{% include_cached copy-clipboard.html %} -~~~ ---type-map-file 'type-mappings.json' -~~~ - -The following JSON example defines two type mappings: - -~~~ json - [ - { - "table": "public.t1", - "column_type_map": [ - { - "column": "*", - "source_type": "int", - "crdb_type": "INT2" - }, - { - "column": "name", - "source_type": "varbit", - "crdb_type": "string" - } - ] - } -] -~~~ - -- `table` specifies the table that will use the custom type mappings in `column_type_map`. The value is written as `{schema}.{table}`. -- `column` specifies the column that will use the custom type mapping. If `*` is specified, then all columns in the `table` with the matching `source_type` are converted. -- `source_type` specifies the source type to be mapped. -- `crdb_type` specifies the target CockroachDB [type]({% link {{ site.current_cloud_version }}/data-types.md %}) to be mapped. - -### Transformations - -You can define transformation rules to be performed on the target schema during the fetch task. These can be used to: - -- Map [computed columns]({% link {{ site.current_cloud_version }}/computed-columns.md %}) to a target schema. -- Map [partitioned tables]({% link {{ site.current_cloud_version }}/partitioning.md %}) to a single target table. -- Rename tables on the target schema. - -Transformation rules are defined in the JSON file indicated by the `--transformations-file` flag. For example: - -{% include_cached copy-clipboard.html %} -~~~ ---transformations-file 'transformation-rules.json' -~~~ - -The following JSON example defines two transformation rules: - -~~~ json -{ - "transforms": [ - { - "id": 1, - "resource_specifier": { - "schema": ".*", - "table": ".*" - }, - "column_exclusion_opts": { - "add_computed_def": true, - "column": "^age$" - } - }, - { - "id": 2, - "resource_specifier": { - "schema": "public", - "table": "charges_part.*" - }, - "table_rename_opts": { - "value": "charges" - } - } - ] -} -~~~ - -- `resource_specifier` configures the following options for transformation rules: - - `schema` specifies the schemas to be affected by the transformation rule, formatted as a POSIX regex string. - - `table` specifies the tables to be affected by the transformation rule, formatted as a POSIX regex string. -- `column_exclusion_opts` configures the following options for column exclusions and computed columns: - - `column` specifies source columns to exclude from being mapped to regular columns on the target schema. It is formatted as a POSIX regex string. - - `add_computed_def`, when set to `true`, specifies that each matching `column` should be mapped to a [computed column]({% link {{ site.current_cloud_version }}/computed-columns.md %}) on the target schema. Instead of being moved from the source, the column data is generated on the target using [`ALTER TABLE ... ADD COLUMN`]({% link {{ site.current_cloud_version }}/alter-table.md %}#add-column) and the computed column definition from the source schema. This assumes that all matching columns are computed columns on the source. - {{site.data.alerts.callout_danger}} - Columns that match the `column` regex will **not** be moved to CockroachDB if `add_computed_def` is omitted or set to `false` (default), or if a matching column is a non-computed column. - {{site.data.alerts.end}} -- `table_rename_opts` configures the following option for table renaming: - - `value` specifies the table name to which the matching `resource_specifier` is mapped. If only one source table matches `resource_specifier`, it is renamed to `table_rename_opts.value` on the target. If more than one table matches `resource_specifier` (i.e., an n-to-1 mapping), the fetch task assumes that all matching tables are [partitioned tables]({% link {{ site.current_cloud_version }}/partitioning.md %}) with the same schema, and moves their data to a table named `table_rename_opts.value` on the target. Otherwise, the task will error. - - Additionally, in an n-to-1 mapping situation: - - - Specify [`--use-copy`](#data-load-mode) or [`--direct-copy`](#direct-copy) for data movement. This is because the data from the source tables is loaded concurrently into the target table. - - Create the target table schema manually, and do **not** use [`--table-handling drop-on-target-and-recreate`](#target-table-handling) for target table handling. - -The preceding JSON example therefore defines two rules: - -- Rule `1` maps all source `age` columns on the source database to [computed columns]({% link {{ site.current_cloud_version }}/computed-columns.md %}) on CockroachDB. This assumes that all matching `age` columns are defined as computed columns on the source. -- Rule `2` maps all table names with prefix `charges_part` from the source database to a single `charges` table on CockroachDB (i.e., an n-to-1 mapping). This assumes that all matching `charges_part.*` tables have the same schema. - -Each rule is applied in the order it is defined. If two rules overlap, the later rule will override the earlier rule. - -To verify that the logging shows that the computed columns are being created: - -When running `molt fetch`, set `--logging debug` and look for `ALTER TABLE ... ADD COLUMN` statements with the `STORED` or `VIRTUAL` keywords in the log output: - -~~~ json -{"level":"debug","time":"2024-07-22T12:01:51-04:00","message":"running: ALTER TABLE IF EXISTS public.computed ADD COLUMN computed_col INT8 NOT NULL AS ((col1 + col2)) STORED"} -~~~ - -After running `molt fetch`, issue a `SHOW CREATE TABLE` statement on CockroachDB: - -{% include_cached copy-clipboard.html %} -~~~ sql -SHOW CREATE TABLE computed; -~~~ - -~~~ - table_name | create_statement --------------+------------------------------------------------------------------- - computed | CREATE TABLE public.computed ( - ... - | computed_col INT8 NOT NULL AS (col1 + col2) STORED - | ) -~~~ - -### Fetch continuation - -If MOLT Fetch fails while loading data into CockroachDB from intermediate files, it exits with an error message, fetch ID, and [continuation token](#list-active-continuation-tokens) for each table that failed to load on the target database. You can use this information to continue the task from the *continuation point* where it was interrupted. - -Continuation is only possible under the following conditions: - -- All data has been exported from the source database into intermediate files on [cloud](#bucket-path) or [local storage](#local-path). -- The *initial load* of source data into the target CockroachDB database is incomplete. - -{{site.data.alerts.callout_info}} -Only one fetch ID and set of continuation tokens, each token corresponding to a table, are active at any time. See [List active continuation tokens](#list-active-continuation-tokens). -{{site.data.alerts.end}} - -To retry all data starting from the continuation point, reissue the `molt fetch` command and include the `--fetch-id`. - -{% include_cached copy-clipboard.html %} -~~~ ---fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 -~~~ - -To retry a specific table that failed, include both `--fetch-id` and `--continuation-token`. The latter flag specifies a token string that corresponds to a specific table on the source database. A continuation token is written in the `molt fetch` output for each failed table. If the fetch task encounters a subsequent error, it generates a new token for each failed table. See [List active continuation tokens](#list-active-continuation-tokens). - -{{site.data.alerts.callout_info}} -This will retry only the table that corresponds to the continuation token. If the fetch task succeeds, there may still be source data that is not yet loaded into CockroachDB. -{{site.data.alerts.end}} - -{% include_cached copy-clipboard.html %} -~~~ ---fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 ---continuation-token 011762e5-6f70-43f8-8e15-58b4de10a007 -~~~ - -To retry all data starting from a specific file, include both `--fetch-id` and `--continuation-file-name`. The latter flag specifies the filename of an intermediate file in [cloud or local storage](#data-path). All filenames are prepended with `part_` and have the `.csv.gz` or `.csv` extension, depending on compression type (gzip by default). For example: - -{% include_cached copy-clipboard.html %} -~~~ ---fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 ---continuation-file-name part_00000003.csv.gz -~~~ - -{{site.data.alerts.callout_info}} -Continuation is not possible when using [direct copy](#direct-copy). -{{site.data.alerts.end}} - -#### List active continuation tokens - -To view all active continuation tokens, issue a `molt fetch tokens list` command along with `--conn-string`, which specifies the [connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url) for the target CockroachDB database. For example: - -{% include_cached copy-clipboard.html %} -~~~ shell -molt fetch tokens list \ ---conn-string 'postgres://root@localhost:26257/defaultdb?sslmode=verify-full' -~~~ - -~~~ -+--------------------------------------+--------------------------------------+------------------+----------------------+ -| ID | FETCH ID | TABLE NAME | FILE NAME | -+--------------------------------------+--------------------------------------+------------------+----------------------+ -| f6f0284c-d9c1-43c9-8fde-af609d0dbd82 | 66443597-5689-4df3-a7b9-9fc5e27180eb | public.employees | part_00000001.csv.gz | -+--------------------------------------+--------------------------------------+------------------+----------------------+ -Continuation Tokens. -~~~ - -### CDC cursor - -A change data capture (CDC) cursor is written to the output as `cdc_cursor` at the beginning and end of the fetch task. For example: - -~~~ json -{"level":"info","type":"summary","fetch_id":"735a4fe0-c478-4de7-a342-cfa9738783dc","num_tables":1,"tables":["public.employees"],"cdc_cursor":"b7f9e0fa-2753-1e1f-5d9b-2402ac810003:3-21","net_duration_ms":4879.890041,"net_duration":"000h 00m 04s","time":"2024-03-18T12:37:02-04:00","message":"fetch complete"} -~~~ - -Use the `cdc_cursor` value as the checkpoint for MySQL or Oracle replication with [MOLT Replicator]({% link molt/molt-replicator.md %}#replication-checkpoints). - -You can also use the `cdc_cursor` value with an external change data capture (CDC) tool to continuously replicate subsequent changes from the source database to CockroachDB. - -## Security - -Cockroach Labs strongly recommends the following security practices. - -### Connection security - -{% include molt/molt-secure-connection-strings.md %} - -{{site.data.alerts.callout_info}} -By default, insecure connections (i.e., `sslmode=disable` on PostgreSQL; `sslmode` not set on MySQL) are disallowed. When using an insecure connection, `molt fetch` returns an error. To override this check, you can enable the `--allow-tls-mode-disable` flag. Do this **only** when testing, or if a secure SSL/TLS connection to the source or target database is not possible. -{{site.data.alerts.end}} - -### Cloud storage security - -{% include molt/fetch-secure-cloud-storage.md %} - -## Common workflows - -### Bulk data load - -To perform a bulk data load migration from your source database to CockroachDB, run the `molt fetch` command with the required flags. - -Specify the source and target database connections. For connection string formats, refer to [Source and target databases](#source-and-target-databases): - -{% include_cached copy-clipboard.html %} -~~~ ---source $SOURCE ---target $TARGET -~~~ - -Specify how to move data to CockroachDB. Use [cloud storage](#bucket-path) for intermediate file storage: - -{% include_cached copy-clipboard.html %} -~~~ ---bucket-path 's3://bucket/path' -~~~ - -Alternatively, use a [local file server](#local-path) for intermediate storage: - -{% include_cached copy-clipboard.html %} -~~~ ---local-path /migration/data/cockroach ---local-path-listen-addr 'localhost:3000' -~~~ - -Alternatively, use [direct copy](#direct-copy) to move data directly without intermediate storage: - -{% include_cached copy-clipboard.html %} -~~~ ---direct-copy -~~~ - -Optionally, filter which schemas and tables to migrate. By default, all schemas and tables are migrated. For details, refer to [Schema and table selection](#schema-and-table-selection): - -{% include_cached copy-clipboard.html %} -~~~ ---schema-filter 'public' ---table-filter '.*user.*' -~~~ - -Specify how to handle target tables. By default, `--table-handling` is set to `none`, which loads data without changing existing data in the tables. For details, refer to [Target table handling](#target-table-handling): - -{% include_cached copy-clipboard.html %} -~~~ ---table-handling truncate-if-exists -~~~ - -When performing a bulk load without subsequent replication, use `--ignore-replication-check` to skip querying for replication checkpoints (such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle). This is appropriate when: - -- Performing a one-time data migration with no plan to replicate ongoing changes. -- Exporting data from a read replica where replication checkpoints are unavailable. - -{% include_cached copy-clipboard.html %} -~~~ ---ignore-replication-check -~~~ - -At minimum, the `molt fetch` command should include the source, target, data path, and `--ignore-replication-check` flags: - -{% include_cached copy-clipboard.html %} -~~~ shell -molt fetch \ ---source $SOURCE \ ---target $TARGET \ ---bucket-path 's3://bucket/path' \ ---ignore-replication-check -~~~ - -For detailed steps, refer to [Bulk load migration]({% link molt/migrate-bulk-load.md %}). - -### Load before replication - -To perform an initial data load before setting up ongoing replication with [MOLT Replicator]({% link molt/molt-replicator.md %}), run the `molt fetch` command without `--ignore-replication-check`. This captures replication checkpoints during the data load. - -The workflow is the same as [Bulk data load](#bulk-data-load), except: - -- Exclude `--ignore-replication-check`. MOLT Fetch will query and record replication checkpoints. -- After the data load completes, check the [CDC cursor](#cdc-cursor) in the output for the checkpoint value to use with MOLT Replicator. - -At minimum, the `molt fetch` command should include the source, target, and data path flags: - -{% include_cached copy-clipboard.html %} -~~~ shell -molt fetch \ ---source $SOURCE \ ---target $TARGET \ ---bucket-path 's3://bucket/path' -~~~ - -The output will include a `cdc_cursor` value at the end of the fetch task: - -~~~ json -{"level":"info","type":"summary","fetch_id":"735a4fe0-c478-4de7-a342-cfa9738783dc","num_tables":1,"tables":["public.employees"],"cdc_cursor":"b7f9e0fa-2753-1e1f-5d9b-2402ac810003:3-21","net_duration_ms":4879.890041,"net_duration":"000h 00m 04s","time":"2024-03-18T12:37:02-04:00","message":"fetch complete"} -~~~ - -Use this `cdc_cursor` value when starting MOLT Replicator to ensure replication begins from the correct position. For detailed steps, refer to [Load and replicate]({% link molt/migrate-load-replicate.md %}). - -## Monitoring - -### Metrics - -By default, MOLT Fetch exports [Prometheus](https://prometheus.io/) metrics at `127.0.0.1:3030/metrics`. You can configure this endpoint with the `--metrics-listen-addr` [flag](#global-flags). - -Cockroach Labs recommends monitoring the following metrics: - -| Metric Name | Description | -|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------| -| `molt_fetch_num_tables` | Number of tables that will be moved from the source. | -| `molt_fetch_num_task_errors` | Number of errors encountered by the fetch task. | -| `molt_fetch_overall_duration` | Duration (in seconds) of the fetch task. | -| `molt_fetch_rows_exported` | Number of rows that have been exported from a table. For example:
`molt_fetch_rows_exported{table="public.users"}` | -| `molt_fetch_rows_imported` | Number of rows that have been imported from a table. For example:
`molt_fetch_rows_imported{table="public.users"}` | -| `molt_fetch_table_export_duration_ms` | Duration (in milliseconds) of a table's export. For example:
`molt_fetch_table_export_duration_ms{table="public.users"}` | -| `molt_fetch_table_import_duration_ms` | Duration (in milliseconds) of a table's import. For example:
`molt_fetch_table_import_duration_ms{table="public.users"}` | - -You can also use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view the preceding metrics. - -## Best practices - -### Test and validate - -To verify that your connections and configuration work properly, run MOLT Fetch in a staging environment before migrating any data in production. Use a test or development environment that closely resembles production. - -### Configure the source database and connection - -- To prevent connections from terminating prematurely during the [data export phase](#data-export-phase), set the following to high values on the source database: - - - **Maximum allowed number of connections.** MOLT Fetch can export data across multiple connections. The number of connections it will create is the number of shards ([`--export-concurrency`](#global-flags)) multiplied by the number of tables ([`--table-concurrency`](#global-flags)) being exported concurrently. - - {{site.data.alerts.callout_info}} - With the default numerical range sharding, only tables with [primary key]({% link {{ site.current_cloud_version }}/primary-key.md %}) types of [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) can be sharded. PostgreSQL users can enable [`--use-stats-based-sharding`](#global-flags) to use statistics-based sharding for tables with primary keys of any data type. For details, refer to [Table sharding](#table-sharding). - {{site.data.alerts.end}} - - - **Maximum lifetime of a connection.** - -- If a PostgreSQL database is set as a [source](#source-and-target-databases), ensure that [`idle_in_transaction_session_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT) on PostgreSQL is either disabled or set to a value longer than the duration of the [data export phase](#data-export-phase). Otherwise, the connection will be prematurely terminated. To estimate the time needed to export the PostgreSQL tables, you can perform a dry run and sum the value of [`molt_fetch_table_export_duration_ms`](#monitoring) for all exported tables. - -### Optimize performance - -- {% include molt/molt-drop-constraints-indexes.md %} - -- For PostgreSQL sources using [`--use-stats-based-sharding`](#global-flags), run [`ANALYZE`]({% link {{ site.current_cloud_version }}/create-statistics.md %}) on source tables before migration to ensure optimal shard distribution. This is especially important for large tables where even distribution can significantly improve export performance. - -- To prevent memory outages during `READ COMMITTED` [data export](#data-export-phase) of tables with large rows, estimate the amount of memory used to export a table: - - ~~~ - --row-batch-size * --export-concurrency * average size of the table rows - ~~~ - - If you are exporting more than one table at a time (i.e., [`--table-concurrency`](#global-flags) is set higher than `1`), add the estimated memory usage for the tables with the largest row sizes. Ensure that you have sufficient memory to run `molt fetch`, and adjust `--row-batch-size` accordingly. For details on how concurrency and sharding interact, refer to [Table sharding](#table-sharding). - -- If a table in the source database is much larger than the other tables, [filter and export the largest table](#schema-and-table-selection) in its own `molt fetch` task. Repeat this for each of the largest tables. Then export the remaining tables in another task. - -- Ensure that the machine running MOLT Fetch is large enough to handle the amount of data being migrated. Fetch performance can sometimes be limited by available resources, but should always be making progress. To identify possible resource constraints, observe the `molt_fetch_rows_exported` [metric](#monitoring) for decreases in the number of rows being processed. You can use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view metrics. For details on optimizing export performance through sharding, refer to [Table sharding](#table-sharding). - -### Import and continuation handling - -- When using [`IMPORT INTO`](#data-load-mode) during the [data import phase](#data-import-phase) to load tables into CockroachDB, if the fetch task terminates before the import job completes, the hanging import job on the target database will keep the table offline. To make this table accessible again, [manually resume or cancel the job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs). Then resume `molt fetch` using [continuation](#fetch-continuation), or restart the task from the beginning. - -## Troubleshooting - -
- - - -
- -{% include molt/molt-troubleshooting-fetch.md %} - ## See also - [Migration Overview]({% link molt/migration-overview.md %}) From d2a9b909d9bc6fad5ec8dc7b97cde3fbc3ce9bde Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Fri, 21 Nov 2025 17:08:14 -0500 Subject: [PATCH 02/15] worked out the IA for migration variables, basically --- src/current/images/molt/molt_flows_3.svg | 736 ++++++++++++++++++ .../molt/migration-considerations-phases.md | 164 +--- src/current/molt/migration-considerations.md | 62 +- src/current/molt/migration-overview.md | 40 +- src/current/molt/migration-strategy.md | 14 - 5 files changed, 805 insertions(+), 211 deletions(-) create mode 100644 src/current/images/molt/molt_flows_3.svg diff --git a/src/current/images/molt/molt_flows_3.svg b/src/current/images/molt/molt_flows_3.svg new file mode 100644 index 00000000000..fa8a9d22f72 --- /dev/null +++ b/src/current/images/molt/molt_flows_3.svg @@ -0,0 +1,736 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/current/molt/migration-considerations-phases.md b/src/current/molt/migration-considerations-phases.md index e14a625fb0d..fc856f1ceac 100644 --- a/src/current/molt/migration-considerations-phases.md +++ b/src/current/molt/migration-considerations-phases.md @@ -5,17 +5,18 @@ toc: true docs_area: migrate --- -Choosing between a **bulk migration** (migrating all data at once) and a **phased migration** (migrating data in slices) is one of the most important decisions in your CockroachDB migration plan. This page explains when to choose each approach, how to define phases, and how to use MOLT tools effectively in either context. For end-to-end sequencing, see []. +You may choose to migrate all of your data into a CockroachDB cluster at once. However, for larger data stores it's recommended that you migrate data in separate phases. This can help break the migration down into manageable slices, and it can help limit the effects of migration difficulties. + +This page explains when to choose each approach, how to define phases, and how to use MOLT tools effectively in either context. In general: -* Choose a **bulk migration** if you can fit the entire migration sequence within a planned downtime window, your data volume is modest, and external integrations are simple. +- Choose to migrate your data **all at once** if your data volume is modest, if you want to minimize migration complexity, or if you don't mind taking on a greater risk of something going wrong. -* Choose a **phased migration** if your data volume is large or if need to limit risk and downtime blast radius, or you can naturally partition workload by tenant, service/domain, table/shard, geography, or time. Use MOLT Fetch for initial loads per slice, MOLT Replicator for ongoing changes, MOLT Verify for per-slice checks, and perform many small cutovers instead of one big bang. +- Choose a **phased migration** if your data volume is large, especially if you can naturally partition workload by tenant, service/domain, table/shard, geography, or time. A phased migration helps to reduce risk by limiting the workloads that would be adversely affected by a migration failure. It also helps to limit the downtime per phase, and allows the application to continue serving unaffected subsets of the data during the migration of a phase. ---- +## How to divide migrations into phases -### How to think about “phases” Here are some common ways to divide migrations: * **Per-tenant**: Multi-tenant apps route traffic and data per customer/tenant. Migrate a small cohort first (canary), then progressively larger cohorts. This aligns with access controls and isolates blast radius. @@ -28,147 +29,48 @@ Here are some common ways to divide migrations: Tips for picking slices: -* Prefer slices with clear routing keys (tenant_id, region_id) to simplify cutover and verification. +- Prefer slices with clear routing keys (tenant_id, region_id) to simplify cutover and verification. -* Start with lower-risk/impact slices to exercise the toolchain and runbooks before high-value cohorts. +- Start with lower-impact slices to exercise the migration process before migrating high-value cohorts. -* Ensure each slice has an explicit rollback option and a measurable definition of “done” (schema parity, row counts/checksums, app SLOs). - ---- +## Tradeoffs -### Tradeoffs: Bulk vs. Phased -The table below captures the core differences. - -| Factor | Bulk migration | Phased migration | +| | All at once | Phased | |---|---|---| -| Downtime | Single, longer window; must fit full load + index build | Multiple short windows; can achieve minimal downtime per slice via replication | -| Risk | Higher blast radius if issues surface post-cutover | Lower blast radius; issues confined to a slice | -| Complexity | Simpler orchestration; one cutover | More orchestration; repeated verify and cutover steps | +| Downtime | A single downtime window, but it affects the whole database | Multiple short windows, each with limited impact | +| Risk | Higher blast radius if issues surface post-cutover | Lower blast radius, issues confined to a slice | +| Complexity | Simpler orchestration, enables a single cutover | More orchestration, repeated verify and cutover steps | | Validation | One-time, system-wide | Iterative per slice; faster feedback loops | -| Timeline | Shorter elapsed run if everything fits | Longer calendar time but safer path | -| Best for | Small/medium datasets, simple integrations, tolerant of planned downtime | Multi-tenant/sharded/microservice estates, low downtime tolerance, risk-averse programs | - -Bulk loads and minimal-downtime flows are supported natively by MOLT; see the dedicated flow pages for detailed steps. - ---- +| Timeline | Shorter migration time | Longer calendar time but safer path | +| Best for | Small/medium datasets, simple integrations | Larger datasets, data with natural partitions or multiple tenants, risk-averse migrations | ## MOLT toolkit support -#### Bulk migration (all-at-once) -When: You can complete the full data load and post-load steps within the maintenance window. - -Tool pattern: - -1) **Schema conversion**: Generate CockroachDB DDL with the Schema Conversion Tool (SCT), apply DDL, and drop secondary indexes/constraints that slow load (you’ll rebuild later). - -2) **Initial load**: Run **MOLT Fetch** in data-load mode to bulk-ingest the entire dataset. - -3) **Pre-cutover verify**: Run **MOLT Verify** for row counts/checksums and schema parity before you expose the target to traffic. - -4) **Finalize schema**: Recreate indexes/constraints that were deferred to accelerate load. - -5) **Cutover**: Redirect application traffic to CockroachDB; no replication is required in a pure bulk flow. - -Notes: - -* If your “bulk” window is tight, consider “load then replicate” even for a single-shot migration; it reduces write pause during cutover by draining replication rather than loading everything during downtime. - -#### Phased migration (sliced) -When: You want to reduce risk, limit downtime blast radius, and/or leverage natural partitions (tenants/services/tables/shards/regions). - -Per-slice loop: - -1) **Define the slice**: Specify the routing key and all tables touched by the slice (including reference/lookup tables). Document read/write paths and dependencies. - -2) **Schema conversion once; parameterize per slice**: Run SCT to produce target DDL; apply once. If you need per-slice variants (e.g., tenant-specific objects), template them. - -3) **Initial load for the slice**: Use **MOLT Fetch** to move only the slice’s rows (via filters/selection); for large tables, consider range-based or predicate-based extraction. - -4) **Start continuous replication**: Enable **MOLT Replicator** to stream ongoing changes from source to CockroachDB for just that slice. Let lag stabilize. - -5) **Per-slice verification**: Run **MOLT Verify** focused on the slice (row counts, checksums, schema), and—optionally—semantic checks at the app layer (read-your-writes, idempotency behavior, latency). - -6) **Micro-cutover**: Pause writes for the slice (e.g., drain tenant/service traffic), wait for replication to drain, then route that slice to CockroachDB. Keep replication running temporarily for safety or to support failback policies. - -7) **Rinse and repeat**: Expand to the next slice as confidence grows. Keep a clear rollback runbook per slice. When all slices are moved, disable replication and decommission the source. - -Notes: - -* If business requires a back-out path during or after cutover, configure **failback** mode to replicate from CockroachDB back to the source until the rollback window expires. - -* Treat each slice as a rehearsal—tune cluster sizing, indexing, and app configuration iteratively based on observations. +Phased and unphased migrations are both supported natively by MOLT. ---- - -### Cutover considerations (both approaches) -Regardless of approach: - -* Plan and rehearse cutover, including DNS/connection string flips, credential rotation, feature flags, and cache invalidation paths. - -* For minimal downtime, combine “initial load + continuous replication,” then briefly pause writes to drain replication before finalizing cutover; the pause length depends on write volume and replication lag. - -* Define a clear rollback plan. With replicator failback, you can synchronize CockroachDB-side changes back to the source to restore service quickly if needed. - ---- - -### Choosing the right approach: a quick rubric -Score each item 1–5; higher totals favor phased migrations. - -* Data volume and size of indexes are too large for your maintenance window. - -* Application is mission-critical; downtime tolerance is near-zero or seconds. - -* Estate is naturally partitioned (tenants/services/shards/regions), enabling isolated routing. - -* High integration surface area (ETL, reporting, downstream consumers) increases change risk. - -* Organization prefers incremental risk and progressive validation over a one-time event. - -If your total is high, phase it. If your total is low and downtime is acceptable, bulk may be simpler. +By default, [MOLT Fetch]() moves all data from the source database to CockroachDB. However, you can use the `--schema-filter`, `--table-filter`, and `--filter-path` flags to selective migrate data from the source to the target. Learn more about [schema and table selection]({% link molt/molt-fetch-usage.md %}#schema-and-table-selection) and [selective data movement]({% link molt/molt-fetch-usage.md %}#selective-data-movement), both of which can enable a phased migration. ---- - -### Example blueprints - -#### Bulk (planned downtime) -* SCT -> apply DDL (defer secondary indexes) - -* Fetch (data-load) full dataset - -* Verify (counts/checksums) - -* Rebuild indexes; smoke test - -* Cutover all traffic to CockroachDB +Similarly, you can use [MOLT Verify]()'s `--schema-filter` and `--table-filter` flags to run validation checks on subsets of the data in your source and target databases. In a phased migration, you will likely want to verify data at the end of each migration phase, rather than at the end of the entire migration. -#### Phased (per-tenant) -* Choose 5 low-risk tenants as canary +[MOLT Replicator]() replicates full tables by default. If you choose to combine phased migration with [continuous replication]({% link molt/migration-considerations-replication.md %}), you will either need to select phases that include whole tables, or else use [userscripts]({% link molt/molt-replicator.md %}#flags) to select rows to replicate. -* SCT once; apply DDL +## Example sequences -* Fetch tenant rows; start Replicator for those tenants +### Migrating all data at once -* Verify per tenant; drain and cut over tenant traffic +
+MOLT tooling overview +
-* Repeat with larger cohorts; disable Replicator after final cohort - ---- - -### MOLT references -* Migration Overview: sequencing and tool roles. - -* Migration Strategy: planning downtime, validation, and cutover. - -* Migrate to CockroachDB: flow-specific guidance including bulk load, load and replicate, resume replication, and failback. - ---- +### Phased migration -### Appendix: FAQ -Q: Can I mix bulk and phased? -A: Yes. Many teams bulk-load non-critical/static tables during a short window, and phase live/critical tables with replication and micro-cutovers. +
+MOLT tooling overview +
-Q: How do I pick the first slice? -A: Choose a slice with clear routing keys, moderate data volume, and limited dependencies—often a low-risk tenant or a service-owned table set. This maximizes learning with minimal blast radius. +## See Also -Q: When should I enable failback? -A: For mission-critical workloads or when organizational risk tolerance requires a rollback window after cutover. Keep failback replication running until SLAs are met and stakeholders sign off. +- [Migration Overview]({% link molt/migration-overview.md %}) +- [Migration Considerations]({% link molt/migration-considerations.md %}) +- [Continuous Replication]({% link molt/migration-considerations-replication.md %}) +- [MOLT Fetch]({% link molt/molt-fetch-overview.md %}) diff --git a/src/current/molt/migration-considerations.md b/src/current/molt/migration-considerations.md index 4c4fd98ac24..15518dd0c82 100644 --- a/src/current/molt/migration-considerations.md +++ b/src/current/molt/migration-considerations.md @@ -24,71 +24,45 @@ Learn more about each migration variable by clicking the links in the left-hand The combination of these variables largely defines your migration approach. While you'll typically choose one primary option for each variable, some migrations may involve a hybrid approach depending on your specific requirements. -## Things to consider +## Factors to consider When deciding on the options for each migration variable, consider the following business and technical requirements: -### Allowable downtime +### Permissible downtime -How much downtime can your application tolerate during the migration? This is one of the most critical factors in determining your migration approach: +How much downtime can your application tolerate during the migration? This is one of the most critical factors in determining your migration approach, and it may influence your choices for [migration granularity](), [continuous replication](), and [cutover strategy](). -- **Planned downtime**: If you can take the application offline for several hours or more, a simpler bulk load approach may be sufficient. You can load all data during the downtime window, verify it, and then bring the application back online on CockroachDB. +- **Planned downtime** is made known to your users in advance. It involves taking the application offline, conducting the migration, and bginging the application back online on CockroachDB. -- **Minimal downtime**: If you need to minimize user impact (ideally to seconds or minutes), you'll need to use continuous replication to keep CockroachDB synchronized with the source database. Application writes are paused only briefly to allow the replication stream to drain before cutover. + To succeed, you should estimate the amount of downtime required to migrate your data, and ideally schedule the downtime outside of peak hours. Scheduling downtime is easiest if your application traffic is "periodic", meaning that it varies by the time of day, day of week, or day of month. -- **Zero downtime**: For mission-critical applications that cannot tolerate any downtime, consider a phased migration where you progressively move slices of data (e.g., per-tenant or per-service) while maintaining dual-write capabilities or bidirectional replication. + If you can support planned downtime, you may want to migrate your data [all at once]({% link molt/migration-considerations-phases.md %}), and _without_ [continuous replication]({% link molt/migration-considerations-replication.md %}). -Your downtime tolerance will influence your choices for data transfer approach, validation strategy, and cutover strategy. +- **Minimal downtime** impacts as few customers as possible, ideally without impacting their regular usage. If your application is intentionally offline at certain times (e.g., outside business hours), you can migrate the data without users noticing. Alternatively, if your application's functionality is not time-sensitive (e.g., it sends batched messages or emails), you can queue requests while the system is offline and process them after completing the migration to CockroachDB. -### Migration timeframe +- **Near-zero downtime** is necessary for mission-critical applications. For these migrations, consider cutover strategies that keep applications online for as long as possible, and which utilize [continuous replication](). -When do you need to complete the migration, and how does this timeline affect your approach? +In addition to downtime duration, consider whether your application could support windows of **reduced functionality** in which some, but not all, application functionality is brought offline. For example, you can disable writes but not reads while you migrate the application data, and queue data to be written after completing the migration. -- **Shorter calendar time**: If you need to complete the migration quickly and can tolerate planned downtime, a bulk migration may be the fastest path. However, this concentrates risk into a single event. +### Migration timeframe and allowable complexity -- **Longer calendar time**: If you have more time available, a phased migration allows you to reduce risk by migrating in smaller increments. This takes longer overall but provides faster feedback loops and the ability to adjust your approach based on early results. +When do you need to complete the migration? How many team members can be allocated for this effort? How much complex orchestration can your team manage? These factors may influence your choices for [migration granularity](), [continuous replication](), and [cutover strategy](). -- **Team availability**: Consider when your migration team and stakeholders are available. Can you schedule a migration during off-peak hours or weekends? Do you need to coordinate with multiple teams? +- Migrations with a short timeline, or which cannot accommodate high complexity, may want to migrate data [all at once](), without utilizing [continuous replication](), and requiring [manual reconciliation]() in the event of migration failure. -Your migration timeframe will influence whether you choose a bulk or phased approach, and how aggressively you can schedule cutover windows. +- Migrations with a long timeline, or which can accomodate complexity, may want to migrate data [in phases](). If the migration requires minimal downtime, these migrations may also want to utilize [continuous replication](). If the migration is low in risk-tolerance, these migrations may also want to enable [failback](). ### Risk tolerance -How much risk is your organization willing to accept during the migration? +How much risk is your organization willing to accept during the migration? This may influence your choices for [migration granularity](), [validation strategy](), and [rollback plan](). -- **Risk-averse**: Organizations with low risk tolerance should prefer phased migrations that limit the blast radius of any issues. Start with low-risk slices (e.g., a small cohort of tenants or a non-critical service), validate thoroughly, and progressively expand to higher-value workloads. +- Risk-averse migrations should prefer [phased migrations]() that limit the blast radius of any issues. Start with low-risk slices (e.g., a small cohort of tenants or a non-critical service), [validate thoroughly](), and progressively expand to higher-value workloads. These migrations may also prefer [rollback plans]() that enable quick recovery in the event of migration issues. -- **Risk-tolerant**: If you're comfortable with higher risk and can recover quickly from issues, a bulk migration may be acceptable. This is especially true for development or staging environments, or for applications with strong rollback capabilities. +- For risk-tolerant migrations, it may be acceptable to migrate [all of your data at once](). Less stringent [validation strategies]() and [manual reconciliation]() in the event of a migration failure may also be acceptable. -- **Rollback requirements**: Does your organization require the ability to roll back the migration after cutover? This will influence your choice of rollback plan (e.g., failback replication vs. manual reconciliation). +___ -Your risk tolerance will influence your choices for migration granularity, rollback plan, and validation strategy. - -### Allowable migration complexity - -How complex of a migration can your team execute and maintain? - -- **Simple migrations**: Bulk migrations with planned downtime are generally simpler to orchestrate. They involve fewer moving parts and a single cutover event. This is best for teams with limited migration experience or smaller datasets. - -- **Complex migrations**: Phased migrations with continuous replication, per-slice validation, and progressive cutover require more sophisticated orchestration. You'll need to manage replication streams, coordinate multiple cutover windows, and maintain clear rollback runbooks for each slice. This is best for experienced teams managing large-scale or mission-critical migrations. - -- **Team expertise**: Consider your team's familiarity with the MOLT tools, CockroachDB, and migration best practices. Can you dedicate time for dry runs and rehearsals? Do you have monitoring and alerting in place? - -Your team's capacity and expertise will influence the complexity of the migration approach you can successfully execute. - -### Additional factors - -Other factors that may influence your migration decisions: - -- **Data volume**: Larger datasets may require phased migrations to fit within maintenance windows and to manage resource consumption during load. - -- **Application architecture**: Multi-tenant applications, microservices, and sharded databases are natural candidates for phased migrations. Monolithic applications may be better suited to bulk migrations. - -- **Integration surface area**: Applications with many downstream consumers (ETL pipelines, analytics tools, third-party integrations) may benefit from phased migrations to reduce the risk of integration issues. - -- **Compliance and regulatory requirements**: Some industries require specific validation, auditing, or rollback capabilities that will influence your migration approach. - -These factors, along with your specific business requirements and constraints, will help determine which options you choose for each migration variable. It's recommended to document your decisions and the reasoning behind them as part of your migration plan. +These above factors are only a subset of all of what you'll want to consider in the decision-making about your CockroachDB migration, along with your specific business requirements and technical constraints. It's recommended that you document these decisions and the reasoning behind them as part of your [migration plan](). ## See also diff --git a/src/current/molt/migration-overview.md b/src/current/molt/migration-overview.md index 07d901d9df5..748f725a602 100644 --- a/src/current/molt/migration-overview.md +++ b/src/current/molt/migration-overview.md @@ -33,10 +33,10 @@ A migration to CockroachDB generally follows this sequence: 1. **Assess and discover**: Inventory the source database, flag unsupported features, make a migration plan. 1. **Prepare the environment**: Configure networking, users and permissions, bucket locations, replication settings, and more. 1. **Convert the source schema**: Generate CockroachDB-compatible [DDL]({% link {{ site.current_cloud_version }}/sql-statements.md %}#data-definition-statements). Apply the converted schema to the target database. Drop constraints and indexes to facilitate data load. -1. **Stop application traffic**: Limit user read/write traffic to the source database. _This begins application downtime._ 1. **Load data into CockroachDB**: Bulk load the source data into the CockroachDB cluster. -1. **_(Optional)_ Replicate ongoing changes**: Keep CockroachDB in sync with the source. This may be necessary for migrations that minimize downtime. 1. **Finalize target schema**: Recreate indexes or constraints on CockroachDB that you previously dropped to facilitate data load. +1. **_(Optional)_ Replicate ongoing changes**: Keep CockroachDB in sync with the source. This may be necessary for migrations that minimize downtime. +1. **Stop application traffic**: Limit user read/write traffic to the source database. _This begins application downtime._ 1. **Verify data consistency**: Confirm that the CockroachDB data is consistent with the source. 1. **_(Optional)_ Enable failback**: Replicate data from the target back to the source, enabling a reversion to the source database in the event of migration failure. 1. **Cut over application traffic**: Resume normal application use, with the CockroachDB cluster as the target database. _This ends application downtime._ @@ -141,45 +141,41 @@ MOLT supports various migration flows using [MOLT Fetch]({% link molt/molt-fetch | [Resume replication]({% link molt/migrate-resume-replication.md %}) | MOLT Replicator | Resume replication from a checkpoint after interruption. | Resuming interrupted migrations, post-load sync | | [Failback]({% link molt/migrate-failback.md %}) | MOLT Replicator | Replicate changes from CockroachDB back to the source database. | [Rollback]({% link molt/migrate-failback.md %}) scenarios | --> -## Migration considerations +## Migration variables You must decide how you want your migration to handle each of the following variables. These decisions will depend on your specific business and technical considerations. The MOLT toolkit supports any set of decisions made for the [supported source databases](#molt-tools). -### Bulk vs. phased migration - -For smaller data stores, it's possible to migrate all of your data onto the target cluster at once. For larger data stores, it's recommended that you do so in phases. This +### Migration granularity -Learn more about [phased migrations]({% link molt/migration-considerations-phases.md %}). +You may choose to migrate all of your data into a CockroachDB cluster at once. However, for larger data stores it's recommended that you migrate data in separate phases. This can help break the migration down into manageable slices, and it can help limit the effects of migration difficulties. ### Continuous replication -To minimize downtime during migration, use MOLT Fetch for initial data loading followed by MOLT Replicator for continuous replication. Instead of loading all data during a planned downtime window, you can run an initial load followed by continuous replication. Writes are paused only briefly to allow replication to drain before the final cutover. The duration of this pause depends on the volume of write traffic and the replication lag between the source and CockroachDB. Learn more about [continuous replication]({% link molt/migration-considerations-replication.md %}). +After data is migrated from the source into CockroachDB, you may choose to continue streaming changes to that source data from the source to the target. This is important for migrations that aim to minimize application downtime, as they may require the source database to continue receiving writes until application traffic is fully cut over to CockroachDB. -### Rollback plan +### Data transformation strategy -If the migration is interrupted or cutover must be aborted, MOLT Replicator provides safe recovery options: - -- Resume a previously interrupted replication stream. Refer to [Resume Replication]({% link molt/migrate-resume-replication.md %}). -- Use failback mode to reverse the migration, synchronizing changes from CockroachDB back to the original source. This ensures data consistency on the source so that you can retry the migration later. Refer to [Migration Failback]({% link molt/migrate-failback.md %}). +If there are discrepencies between the source and target schemas, the rules that determine necessary data transformations need to be defined. These transformations can be applied in the source database, in flight, or in the target database. ### Validation strategy -[] +There are several different ways of verifying that the data in the source and the target match one another. You must decide what validation checks you want to perform, and when in the migration process you want to perform them. + +### Rollback plan + +Until the migration is complete, migration failures may make you decide to roll back application traffic entirely to the source database. You may therefore need a way of keeping the source database up to date with new writes to the target. This is especially important for risk-averse migrations that aim to minimize downtime. ### Cutover plan -*Cutover* is the process of switching application traffic from the source database to CockroachDB. Once the source data is fully migrated to CockroachDB, switch application traffic to the new database to end downtime. +*Cutover* is the process of switching application traffic from the source database to CockroachDB. -MOLT enables [migrations with minimal downtime]({% link molt/migration-overview.md %}#migrations-with-minimal-downtime), using [MOLT Replicator]({% link molt/molt-replicator.md %}) for continuous replication of source changes to CockroachDB. +There are many different approaches to cutover. It can happen all at once, it can occur in multiple steps (in tandem with different [migration phases](#migration-granularity)). It's possible to cut over read and write traffic at different times. The possibilities are varied. -To safely cut over when using replication: +The decision of how to cut over application traffic is closely linked with many of the other choices above. -1. Stop application traffic on the source database. -1. Wait for the replication stream to drain. -1. When your [monitoring](#set-up-monitoring-and-alerting) indicates that replication is idle, use [MOLT Verify]({% link molt/molt-verify.md %}) to validate the CockroachDB data. -1. Start application traffic on CockroachDB. +--- -When you are ready to migrate, refer to [Migration flows]({% link molt/migration-overview.md %}#migration-flows) for a summary of migration types. +[Learn more about the different migration variables]({% link molt/migration-considerations.md %}), how you should consider the different options for each variable, and how to use the MOLT toolkit for each variable. ## See also diff --git a/src/current/molt/migration-strategy.md b/src/current/molt/migration-strategy.md index 780033568e5..769b7f1164a 100644 --- a/src/current/molt/migration-strategy.md +++ b/src/current/molt/migration-strategy.md @@ -31,20 +31,6 @@ Consider the following as you plan your migration: Create a document summarizing the migration's purpose, technical details, and team members involved. -## Approach to downtime - -It's important to fully [prepare the migration](#prepare-for-migration) in order to be certain that the migration can be completed successfully during the downtime window. - -- *Planned downtime* is made known to your users in advance. Once you have [prepared for the migration](#prepare-for-migration), you take the application offline, [conduct the migration]({% link molt/migration-overview.md %}), and bring the application back online on CockroachDB. To succeed, you should estimate the amount of downtime required to migrate your data, and ideally schedule the downtime outside of peak hours. Scheduling downtime is easiest if your application traffic is "periodic", meaning that it varies by the time of day, day of week, or day of month. - - Migrations with planned downtime are only recommended if you can complete the bulk data load (e.g., using the MOLT Fetch [`data-load` mode]({% link molt/molt-fetch.md %}#fetch-mode)) within the downtime window. Otherwise, you can [minimize downtime using continuous replication]({% link molt/migration-overview.md %}#migrations-with-minimal-downtime). - -- *Minimal downtime* impacts as few customers as possible, ideally without impacting their regular usage. If your application is intentionally offline at certain times (e.g., outside business hours), you can migrate the data without users noticing. Alternatively, if your application's functionality is not time-sensitive (e.g., it sends batched messages or emails), you can queue requests while the system is offline and process them after completing the migration to CockroachDB. - - MOLT enables [migrations with minimal downtime]({% link molt/migration-overview.md %}#migrations-with-minimal-downtime), using [MOLT Replicator]({% link molt/molt-replicator.md %}) for continuous replication of source changes to CockroachDB. - -- *Reduced functionality* takes some, but not all, application functionality offline. For example, you can disable writes but not reads while you migrate the application data, and queue data to be written after completing the migration. - ## Capacity planning To size the target CockroachDB cluster, consider your data volume and workload characteristics: From 3b21e54bbcfab83b396a833ff7938fb4a1be34b0 Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Fri, 21 Nov 2025 17:13:01 -0500 Subject: [PATCH 03/15] reverting molt-fetch to main --- src/current/molt/molt-fetch.md | 987 +++++++++++++++++++++++++++++++++ 1 file changed, 987 insertions(+) diff --git a/src/current/molt/molt-fetch.md b/src/current/molt/molt-fetch.md index 754d04b3c32..02052c16583 100644 --- a/src/current/molt/molt-fetch.md +++ b/src/current/molt/molt-fetch.md @@ -5,6 +5,993 @@ toc: true docs_area: migrate --- +MOLT Fetch moves data from a source database into CockroachDB as part of a [database migration]({% link molt/migration-overview.md %}). + +MOLT Fetch uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to move the source data to cloud storage (Google Cloud Storage, Amazon S3, or Azure Blob Storage), a local file server, or local memory. Once the data is exported, MOLT Fetch loads the data into a target CockroachDB database. For details, refer to [Migration phases](#migration-phases). + +## Terminology + +- *Shard*: A portion of a table's data exported concurrently during the data export phase. Tables are divided into shards to enable parallel processing. For details, refer to [Table sharding](#table-sharding). +- *Continuation token*: An identifier that marks the progress of a fetch task. Used to resume data loading from the point of interruption if a fetch task fails. For details, refer to [Fetch continuation](#fetch-continuation). +- *Intermediate files*: Temporary data files written to cloud storage or a local file server during the data export phase. These files are used to stage exported data before importing it into CockroachDB during the data import phase. For details, refer to [Data path](#data-path). + +## Prerequisites + +### Supported databases + +The following source databases are supported: + +- PostgreSQL 11-16 +- MySQL 5.7, 8.0 and later +- Oracle Database 19c (Enterprise Edition) and 21c (Express Edition) + +### Database configuration + +Ensure that the source and target schemas are identical, unless you enable automatic schema creation with the [`drop-on-target-and-recreate`](#target-table-handling) option. If you are creating the target schema manually, review the behaviors in [Mismatch handling](#mismatch-handling). + +{{site.data.alerts.callout_info}} +MOLT Fetch does not support migrating sequences. If your source database contains sequences, refer to the [guidance on indexing with sequential keys]({% link {{site.current_cloud_version}}/sql-faqs.md %}#how-do-i-generate-unique-slowly-increasing-sequential-numbers-in-cockroachdb). If a sequential key is necessary in your CockroachDB table, you must create it manually. After using MOLT Fetch to load the data onto the target, but before cutover, make sure to update each sequence's current value using [`setval()`]({% link {{site.current_cloud_version}}/functions-and-operators.md %}#sequence-functions) so that new inserts continue from the correct point. +{{site.data.alerts.end}} + +If you plan to use cloud storage for the data migration, follow the steps in [Cloud storage security](#cloud-storage-security). + +### User permissions + +The SQL user running MOLT Fetch requires specific privileges on both the source and target databases: + +| Database | Required Privileges | Details | +|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------| +| PostgreSQL source |
  • `CONNECT` on database.
  • `USAGE` on schema.
  • `SELECT` on tables to migrate.
| [Create PostgreSQL migration user]({% link molt/migrate-bulk-load.md %}#create-migration-user-on-source-database) | +| MySQL source |
  • `SELECT` on tables to migrate.
| [Create MySQL migration user]({% link molt/migrate-bulk-load.md %}?filters=mysql#create-migration-user-on-source-database) | +| Oracle source |
  • `CONNECT` and `CREATE SESSION`.
  • `SELECT` and `FLASHBACK` on tables to migrate.
  • `SELECT` on metadata views (`ALL_USERS`, `DBA_USERS`, `DBA_OBJECTS`, `DBA_SYNONYMS`, `DBA_TABLES`).
| [Create Oracle migration user]({% link molt/migrate-bulk-load.md %}?filters=oracle#create-migration-user-on-source-database) | +| CockroachDB target |
  • `ALL` on target database.
  • `CREATE` on schema.
  • `SELECT`, `INSERT`, `UPDATE`, `DELETE` on target tables.
  • For `IMPORT INTO`: `SELECT`, `INSERT`, `DROP` on target tables. Optionally `EXTERNALIOIMPLICITACCESS` for implicit cloud storage authentication.
  • For `COPY FROM`: `admin` role.
| [Create CockroachDB user]({% link molt/migrate-bulk-load.md %}#create-the-sql-user) | + +## Installation + +{% include molt/molt-install.md %} + +### Docker usage + +{% include molt/molt-docker.md %} + +## Migration phases + +MOLT Fetch operates in distinct phases to move data from source databases to CockroachDB. For details on available modes, refer to [Fetch mode](#fetch-mode). + +### Data export phase + +MOLT Fetch connects to the source database and exports table data to intermediate storage. Data is written to [cloud storage](#bucket-path) (Amazon S3, Google Cloud Storage, Azure Blob Storage), a [local file server](#local-path), or [directly to CockroachDB memory](#direct-copy). Multiple tables and table shards can be exported simultaneously using [`--table-concurrency`](#global-flags) and [`--export-concurrency`](#global-flags), with large tables divided into shards for parallel processing. For details, refer to: + +- [Fetch mode](#fetch-mode) +- [Table sharding](#table-sharding) + +### Data import phase + +MOLT Fetch loads the exported data into the target CockroachDB database. The process uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) (faster, tables offline during import) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) (slower, tables remain queryable) to move data. Data files are imported in configurable batches using [`--import-batch-size`](#global-flags), and target tables can be automatically created, truncated, or left unchanged based on [`--table-handling`](#global-flags) settings. For details, refer to: + +- [Data movement](#data-load-mode) +- [Target table handling](#target-table-handling) + +## Commands + +| Command | Usage | +|---------|---------------------------------------------------------------------------------------------------| +| `fetch` | Start the fetch task. This loads data from a source database to a target CockroachDB database. | + +### Subcommands + +| Command | Usage | +|--------------|----------------------------------------------------------------------| +| `tokens list` | List active [continuation tokens](#list-active-continuation-tokens). | + +## Flags + +### Global flags + +| Flag | Description | +|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--source` | (Required) Connection string used to connect to the Oracle PDB (in a CDB/PDB architecture) or to a standalone database (non‑CDB). For details, refer to [Source and target databases](#source-and-target-databases). | +| `--source-cdb` | Connection string for the Oracle container database (CDB) when using a multitenant (CDB/PDB) architecture. Omit this flag on a non‑multitenant Oracle database. For details, refer to [Source and target databases](#source-and-target-databases). | +| `--target` | (Required) Connection string for the target database. For details, refer to [Source and target databases](#source-and-target-databases). | +| `--allow-tls-mode-disable` | Allow insecure connections to databases. Secure SSL/TLS connections should be used by default. This should be enabled **only** if secure SSL/TLS connections to the source or target database are not possible. | +| `--assume-role` | Service account to use for assume role authentication. `--use-implicit-auth` must be included. For example, `--assume-role='user-test@cluster-ephemeral.iam.gserviceaccount.com' --use-implicit-auth`. For details, refer to [Cloud Storage Authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}). | +| `--bucket-path` | The path within the [cloud storage](#bucket-path) bucket where intermediate files are written (e.g., `'s3://bucket/path'` or `'gs://bucket/path'`). Only the URL path is used; query parameters (e.g., credentials) are ignored. To pass in query parameters, use the appropriate flags: `--assume-role`, `--import-region`, `--use-implicit-auth`. | +| `--case-sensitive` | Toggle case sensitivity when comparing table and column names on the source and target. To disable case sensitivity, set `--case-sensitive=false`. If `=` is **not** included (e.g., `--case-sensitive false`), the flag is interpreted as `--case-sensitive` (i.e., `--case-sensitive=true`).

**Default:** `false` | +| `--cleanup` | Whether to delete intermediate files after moving data using [cloud or local storage](#data-path). **Note:** Cleanup does not occur on [continuation](#fetch-continuation). | +| `--compression` | Compression method for data when using [`IMPORT INTO`](#data-load-mode) (`gzip`/`none`).

**Default:** `gzip` | +| `--continuation-file-name` | Restart fetch at the specified filename if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation](#fetch-continuation). | +| `--continuation-token` | Restart fetch at a specific table, using the specified continuation token, if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation](#fetch-continuation). | +| `--crdb-pts-duration` | The duration for which each timestamp used in data export from a CockroachDB source is protected from garbage collection. This ensures that the data snapshot remains consistent. For example, if set to `24h`, each timestamp is protected for 24 hours from the initiation of the export job. This duration is extended at regular intervals specified in `--crdb-pts-refresh-interval`.

**Default:** `24h0m0s` | +| `--crdb-pts-refresh-interval` | The frequency at which the protected timestamp's validity is extended. This interval maintains protection of the data snapshot until data export from a CockroachDB source is completed. For example, if set to `10m`, the protected timestamp's expiration will be extended by the duration specified in `--crdb-pts-duration` (e.g., `24h`) every 10 minutes while export is not complete.

**Default:** `10m0s` | +| `--direct-copy` | Enables [direct copy](#direct-copy), which copies data directly from source to target without using an intermediate store. | +| `--export-concurrency` | Number of shards to export at a time per table, each on a dedicated thread. This controls how many shards are created for each individual table during the [data export phase](#data-export-phase) and is distinct from `--table-concurrency`, which controls how many tables are processed simultaneously. The total number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`. Tables can be sharded with a range-based or stats-based mechanism. For details, refer to [Table sharding](#table-sharding).

**Default:** `4` | +| `--export-retry-max-attempts` | Maximum number of retry attempts for source export queries when connection failures occur. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `3` | +| `--export-retry-max-duration` | Maximum total duration for retrying source export queries. If `0`, no time limit is enforced. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `5m0s` | +| `--filter-path` | Path to a JSON file defining row-level filters for the [data import phase](#data-import-phase). Refer to [Selective data movement](#selective-data-movement). | +| `--fetch-id` | Restart fetch task corresponding to the specified ID. If `--continuation-file-name` or `--continuation-token` are not specified, fetch restarts for all failed tables. | +| `--flush-rows` | Number of rows before the source data is flushed to intermediate files. **Note:** If `--flush-size` is also specified, the fetch behavior is based on the flag whose criterion is met first. | +| `--flush-size` | Size (in bytes) before the source data is flushed to intermediate files. **Note:** If `--flush-rows` is also specified, the fetch behavior is based on the flag whose criterion is met first. | +| `--ignore-replication-check` | Skip querying for replication checkpoints such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle. This option is intended for use during bulk load migrations or when doing a one-time data export from a read replica. | +| `--import-batch-size` | The number of files to be imported at a time to the target database during the [data import phase](#data-import-phase). This applies only when using [`IMPORT INTO`](#data-load-mode) for data movement. **Note:** Increasing this value can improve the performance of full-scan queries on the target database shortly after fetch completes, but very high values are not recommended. If any individual file in the import batch fails, you must [retry](#fetch-continuation) the entire batch.

**Default:** `1000` | +| `--import-region` | The region of the [cloud storage](#bucket-path) bucket. This applies only to [Amazon S3 buckets](#bucket-path). Set this flag only if you need to specify an `AWS_REGION` explicitly when using [`IMPORT INTO`](#data-load-mode) for data movement. For example, `--import-region=ap-south-1`. | +| `--local-path` | The path within the [local file server](#local-path) where intermediate files are written (e.g., `data/migration/cockroach`). `--local-path-listen-addr` must be specified. | +| `--local-path-crdb-access-addr` | Address of a [local file server](#local-path) that is **publicly accessible**. This flag is only necessary if CockroachDB cannot reach the local address specified with `--local-path-listen-addr` (e.g., when moving data to a CockroachDB {{ site.data.products.cloud }} deployment). `--local-path` and `--local-path-listen-addr` must be specified.

**Default:** Value of `--local-path-listen-addr`. | +| `--local-path-listen-addr` | Write intermediate files to a [local file server](#local-path) at the specified address (e.g., `'localhost:3000'`). `--local-path` must be specified. | +| `--log-file` | Write messages to the specified log filename. If no filename is provided, messages write to `fetch-{datetime}.log`. If `"stdout"` is provided, messages write to `stdout`. | +| `--logging` | Level at which to log messages (`trace`/`debug`/`info`/`warn`/`error`/`fatal`/`panic`).

**Default:** `info` | +| `--metrics-listen-addr` | Address of the Prometheus metrics endpoint, which has the path `{address}/metrics`. For details on important metrics to monitor, refer to [Monitoring](#monitoring).

**Default:** `'127.0.0.1:3030'` | +| `--mode` | Configure the MOLT Fetch behavior: `data-load`, `export-only`, or `import-only`. For details, refer to [Fetch mode](#fetch-mode).

**Default:** `data-load` | +| `--non-interactive` | Run the fetch task without interactive prompts. This is recommended **only** when running `molt fetch` in an automated process (i.e., a job or continuous integration). | +| `--pprof-listen-addr` | Address of the pprof endpoint.

**Default:** `'127.0.0.1:3031'` | +| `--row-batch-size` | Number of rows per shard to export at a time. For details on sharding, refer to [Table sharding](#table-sharding). See also [Best practices](#best-practices).

**Default:** `100000` | +| `--schema-filter` | Move schemas that match a specified [regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | +| `--skip-pk-check` | Skip primary-key matching to allow data load when source or target tables have missing or mismatched primary keys. Disables sharding and bypasses `--export-concurrency` and `--row-batch-size` settings. Refer to [Skip primary key matching](#skip-primary-key-matching).

**Default:** `false` | +| `--table-concurrency` | Number of tables to export at a time. The number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`.

**Default:** `4` | +| `--table-exclusion-filter` | Exclude tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

This value **cannot** be set to `'.*'`, which would cause every table to be excluded.

**Default:** Empty string | +| `--table-filter` | Move tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | +| `--table-handling` | How tables are initialized on the target database (`none`/`drop-on-target-and-recreate`/`truncate-if-exists`). For details, see [Target table handling](#target-table-handling).

**Default:** `none` | +| `--transformations-file` | Path to a JSON file that defines transformations to be performed on the target schema during the fetch task. Refer to [Transformations](#transformations). | +| `--type-map-file` | Path to a JSON file that contains explicit type mappings for automatic schema creation, when enabled with `--table-handling drop-on-target-and-recreate`. For details on the JSON format and valid type mappings, see [type mapping](#type-mapping). | +| `--use-console-writer` | Use the console writer, which has cleaner log output but introduces more latency.

**Default:** `false` (log as structured JSON) | +| `--use-copy` | Use [`COPY FROM`](#data-load-mode) to move data. This makes tables queryable during data load, but is slower than using `IMPORT INTO`. For details, refer to [Data movement](#data-load-mode). | +| `--use-implicit-auth` | Use [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}) for [cloud storage](#bucket-path) URIs. | +| `--use-stats-based-sharding` | Enable statistics-based sharding for PostgreSQL sources. This allows sharding of tables with primary keys of any data type and can create more evenly distributed shards compared to the default numerical range sharding. Requires PostgreSQL 11+ and access to `pg_stats`. For details, refer to [Table sharding](#table-sharding). | + + +### `tokens list` flags + +| Flag | Description | +|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------| +| `--conn-string` | (Required) Connection string for the target database. For details, see [List active continuation tokens](#list-active-continuation-tokens). | +| `-n`, `--num-results` | Number of results to return. | + + +## Usage + +The following sections describe how to use the `molt fetch` [flags](#flags). + +### Source and target databases + +{{site.data.alerts.callout_success}} +Follow the recommendations in [Connection security](#connection-security). +{{site.data.alerts.end}} + +`--source` specifies the connection string of the source database. + +PostgreSQL or CockroachDB connection string: + +{% include_cached copy-clipboard.html %} +~~~ +--source 'postgresql://{username}:{password}@{host}:{port}/{database}' +~~~ + +MySQL connection string: + +{% include_cached copy-clipboard.html %} +~~~ +--source 'mysql://{username}:{password}@{protocol}({host}:{port})/{database}' +~~~ + +Oracle connection string: + +{% include_cached copy-clipboard.html %} +~~~ +--source 'oracle://{username}:{password}@{host}:{port}/{service_name}' +~~~ + +For Oracle Multitenant databases, `--source-cdb` specifies the container database (CDB) connection. `--source` specifies the pluggable database (PDB): + +{% include_cached copy-clipboard.html %} +~~~ +--source 'oracle://{username}:{password}@{host}:{port}/{pdb_service_name}' +--source-cdb 'oracle://{username}:{password}@{host}:{port}/{cdb_service_name}' +~~~ + +`--target` specifies the [CockroachDB connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url): + +{% include_cached copy-clipboard.html %} +~~~ +--target 'postgresql://{username}:{password}@{host}:{port}/{database}' +~~~ + +### Fetch mode + +`--mode` specifies the MOLT Fetch behavior. + +`data-load` (default) instructs MOLT Fetch to load the source data into CockroachDB: + +{% include_cached copy-clipboard.html %} +~~~ +--mode data-load +~~~ + +`export-only` instructs MOLT Fetch to export the source data to the specified [cloud storage](#bucket-path) or [local file server](#local-path). It does not load the data into CockroachDB: + +{% include_cached copy-clipboard.html %} +~~~ +--mode export-only +~~~ + +`import-only` instructs MOLT Fetch to load the source data in the specified [cloud storage](#bucket-path) or [local file server](#local-path) into the CockroachDB target: + +{% include_cached copy-clipboard.html %} +~~~ +--mode import-only +~~~ + +### Data load mode + +MOLT Fetch can use either [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to load data into CockroachDB. + +By default, MOLT Fetch uses `IMPORT INTO`: + +- `IMPORT INTO` achieves the highest throughput, but [requires taking the CockroachDB tables **offline**]({% link {{site.current_cloud_version}}/import-into.md %}#considerations) to achieve its import speed. Tables are taken back online once an [import job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs) completes successfully. See [Best practices](#best-practices). +- `IMPORT INTO` supports compression using the `--compression` flag, which reduces the amount of storage used. + +`--use-copy` configures MOLT Fetch to use `COPY FROM`: + +- `COPY FROM` enables your tables to remain online and accessible. However, it is slower than using [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}). +- `COPY FROM` does not support compression. + +{{site.data.alerts.callout_info}} +`COPY FROM` is also used for [direct copy](#direct-copy). +{{site.data.alerts.end}} + +### Table sharding + +During the [data export phase](#data-export-phase), MOLT Fetch can divide large tables into multiple shards for concurrent export. + +To control the number of shards created per table, use the `--export-concurrency` flag. For example: + +{% include_cached copy-clipboard.html %} +~~~ +--export-concurrency=4 +~~~ + +{{site.data.alerts.callout_success}} +For performance considerations with concurrency settings, refer to [Best practices](#best-practices). +{{site.data.alerts.end}} + +Two sharding mechanisms are available: + +- **Range-based sharding (default):** Tables are divided based on numerical ranges found in primary key values. Only tables with [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) primary keys can use range-based sharding. Tables with other primary key data types export as a single shard. + +- **Stats-based sharding (PostgreSQL only):** Enable with [`--use-stats-based-sharding`](#global-flags) for PostgreSQL 11+ sources. Tables are divided by analyzing the [`pg_stats`](https://www.postgresql.org/docs/current/view-pg-stats.htm) view to create more evenly distributed shards, up to a maximum of 200 shards. Primary keys of any data type are supported. + +Stats-based sharding requires that the user has `SELECT` permissions on source tables and on each table's `pg_stats` view. The latter permission is automatically granted to users that can read the table. + +To optimize stats-based sharding, run [`ANALYZE`](https://www.postgresql.org/docs/current/sql-analyze.html) on source tables before migration to ensure that table statistics are up-to-date and shards are evenly distributed. This requires `MAINTAIN` or `OWNER` permissions on the table. You can analyze specific primary key columns or the entire table. For example: + +{% include_cached copy-clipboard.html %} +~~~ sql +ANALYZE table_name(PK1, PK2, PK3); +~~~ + +{% include_cached copy-clipboard.html %} +~~~ sql +ANALYZE table_name; +~~~ + +Large tables may take time to analyze, but `ANALYZE` can run in the background. You can run `ANALYZE` with `MAINTAIN` or `OWNER` privileges during migration preparation, then perform the actual migration with standard `SELECT` privileges. + +{{site.data.alerts.callout_info}} +Migration without running `ANALYZE` will still work, but shard distribution may be less even. +{{site.data.alerts.end}} + +When using `--use-stats-based-sharding`, monitor the log output for each table you want to migrate. + +If stats-based sharding is successful on a table, MOLT logs the following `INFO` message: + +~~~ +Stats based sharding enabled for table {table_name} +~~~ + +If stats-based sharding fails on a table, MOLT logs the following `WARNING` message and defaults to range-based sharding: + +~~~ +Warning: failed to shard table {table_name} using stats based sharding: {reason_for_failure}, falling back to non stats based sharding +~~~ + +The number of shards is dependent on the number of distinct values in the first primary key column of the table to be migrated. If this is different from the number of shards requested with `--export-concurrency`, MOLT logs the following `WARNING` and continues with the migration: + +~~~ +number of shards formed: {num_shards_formed} is not equal to number of shards requested: {num_shards_requested} for table {table_name} +~~~ + +Because stats-based sharding analyzes the entire table, running `--use-stats-based-sharding` with [`--filter-path`](#global-flags) (refer to [Selective data movement](#selective-data-movement)) will cause imbalanced shards to form. + +### Data path + +MOLT Fetch can move the source data to CockroachDB via [cloud storage](#bucket-path), a [local file server](#local-path), or [directly](#direct-copy) without an intermediate store. + +#### Bucket path + +{{site.data.alerts.callout_success}} +Only the path specified in `--bucket-path` is used. Query parameters, such as credentials, are ignored. To authenticate cloud storage, follow the steps in [Secure cloud storage](#cloud-storage-security). +{{site.data.alerts.end}} + +`--bucket-path` instructs MOLT Fetch to write intermediate files to a path within [Google Cloud Storage](https://cloud.google.com/storage/docs/buckets), [Amazon S3](https://aws.amazon.com/s3/), or [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) to which you have the necessary permissions. Use additional [flags](#global-flags), shown in the following examples, to specify authentication or region parameters as required for bucket access. + +Connect to a Google Cloud Storage bucket with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#google-cloud-storage-implicit) and [assume role]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#set-up-google-cloud-storage-assume-role): + +{% include_cached copy-clipboard.html %} +~~~ +--bucket-path 'gs://migration/data/cockroach' +--assume-role 'user-test@cluster-ephemeral.iam.gserviceaccount.com' +--use-implicit-auth +~~~ + +Connect to an Amazon S3 bucket and explicitly specify the `ap_south-1` region: + +{% include_cached copy-clipboard.html %} +~~~ +--bucket-path 's3://migration/data/cockroach' +--import-region 'ap-south-1' +~~~ + +{{site.data.alerts.callout_info}} +When `--import-region` is set, `IMPORT INTO` must be used for [data movement](#data-load-mode). +{{site.data.alerts.end}} + +Connect to an Azure Blob Storage container with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}?filters=azure#azure-blob-storage-implicit-authentication): + +{% include_cached copy-clipboard.html %} +~~~ +--bucket-path 'azure-blob://migration/data/cockroach' +--use-implicit-auth +~~~ + +#### Local path + +`--local-path` instructs MOLT Fetch to write intermediate files to a path within a [local file server]({% link {{site.current_cloud_version}}/use-a-local-file-server.md %}). `local-path-listen-addr` specifies the address of the local file server. For example: + +{% include_cached copy-clipboard.html %} +~~~ +--local-path /migration/data/cockroach +--local-path-listen-addr 'localhost:3000' +~~~ + +In some cases, CockroachDB will not be able to use the local address specified by `--local-path-listen-addr`. This will depend on where CockroachDB is deployed, the runtime OS, and the source dialect. + +For example, if you are migrating to CockroachDB {{ site.data.products.cloud }}, such that the {{ site.data.products.cloud }} cluster is in a different physical location than the machine running `molt fetch`, then CockroachDB cannot reach an address such as `localhost:3000`. In these situations, use `--local-path-crdb-access-addr` to specify an address for the local file server that is **publicly accessible**. For example: + +{% include_cached copy-clipboard.html %} +~~~ +--local-path /migration/data/cockroach +--local-path-listen-addr 'localhost:3000' +--local-path-crdb-access-addr '44.55.66.77:3000' +~~~ + +{{site.data.alerts.callout_success}} +[Cloud storage](#bucket-path) is often preferable to a local file server, which can require considerable disk space. +{{site.data.alerts.end}} + +#### Direct copy + +`--direct-copy` specifies that MOLT Fetch should use `COPY FROM` to move the source data directly to CockroachDB without an intermediate store: + +- Because the data is held in memory, the machine must have sufficient RAM for the data currently in flight: + + ~~~ + average size of each row * --row-batch-size * --export-concurrency * --table-concurrency + ~~~ + +- Direct copy does not support compression or [continuation](#fetch-continuation). +- The [`--use-copy`](#data-load-mode) flag is redundant with `--direct-copy`. + +### Schema and table selection + +By default, MOLT Fetch moves all data from the [`--source`](#source-and-target-databases) database to CockroachDB. Use the following flags to move a subset of data. + +`--schema-filter` specifies a range of schema objects to move to CockroachDB, formatted as a POSIX regex string. For example, to move every table in the source database's `public` schema: + +{% include_cached copy-clipboard.html %} +~~~ +--schema-filter 'public' +~~~ + +`--table-filter` and `--table-exclusion-filter` specify tables to include and exclude from the migration, respectively, formatted as POSIX regex strings. For example, to move every source table that has "user" in the table name and exclude every source table that has "temp" in the table name: + +{% include_cached copy-clipboard.html %} +~~~ +--table-filter '.*user.*' --table-exclusion-filter '.*temp.*' +~~~ + +### Selective data movement + +Use `--filter-path` to specify the path to a JSON file that defines row-level filtering for data load. This enables you to move a subset of data in a table, rather than all data in the table. To apply row-level filters during replication, use [MOLT Replicator]({% link molt/molt-replicator.md %}) with userscripts. + +{% include_cached copy-clipboard.html %} +~~~ +--filter-path 'data-filter.json' +~~~ + +The JSON file should contain one or more entries in `filters`, each with a `resource_specifier` (`schema` and `table`) and a SQL expression `expr`. For example, the following example exports only rows from `public.t1` where `v > 100`: + +~~~ json +{ + "filters": [ + { + "resource_specifier": { + "schema": "public", + "table": "t1" + }, + "expr": "v > 100" + } + ] +} +~~~ + +`expr` is case-sensitive and must be valid in your source dialect. For example, when using Oracle as the source, quote all identifiers and escape embedded quotes: + +~~~ json +{ + "filters": [ + { + "resource_specifier": { + "schema": "C##FETCHORACLEFILTERTEST", + "table": "FILTERTBL" + }, + "expr": "ABS(\"X\") > 10 AND CEIL(\"X\") < 100 AND FLOOR(\"X\") > 0 AND ROUND(\"X\", 2) < 100.00 AND TRUNC(\"X\", 0) > 0 AND MOD(\"X\", 2) = 0 AND FLOOR(\"X\" / 3) > 1" + } + ] +} +~~~ + +{{site.data.alerts.callout_info}} +If the expression references columns that are not indexed, MOLT Fetch will emit a warning like: `filter expression ‘v > 100' contains column ‘v' which is not indexed. This may lead to performance issues.` +{{site.data.alerts.end}} + +{% comment %} +#### `--filter-path` userscript for replication + +To use `--filter-path` with replication, create and save a TypeScript userscript (e.g., `filter-script.ts`). The following script ensures that only rows where `v > 100` are replicated to `defaultdb.public.t1`: + +{% include_cached copy-clipboard.html %} +~~~ ts +import * as api from "replicator@v1"; +function disp(doc, meta) { + if (Number(doc.v) > 100) { + return { "defaultdb.public.t1" : [ doc ] }; + } +} +// Always put target schema. +api.configureSource("defaultdb.public", { + deletesTo: disp, + dispatch: disp, +}); +~~~ + +Apply the userscript with the `--userscript` replication flag: + +{% include_cached copy-clipboard.html %} +~~~ +--userscript 'filter-script.ts' +~~~ +{% endcomment %} + +### Target table handling + +`--table-handling` defines how MOLT Fetch loads data on the CockroachDB tables that [match the selection](#schema-and-table-selection). + +To load the data without changing the existing data in the tables, use `none`: + +{% include_cached copy-clipboard.html %} +~~~ +--table-handling none +~~~ + +To [truncate]({% link {{site.current_cloud_version}}/truncate.md %}) tables before loading the data, use `truncate-if-exists`: + +{% include_cached copy-clipboard.html %} +~~~ +--table-handling truncate-if-exists +~~~ + +To drop existing tables and create new tables before loading the data, use `drop-on-target-and-recreate`: + +{% include_cached copy-clipboard.html %} +~~~ +--table-handling drop-on-target-and-recreate +~~~ + +When using the `drop-on-target-and-recreate` option, MOLT Fetch creates a new CockroachDB table to load the source data if one does not already exist. To guide the automatic schema creation, you can [explicitly map source types to CockroachDB types](#type-mapping). `drop-on-target-and-recreate` does **not** create indexes or constraints other than [`PRIMARY KEY`]({% link {{site.current_cloud_version}}/primary-key.md %}) and [`NOT NULL`]({% link {{site.current_cloud_version}}/not-null.md %}). + +#### Mismatch handling + +If either [`none`](#target-table-handling) or [`truncate-if-exists`](#target-table-handling) is set, `molt fetch` loads data into the existing tables on the target CockroachDB database. If the target schema mismatches the source schema, `molt fetch` will exit early in certain cases, and will need to be re-run from the beginning. For details, refer to [Fetch exits early due to mismatches](#fetch-exits-early-due-to-mismatches). + +{{site.data.alerts.callout_info}} +This does not apply when [`drop-on-target-and-recreate`](#target-table-handling) is specified, since this option automatically creates a compatible CockroachDB schema. +{{site.data.alerts.end}} + +#### Skip primary key matching + +`--skip-pk-check` removes the [requirement that source and target tables share matching primary keys](#fetch-exits-early-due-to-mismatches) for data load. When this flag is set: + +- The data load proceeds even if the source or target table lacks a primary key, or if their primary key columns do not match. +- [Table sharding](#table-sharding) is disabled. Each table is exported in a single batch within one shard, bypassing `--export-concurrency` and `--row-batch-size`. As a result, memory usage and execution time may increase due to full table scans. +- If the source table contains duplicate rows but the target has [`PRIMARY KEY`]({% link {{ site.current_cloud_version }}/primary-key.md %}) or [`UNIQUE`]({% link {{ site.current_cloud_version }}/unique.md %}) constraints, duplicate rows are deduplicated during import. + +When `--skip-pk-check` is set, all tables are treated as if they lack a primary key, and are thus exported in a single unsharded batch. To avoid performance issues, use this flag with `--table-filter` to target only tables **without** a primary key. + +For example: + +{% include_cached copy-clipboard.html %} +~~~ shell +molt fetch \ + --mode data-load \ + --table-filter 'nopktbl' \ + --skip-pk-check +~~~ + +Example log output when `--skip-pk-check` is enabled: + +~~~json +{"level":"info","message":"sharding is skipped for table public.nopktbl - flag skip-pk-check is specified and thus no PK for source table is specified"} +~~~ + +#### Type mapping + +If [`drop-on-target-and-recreate`](#target-table-handling) is set, MOLT Fetch automatically creates a CockroachDB schema that is compatible with the source data. The column types are determined as follows: + +- PostgreSQL types are mapped to existing CockroachDB [types]({% link {{site.current_cloud_version}}/data-types.md %}) that have the same [`OID`]({% link {{site.current_cloud_version}}/oid.md %}). +- The following MySQL types are mapped to corresponding CockroachDB types: + + | MySQL type | CockroachDB type | Notes | + |-----------------------------------------------------|-------------------------------------------------------------------------------------------|--------------------------------------------------------------| + | `CHAR`, `CHARACTER`, `VARCHAR`, `NCHAR`, `NVARCHAR` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | + | `TINYTEXT`, `TEXT`, `MEDIUMTEXT`, `LONGTEXT` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | + | `GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | + | `LINESTRING` | [`LINESTRING`]({% link {{site.current_cloud_version}}/linestring.md %}) | Spatial type (PostGIS-style) | + | `POINT` | [`POINT`]({% link {{site.current_cloud_version}}/point.md %}) | Spatial type (PostGIS-style) | + | `POLYGON` | [`POLYGON`]({% link {{site.current_cloud_version}}/polygon.md %}) | Spatial type (PostGIS-style) | + | `MULTIPOINT` | [`MULTIPOINT`]({% link {{site.current_cloud_version}}/multipoint.md %}) | Spatial type (PostGIS-style) | + | `MULTILINESTRING` | [`MULTILINESTRING`]({% link {{site.current_cloud_version}}/multilinestring.md %}) | Spatial type (PostGIS-style) | + | `MULTIPOLYGON` | [`MULTIPOLYGON`]({% link {{site.current_cloud_version}}/multipolygon.md %}) | Spatial type (PostGIS-style) | + | `GEOMETRYCOLLECTION`, `GEOMCOLLECTION` | [`GEOMETRYCOLLECTION`]({% link {{site.current_cloud_version}}/geometrycollection.md %}) | Spatial type (PostGIS-style) | + | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | + | `TINYINT`, `INT1` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | + | `BLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `SMALLINT`, `INT2` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | + | `MEDIUMINT`, `INT`, `INTEGER`, `INT4` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | + | `BIGINT`, `INT8` | [`INT`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | + | `FLOAT` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | + | `DOUBLE` | [`FLOAT`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | + | `DECIMAL`, `NUMERIC`, `REAL` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | + | `BINARY`, `VARBINARY` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `DATETIME` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time (no time zone) | + | `TIMESTAMP` | [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time with time zone | + | `TIME` | [`TIME`]({% link {{site.current_cloud_version}}/time.md %}) | Time of day (no date) | + | `BIT` | [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) | Variable-length bit array | + | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | + | `TINYBLOB`, `MEDIUMBLOB`, `LONGBLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `BOOL`, `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | + +- The following Oracle types are mapped to CockroachDB types: + + | Oracle type(s) | CockroachDB type | Notes | + |---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| + | `NCHAR`, `CHAR`, `CHARACTER` | [`CHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`CHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Fixed-length character; falls back to unbounded if length not specified | + | `VARCHAR`, `VARCHAR2`, `NVARCHAR2` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | + | `STRING` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | + | `SMALLINT` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | + | `INTEGER`, `INT`, `SIMPLE_INTEGER` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | + | `LONG` | [`INT8`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | + | `FLOAT`, `BINARY_FLOAT`, `REAL` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | + | `DOUBLE`, `BINARY_DOUBLE` | [`FLOAT8`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | + | `DEC`, `NUMBER`, `DECIMAL`, `NUMERIC` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %})(p, s) or [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | + | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | + | `BLOB`, `RAW`, `LONG RAW` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | + | `CLOB`, `NCLOB` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as large text | + | `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | + | `TIMESTAMP` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) or [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | If `WITH TIME ZONE` → `TIMESTAMPTZ`, else `TIMESTAMP` | + | `ROWID`, `UROWID` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as opaque identifier | + | `SDO_GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | + | `XMLTYPE` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Stored as text | + +- To override the default mappings for automatic schema creation, you can map source to target CockroachDB types explicitly. These are defined in the JSON file indicated by the `--type-map-file` flag. The allowable custom mappings are valid CockroachDB aliases, casts, and the following mappings specific to MOLT Fetch and [Verify]({% link molt/molt-verify.md %}): + + - [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) <> [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) + - [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) <> [`UUID`]({% link {{site.current_cloud_version}}/uuid.md %}) + - [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) <> [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) + - [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) + - [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) <> [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) + - [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) + - [`INET`]({% link {{site.current_cloud_version}}/inet.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) + +`--type-map-file` specifies the path to the JSON file containing the explicit type mappings. For example: + +{% include_cached copy-clipboard.html %} +~~~ +--type-map-file 'type-mappings.json' +~~~ + +The following JSON example defines two type mappings: + +~~~ json + [ + { + "table": "public.t1", + "column_type_map": [ + { + "column": "*", + "source_type": "int", + "crdb_type": "INT2" + }, + { + "column": "name", + "source_type": "varbit", + "crdb_type": "string" + } + ] + } +] +~~~ + +- `table` specifies the table that will use the custom type mappings in `column_type_map`. The value is written as `{schema}.{table}`. +- `column` specifies the column that will use the custom type mapping. If `*` is specified, then all columns in the `table` with the matching `source_type` are converted. +- `source_type` specifies the source type to be mapped. +- `crdb_type` specifies the target CockroachDB [type]({% link {{ site.current_cloud_version }}/data-types.md %}) to be mapped. + +### Transformations + +You can define transformation rules to be performed on the target schema during the fetch task. These can be used to: + +- Map [computed columns]({% link {{ site.current_cloud_version }}/computed-columns.md %}) to a target schema. +- Map [partitioned tables]({% link {{ site.current_cloud_version }}/partitioning.md %}) to a single target table. +- Rename tables on the target schema. + +Transformation rules are defined in the JSON file indicated by the `--transformations-file` flag. For example: + +{% include_cached copy-clipboard.html %} +~~~ +--transformations-file 'transformation-rules.json' +~~~ + +The following JSON example defines two transformation rules: + +~~~ json +{ + "transforms": [ + { + "id": 1, + "resource_specifier": { + "schema": ".*", + "table": ".*" + }, + "column_exclusion_opts": { + "add_computed_def": true, + "column": "^age$" + } + }, + { + "id": 2, + "resource_specifier": { + "schema": "public", + "table": "charges_part.*" + }, + "table_rename_opts": { + "value": "charges" + } + } + ] +} +~~~ + +- `resource_specifier` configures the following options for transformation rules: + - `schema` specifies the schemas to be affected by the transformation rule, formatted as a POSIX regex string. + - `table` specifies the tables to be affected by the transformation rule, formatted as a POSIX regex string. +- `column_exclusion_opts` configures the following options for column exclusions and computed columns: + - `column` specifies source columns to exclude from being mapped to regular columns on the target schema. It is formatted as a POSIX regex string. + - `add_computed_def`, when set to `true`, specifies that each matching `column` should be mapped to a [computed column]({% link {{ site.current_cloud_version }}/computed-columns.md %}) on the target schema. Instead of being moved from the source, the column data is generated on the target using [`ALTER TABLE ... ADD COLUMN`]({% link {{ site.current_cloud_version }}/alter-table.md %}#add-column) and the computed column definition from the source schema. This assumes that all matching columns are computed columns on the source. + {{site.data.alerts.callout_danger}} + Columns that match the `column` regex will **not** be moved to CockroachDB if `add_computed_def` is omitted or set to `false` (default), or if a matching column is a non-computed column. + {{site.data.alerts.end}} +- `table_rename_opts` configures the following option for table renaming: + - `value` specifies the table name to which the matching `resource_specifier` is mapped. If only one source table matches `resource_specifier`, it is renamed to `table_rename_opts.value` on the target. If more than one table matches `resource_specifier` (i.e., an n-to-1 mapping), the fetch task assumes that all matching tables are [partitioned tables]({% link {{ site.current_cloud_version }}/partitioning.md %}) with the same schema, and moves their data to a table named `table_rename_opts.value` on the target. Otherwise, the task will error. + + Additionally, in an n-to-1 mapping situation: + + - Specify [`--use-copy`](#data-load-mode) or [`--direct-copy`](#direct-copy) for data movement. This is because the data from the source tables is loaded concurrently into the target table. + - Create the target table schema manually, and do **not** use [`--table-handling drop-on-target-and-recreate`](#target-table-handling) for target table handling. + +The preceding JSON example therefore defines two rules: + +- Rule `1` maps all source `age` columns on the source database to [computed columns]({% link {{ site.current_cloud_version }}/computed-columns.md %}) on CockroachDB. This assumes that all matching `age` columns are defined as computed columns on the source. +- Rule `2` maps all table names with prefix `charges_part` from the source database to a single `charges` table on CockroachDB (i.e., an n-to-1 mapping). This assumes that all matching `charges_part.*` tables have the same schema. + +Each rule is applied in the order it is defined. If two rules overlap, the later rule will override the earlier rule. + +To verify that the logging shows that the computed columns are being created: + +When running `molt fetch`, set `--logging debug` and look for `ALTER TABLE ... ADD COLUMN` statements with the `STORED` or `VIRTUAL` keywords in the log output: + +~~~ json +{"level":"debug","time":"2024-07-22T12:01:51-04:00","message":"running: ALTER TABLE IF EXISTS public.computed ADD COLUMN computed_col INT8 NOT NULL AS ((col1 + col2)) STORED"} +~~~ + +After running `molt fetch`, issue a `SHOW CREATE TABLE` statement on CockroachDB: + +{% include_cached copy-clipboard.html %} +~~~ sql +SHOW CREATE TABLE computed; +~~~ + +~~~ + table_name | create_statement +-------------+------------------------------------------------------------------- + computed | CREATE TABLE public.computed ( + ... + | computed_col INT8 NOT NULL AS (col1 + col2) STORED + | ) +~~~ + +### Fetch continuation + +If MOLT Fetch fails while loading data into CockroachDB from intermediate files, it exits with an error message, fetch ID, and [continuation token](#list-active-continuation-tokens) for each table that failed to load on the target database. You can use this information to continue the task from the *continuation point* where it was interrupted. + +Continuation is only possible under the following conditions: + +- All data has been exported from the source database into intermediate files on [cloud](#bucket-path) or [local storage](#local-path). +- The *initial load* of source data into the target CockroachDB database is incomplete. + +{{site.data.alerts.callout_info}} +Only one fetch ID and set of continuation tokens, each token corresponding to a table, are active at any time. See [List active continuation tokens](#list-active-continuation-tokens). +{{site.data.alerts.end}} + +To retry all data starting from the continuation point, reissue the `molt fetch` command and include the `--fetch-id`. + +{% include_cached copy-clipboard.html %} +~~~ +--fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 +~~~ + +To retry a specific table that failed, include both `--fetch-id` and `--continuation-token`. The latter flag specifies a token string that corresponds to a specific table on the source database. A continuation token is written in the `molt fetch` output for each failed table. If the fetch task encounters a subsequent error, it generates a new token for each failed table. See [List active continuation tokens](#list-active-continuation-tokens). + +{{site.data.alerts.callout_info}} +This will retry only the table that corresponds to the continuation token. If the fetch task succeeds, there may still be source data that is not yet loaded into CockroachDB. +{{site.data.alerts.end}} + +{% include_cached copy-clipboard.html %} +~~~ +--fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 +--continuation-token 011762e5-6f70-43f8-8e15-58b4de10a007 +~~~ + +To retry all data starting from a specific file, include both `--fetch-id` and `--continuation-file-name`. The latter flag specifies the filename of an intermediate file in [cloud or local storage](#data-path). All filenames are prepended with `part_` and have the `.csv.gz` or `.csv` extension, depending on compression type (gzip by default). For example: + +{% include_cached copy-clipboard.html %} +~~~ +--fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 +--continuation-file-name part_00000003.csv.gz +~~~ + +{{site.data.alerts.callout_info}} +Continuation is not possible when using [direct copy](#direct-copy). +{{site.data.alerts.end}} + +#### List active continuation tokens + +To view all active continuation tokens, issue a `molt fetch tokens list` command along with `--conn-string`, which specifies the [connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url) for the target CockroachDB database. For example: + +{% include_cached copy-clipboard.html %} +~~~ shell +molt fetch tokens list \ +--conn-string 'postgres://root@localhost:26257/defaultdb?sslmode=verify-full' +~~~ + +~~~ ++--------------------------------------+--------------------------------------+------------------+----------------------+ +| ID | FETCH ID | TABLE NAME | FILE NAME | ++--------------------------------------+--------------------------------------+------------------+----------------------+ +| f6f0284c-d9c1-43c9-8fde-af609d0dbd82 | 66443597-5689-4df3-a7b9-9fc5e27180eb | public.employees | part_00000001.csv.gz | ++--------------------------------------+--------------------------------------+------------------+----------------------+ +Continuation Tokens. +~~~ + +### CDC cursor + +A change data capture (CDC) cursor is written to the output as `cdc_cursor` at the beginning and end of the fetch task. For example: + +~~~ json +{"level":"info","type":"summary","fetch_id":"735a4fe0-c478-4de7-a342-cfa9738783dc","num_tables":1,"tables":["public.employees"],"cdc_cursor":"b7f9e0fa-2753-1e1f-5d9b-2402ac810003:3-21","net_duration_ms":4879.890041,"net_duration":"000h 00m 04s","time":"2024-03-18T12:37:02-04:00","message":"fetch complete"} +~~~ + +Use the `cdc_cursor` value as the checkpoint for MySQL or Oracle replication with [MOLT Replicator]({% link molt/molt-replicator.md %}#replication-checkpoints). + +You can also use the `cdc_cursor` value with an external change data capture (CDC) tool to continuously replicate subsequent changes from the source database to CockroachDB. + +## Security + +Cockroach Labs strongly recommends the following security practices. + +### Connection security + +{% include molt/molt-secure-connection-strings.md %} + +{{site.data.alerts.callout_info}} +By default, insecure connections (i.e., `sslmode=disable` on PostgreSQL; `sslmode` not set on MySQL) are disallowed. When using an insecure connection, `molt fetch` returns an error. To override this check, you can enable the `--allow-tls-mode-disable` flag. Do this **only** when testing, or if a secure SSL/TLS connection to the source or target database is not possible. +{{site.data.alerts.end}} + +### Cloud storage security + +{% include molt/fetch-secure-cloud-storage.md %} + +## Common workflows + +### Bulk data load + +To perform a bulk data load migration from your source database to CockroachDB, run the `molt fetch` command with the required flags. + +Specify the source and target database connections. For connection string formats, refer to [Source and target databases](#source-and-target-databases): + +{% include_cached copy-clipboard.html %} +~~~ +--source $SOURCE +--target $TARGET +~~~ + +Specify how to move data to CockroachDB. Use [cloud storage](#bucket-path) for intermediate file storage: + +{% include_cached copy-clipboard.html %} +~~~ +--bucket-path 's3://bucket/path' +~~~ + +Alternatively, use a [local file server](#local-path) for intermediate storage: + +{% include_cached copy-clipboard.html %} +~~~ +--local-path /migration/data/cockroach +--local-path-listen-addr 'localhost:3000' +~~~ + +Alternatively, use [direct copy](#direct-copy) to move data directly without intermediate storage: + +{% include_cached copy-clipboard.html %} +~~~ +--direct-copy +~~~ + +Optionally, filter which schemas and tables to migrate. By default, all schemas and tables are migrated. For details, refer to [Schema and table selection](#schema-and-table-selection): + +{% include_cached copy-clipboard.html %} +~~~ +--schema-filter 'public' +--table-filter '.*user.*' +~~~ + +Specify how to handle target tables. By default, `--table-handling` is set to `none`, which loads data without changing existing data in the tables. For details, refer to [Target table handling](#target-table-handling): + +{% include_cached copy-clipboard.html %} +~~~ +--table-handling truncate-if-exists +~~~ + +When performing a bulk load without subsequent replication, use `--ignore-replication-check` to skip querying for replication checkpoints (such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle). This is appropriate when: + +- Performing a one-time data migration with no plan to replicate ongoing changes. +- Exporting data from a read replica where replication checkpoints are unavailable. + +{% include_cached copy-clipboard.html %} +~~~ +--ignore-replication-check +~~~ + +At minimum, the `molt fetch` command should include the source, target, data path, and `--ignore-replication-check` flags: + +{% include_cached copy-clipboard.html %} +~~~ shell +molt fetch \ +--source $SOURCE \ +--target $TARGET \ +--bucket-path 's3://bucket/path' \ +--ignore-replication-check +~~~ + +For detailed steps, refer to [Bulk load migration]({% link molt/migrate-bulk-load.md %}). + +### Load before replication + +To perform an initial data load before setting up ongoing replication with [MOLT Replicator]({% link molt/molt-replicator.md %}), run the `molt fetch` command without `--ignore-replication-check`. This captures replication checkpoints during the data load. + +The workflow is the same as [Bulk data load](#bulk-data-load), except: + +- Exclude `--ignore-replication-check`. MOLT Fetch will query and record replication checkpoints. +- After the data load completes, check the [CDC cursor](#cdc-cursor) in the output for the checkpoint value to use with MOLT Replicator. + +At minimum, the `molt fetch` command should include the source, target, and data path flags: + +{% include_cached copy-clipboard.html %} +~~~ shell +molt fetch \ +--source $SOURCE \ +--target $TARGET \ +--bucket-path 's3://bucket/path' +~~~ + +The output will include a `cdc_cursor` value at the end of the fetch task: + +~~~ json +{"level":"info","type":"summary","fetch_id":"735a4fe0-c478-4de7-a342-cfa9738783dc","num_tables":1,"tables":["public.employees"],"cdc_cursor":"b7f9e0fa-2753-1e1f-5d9b-2402ac810003:3-21","net_duration_ms":4879.890041,"net_duration":"000h 00m 04s","time":"2024-03-18T12:37:02-04:00","message":"fetch complete"} +~~~ + +Use this `cdc_cursor` value when starting MOLT Replicator to ensure replication begins from the correct position. For detailed steps, refer to [Load and replicate]({% link molt/migrate-load-replicate.md %}). + +## Monitoring + +### Metrics + +By default, MOLT Fetch exports [Prometheus](https://prometheus.io/) metrics at `127.0.0.1:3030/metrics`. You can configure this endpoint with the `--metrics-listen-addr` [flag](#global-flags). + +Cockroach Labs recommends monitoring the following metrics: + +| Metric Name | Description | +|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------| +| `molt_fetch_num_tables` | Number of tables that will be moved from the source. | +| `molt_fetch_num_task_errors` | Number of errors encountered by the fetch task. | +| `molt_fetch_overall_duration` | Duration (in seconds) of the fetch task. | +| `molt_fetch_rows_exported` | Number of rows that have been exported from a table. For example:
`molt_fetch_rows_exported{table="public.users"}` | +| `molt_fetch_rows_imported` | Number of rows that have been imported from a table. For example:
`molt_fetch_rows_imported{table="public.users"}` | +| `molt_fetch_table_export_duration_ms` | Duration (in milliseconds) of a table's export. For example:
`molt_fetch_table_export_duration_ms{table="public.users"}` | +| `molt_fetch_table_import_duration_ms` | Duration (in milliseconds) of a table's import. For example:
`molt_fetch_table_import_duration_ms{table="public.users"}` | + +You can also use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view the preceding metrics. + +## Best practices + +### Test and validate + +To verify that your connections and configuration work properly, run MOLT Fetch in a staging environment before migrating any data in production. Use a test or development environment that closely resembles production. + +### Configure the source database and connection + +- To prevent connections from terminating prematurely during the [data export phase](#data-export-phase), set the following to high values on the source database: + + - **Maximum allowed number of connections.** MOLT Fetch can export data across multiple connections. The number of connections it will create is the number of shards ([`--export-concurrency`](#global-flags)) multiplied by the number of tables ([`--table-concurrency`](#global-flags)) being exported concurrently. + + {{site.data.alerts.callout_info}} + With the default numerical range sharding, only tables with [primary key]({% link {{ site.current_cloud_version }}/primary-key.md %}) types of [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) can be sharded. PostgreSQL users can enable [`--use-stats-based-sharding`](#global-flags) to use statistics-based sharding for tables with primary keys of any data type. For details, refer to [Table sharding](#table-sharding). + {{site.data.alerts.end}} + + - **Maximum lifetime of a connection.** + +- If a PostgreSQL database is set as a [source](#source-and-target-databases), ensure that [`idle_in_transaction_session_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT) on PostgreSQL is either disabled or set to a value longer than the duration of the [data export phase](#data-export-phase). Otherwise, the connection will be prematurely terminated. To estimate the time needed to export the PostgreSQL tables, you can perform a dry run and sum the value of [`molt_fetch_table_export_duration_ms`](#monitoring) for all exported tables. + +### Optimize performance + +- {% include molt/molt-drop-constraints-indexes.md %} + +- For PostgreSQL sources using [`--use-stats-based-sharding`](#global-flags), run [`ANALYZE`]({% link {{ site.current_cloud_version }}/create-statistics.md %}) on source tables before migration to ensure optimal shard distribution. This is especially important for large tables where even distribution can significantly improve export performance. + +- To prevent memory outages during `READ COMMITTED` [data export](#data-export-phase) of tables with large rows, estimate the amount of memory used to export a table: + + ~~~ + --row-batch-size * --export-concurrency * average size of the table rows + ~~~ + + If you are exporting more than one table at a time (i.e., [`--table-concurrency`](#global-flags) is set higher than `1`), add the estimated memory usage for the tables with the largest row sizes. Ensure that you have sufficient memory to run `molt fetch`, and adjust `--row-batch-size` accordingly. For details on how concurrency and sharding interact, refer to [Table sharding](#table-sharding). + +- If a table in the source database is much larger than the other tables, [filter and export the largest table](#schema-and-table-selection) in its own `molt fetch` task. Repeat this for each of the largest tables. Then export the remaining tables in another task. + +- Ensure that the machine running MOLT Fetch is large enough to handle the amount of data being migrated. Fetch performance can sometimes be limited by available resources, but should always be making progress. To identify possible resource constraints, observe the `molt_fetch_rows_exported` [metric](#monitoring) for decreases in the number of rows being processed. You can use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view metrics. For details on optimizing export performance through sharding, refer to [Table sharding](#table-sharding). + +### Import and continuation handling + +- When using [`IMPORT INTO`](#data-load-mode) during the [data import phase](#data-import-phase) to load tables into CockroachDB, if the fetch task terminates before the import job completes, the hanging import job on the target database will keep the table offline. To make this table accessible again, [manually resume or cancel the job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs). Then resume `molt fetch` using [continuation](#fetch-continuation), or restart the task from the beginning. + +## Troubleshooting + +
+ + + +
+ +{% include molt/molt-troubleshooting-fetch.md %} + ## See also - [Migration Overview]({% link molt/migration-overview.md %}) From 91df8d5d3ff2ee7eb7310c0b6678f0b0d5a8b578 Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Fri, 21 Nov 2025 17:52:42 -0500 Subject: [PATCH 04/15] moved the splitting up of Fetch into a separate PR, fixed links for this PR --- .../v25.4/sidebar-data/migrate-new.json | 45 +------------------ 1 file changed, 2 insertions(+), 43 deletions(-) diff --git a/src/current/_includes/v25.4/sidebar-data/migrate-new.json b/src/current/_includes/v25.4/sidebar-data/migrate-new.json index 56535be6826..41e84edb91a 100644 --- a/src/current/_includes/v25.4/sidebar-data/migrate-new.json +++ b/src/current/_includes/v25.4/sidebar-data/migrate-new.json @@ -66,49 +66,8 @@ }, { "title": "Fetch", - "items": [ - { - "title": "Overview", - "urls": [ - "/molt/molt-fetch-overview.html" - ] - }, - { - "title": "Install MOLT Fetch", - "urls": [ - "/molt/molt-fetch-install.html" - ] - }, - { - "title": "Global Flags", - "urls": [ - "/molt/molt-fetch-flags.html" - ] - }, - { - "title": "Use MOLT Fetch", - "urls": [ - "/molt/molt-fetch-usage.html" - ] - }, - { - "title": "Monitoring", - "urls": [ - "/molt/molt-fetch-monitoring.html" - ] - }, - { - "title": "Best Practices", - "urls": [ - "/molt/molt-fetch-best-practices.html" - ] - }, - { - "title": "Troubleshooting", - "urls": [ - "/molt/molt-fetch-troubleshooting.html" - ] - } + "urls": [ + "/molt/molt-fetch.html" ] }, { From b5ec9c6c8755ed9439e1570e03b818488096daf6 Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Fri, 21 Nov 2025 17:53:00 -0500 Subject: [PATCH 05/15] moved the splitting up of Fetch into a separate PR, fixed links for this PR --- src/current/_includes/molt/molt-docker.md | 2 +- .../molt/molt-drop-constraints-indexes.md | 2 +- src/current/_includes/molt/molt-install.md | 4 +- src/current/molt/migrate-bulk-load.md | 4 +- src/current/molt/migrate-to-cockroachdb.md | 4 +- .../molt/migration-considerations-phases.md | 8 +- src/current/molt/migration-considerations.md | 18 +- src/current/molt/migration-overview.md | 5 +- src/current/molt/migration-strategy.md | 5 +- src/current/molt/molt-fetch-best-practices.md | 68 -- src/current/molt/molt-fetch-flags.md | 84 --- src/current/molt/molt-fetch-install.md | 49 -- src/current/molt/molt-fetch-monitoring.md | 30 - src/current/molt/molt-fetch-overview.md | 140 ---- .../molt/molt-fetch-troubleshooting.md | 20 - src/current/molt/molt-fetch-usage.md | 667 ------------------ 16 files changed, 24 insertions(+), 1086 deletions(-) delete mode 100644 src/current/molt/molt-fetch-best-practices.md delete mode 100644 src/current/molt/molt-fetch-flags.md delete mode 100644 src/current/molt/molt-fetch-install.md delete mode 100644 src/current/molt/molt-fetch-monitoring.md delete mode 100644 src/current/molt/molt-fetch-overview.md delete mode 100644 src/current/molt/molt-fetch-troubleshooting.md delete mode 100644 src/current/molt/molt-fetch-usage.md diff --git a/src/current/_includes/molt/molt-docker.md b/src/current/_includes/molt/molt-docker.md index 2c9133f5c65..0e02705974b 100644 --- a/src/current/_includes/molt/molt-docker.md +++ b/src/current/_includes/molt/molt-docker.md @@ -2,7 +2,7 @@ MOLT Fetch, Verify, and Replicator are likely to run more slowly in a Docker container than on a local machine. To improve performance, increase the memory or compute resources, or both, on your Docker container. -{% if page.name == "molt-fetch.md" or page.name == "molt-fetch-install.md" %} +{% if page.name == "molt-fetch.md" %} #### Authentication When using MOLT Fetch with [cloud storage](#bucket-path), it is necessary to specify volumes and environment variables, as described in the following sections for [Google Cloud Storage](#google-cloud-storage) and [Amazon S3](#amazon-s3). diff --git a/src/current/_includes/molt/molt-drop-constraints-indexes.md b/src/current/_includes/molt/molt-drop-constraints-indexes.md index 6f5a843591f..a6456d779fa 100644 --- a/src/current/_includes/molt/molt-drop-constraints-indexes.md +++ b/src/current/_includes/molt/molt-drop-constraints-indexes.md @@ -1,5 +1,5 @@ To optimize data load performance, drop all non-`PRIMARY KEY` [constraints]({% link {{ site.current_cloud_version }}/alter-table.md %}#drop-constraint) and [indexes]({% link {{site.current_cloud_version}}/drop-index.md %}) on the target CockroachDB database before migrating: -{% if page.name == "molt-fetch.md" or page.name == "molt-fetch-best-practices.md" %} +{% if page.name == "molt-fetch.md" %} - [`FOREIGN KEY`]({% link {{ site.current_cloud_version }}/foreign-key.md %}) - [`UNIQUE`]({% link {{ site.current_cloud_version }}/unique.md %}) - [Secondary indexes]({% link {{ site.current_cloud_version }}/schema-design-indexes.md %}) diff --git a/src/current/_includes/molt/molt-install.md b/src/current/_includes/molt/molt-install.md index 5caea9cd208..86b224ba26f 100644 --- a/src/current/_includes/molt/molt-install.md +++ b/src/current/_includes/molt/molt-install.md @@ -22,7 +22,7 @@ To display the current version of each binary, run `molt --version` and `replica For previous binaries, refer to the [MOLT version manifest](https://molt.cockroachdb.com/molt/cli/versions.html). {% if page.name != "molt.md" %}For release details, refer to the [MOLT changelog]({% link releases/molt.md %}).{% endif %} -{% if page.name == "molt-fetch.md" or page.name == "molt.md" or page.name == "molt-fetch-install" %} +{% if page.name == "molt-fetch.md" or page.name == "molt.md" %} {{site.data.alerts.callout_info}} MOLT Fetch is supported on Red Hat Enterprise Linux (RHEL) 9 and above. {{site.data.alerts.end}} @@ -55,7 +55,7 @@ docker pull cockroachdb/molt:oracle-latest ~~~ {% endif %} -{% if page.name != "molt-fetch.md" and page.name != "molt-fetch-install.md" %} +{% if page.name != "molt-fetch.md" %} #### MOLT Replicator [Docker images for MOLT Replicator](https://hub.docker.com/r/cockroachdb/replicator/tags) are also available as a standalone binary: diff --git a/src/current/molt/migrate-bulk-load.md b/src/current/molt/migrate-bulk-load.md index 5f90f8c0b50..d99123fef5e 100644 --- a/src/current/molt/migrate-bulk-load.md +++ b/src/current/molt/migrate-bulk-load.md @@ -21,7 +21,7 @@ Perform a one-time bulk load of source data into CockroachDB. Perform the bulk load of the source data. -1. Run the [MOLT Fetch]({% link molt/molt-fetch-overview.md %}) command to move the source data into CockroachDB. This example command passes the source and target connection strings [as environment variables](#secure-connections), writes [intermediate files](#intermediate-file-storage) to S3 storage, and uses the `truncate-if-exists` [table handling mode](#table-handling-mode) to truncate the target tables before loading data. It limits the migration to a single schema and filters for three specific tables. The [data load mode](#data-load-mode) defaults to `IMPORT INTO`. Include the `--ignore-replication-check` flag to skip replication checkpoint queries, which eliminates the need to configure the source database for logical replication. +1. Run the [MOLT Fetch]({% link molt/molt-fetch.md %}) command to move the source data into CockroachDB. This example command passes the source and target connection strings [as environment variables](#secure-connections), writes [intermediate files](#intermediate-file-storage) to S3 storage, and uses the `truncate-if-exists` [table handling mode](#table-handling-mode) to truncate the target tables before loading data. It limits the migration to a single schema and filters for three specific tables. The [data load mode](#data-load-mode) defaults to `IMPORT INTO`. Include the `--ignore-replication-check` flag to skip replication checkpoint queries, which eliminates the need to configure the source database for logical replication.
{% include_cached copy-clipboard.html %} @@ -91,6 +91,6 @@ Perform a cutover by resuming application traffic, now to CockroachDB. - [Migration Overview]({% link molt/migration-overview.md %}) - [Migration Strategy]({% link molt/migration-strategy.md %}) - [MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}) -- [MOLT Fetch]({% link molt/molt-fetch-overview.md %}) +- [MOLT Fetch]({% link molt/molt-fetch.md %}) - [MOLT Verify]({% link molt/molt-verify.md %}) - [Migration Failback]({% link molt/migrate-failback.md %}) \ No newline at end of file diff --git a/src/current/molt/migrate-to-cockroachdb.md b/src/current/molt/migrate-to-cockroachdb.md index a64832549da..13b28bd1cc3 100644 --- a/src/current/molt/migrate-to-cockroachdb.md +++ b/src/current/molt/migrate-to-cockroachdb.md @@ -11,8 +11,8 @@ MOLT Fetch supports various migration flows using [MOLT Fetch modes]({% link mol | Migration flow | Mode | Description | Best for | |---------------------------------------------------------------------|------------------------------|---------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------| -| [Bulk load]({% link molt/migrate-bulk-load.md %}) | `--mode data-load` | Perform a one-time bulk load of source data into CockroachDB. | Testing, migrations with [planned downtime]({% link molt/migration-strategy.md %}#approach-to-downtime) | -| [Load and replicate]({% link molt/migrate-load-replicate.md %}) | MOLT Fetch + MOLT Replicator | Load source data using MOLT Fetch, then replicate subsequent changes using MOLT Replicator. | [Minimal downtime]({% link molt/migration-strategy.md %}#approach-to-downtime) migrations | +| [Bulk load]({% link molt/migrate-bulk-load.md %}) | `--mode data-load` | Perform a one-time bulk load of source data into CockroachDB. | Testing, migrations with [planned downtime]({% link molt/migration-considerations.md %}#permissible-downtime) | +| [Load and replicate]({% link molt/migrate-load-replicate.md %}) | MOLT Fetch + MOLT Replicator | Load source data using MOLT Fetch, then replicate subsequent changes using MOLT Replicator. | [Minimal downtime]({% link molt/migration-considerations.md %}#permissible-downtime) migrations | | [Resume replication]({% link molt/migrate-resume-replication.md %}) | `--mode replication-only` | Resume replication from a checkpoint after interruption. | Resuming interrupted migrations, post-load sync | | [Failback]({% link molt/migrate-failback.md %}) | `--mode failback` | Replicate changes from CockroachDB back to the source database. | [Rollback]({% link molt/migrate-failback.md %}) scenarios | diff --git a/src/current/molt/migration-considerations-phases.md b/src/current/molt/migration-considerations-phases.md index fc856f1ceac..46c36907491 100644 --- a/src/current/molt/migration-considerations-phases.md +++ b/src/current/molt/migration-considerations-phases.md @@ -48,11 +48,11 @@ Tips for picking slices: Phased and unphased migrations are both supported natively by MOLT. -By default, [MOLT Fetch]() moves all data from the source database to CockroachDB. However, you can use the `--schema-filter`, `--table-filter`, and `--filter-path` flags to selective migrate data from the source to the target. Learn more about [schema and table selection]({% link molt/molt-fetch-usage.md %}#schema-and-table-selection) and [selective data movement]({% link molt/molt-fetch-usage.md %}#selective-data-movement), both of which can enable a phased migration. +By default, [MOLT Fetch]({% link molt/molt-fetch.md %}) moves all data from the source database to CockroachDB. However, you can use the `--schema-filter`, `--table-filter`, and `--filter-path` flags to selective migrate data from the source to the target. Learn more about [schema and table selection]({% link molt/molt-fetch.md %}#schema-and-table-selection) and [selective data movement]({% link molt/molt-fetch.md %}#selective-data-movement), both of which can enable a phased migration. -Similarly, you can use [MOLT Verify]()'s `--schema-filter` and `--table-filter` flags to run validation checks on subsets of the data in your source and target databases. In a phased migration, you will likely want to verify data at the end of each migration phase, rather than at the end of the entire migration. +Similarly, you can use [MOLT Verify]({% link molt/molt-verify.md %})'s `--schema-filter` and `--table-filter` flags to run validation checks on subsets of the data in your source and target databases. In a phased migration, you will likely want to verify data at the end of each migration phase, rather than at the end of the entire migration. -[MOLT Replicator]() replicates full tables by default. If you choose to combine phased migration with [continuous replication]({% link molt/migration-considerations-replication.md %}), you will either need to select phases that include whole tables, or else use [userscripts]({% link molt/molt-replicator.md %}#flags) to select rows to replicate. +[MOLT Replicator]({% link molt/molt-replicator.md %}) replicates full tables by default. If you choose to combine phased migration with [continuous replication]({% link molt/migration-considerations-replication.md %}), you will either need to select phases that include whole tables, or else use [userscripts]({% link molt/molt-replicator.md %}#flags) to select rows to replicate. ## Example sequences @@ -73,4 +73,4 @@ Similarly, you can use [MOLT Verify]()'s `--schema-filter` and `--table-filter` - [Migration Overview]({% link molt/migration-overview.md %}) - [Migration Considerations]({% link molt/migration-considerations.md %}) - [Continuous Replication]({% link molt/migration-considerations-replication.md %}) -- [MOLT Fetch]({% link molt/molt-fetch-overview.md %}) +- [MOLT Fetch]({% link molt/molt-fetch.md %}) diff --git a/src/current/molt/migration-considerations.md b/src/current/molt/migration-considerations.md index 15518dd0c82..07f6151b71f 100644 --- a/src/current/molt/migration-considerations.md +++ b/src/current/molt/migration-considerations.md @@ -30,7 +30,7 @@ When deciding on the options for each migration variable, consider the following ### Permissible downtime -How much downtime can your application tolerate during the migration? This is one of the most critical factors in determining your migration approach, and it may influence your choices for [migration granularity](), [continuous replication](), and [cutover strategy](). +How much downtime can your application tolerate during the migration? This is one of the most critical factors in determining your migration approach, and it may influence your choices for [migration granularity]({% link molt/migration-considerations-phases.md %}), [continuous replication]({% link molt/migration-considerations-replication.md %}), and [cutover strategy]({% link molt/migration-considerations-cutover.md %}). - **Planned downtime** is made known to your users in advance. It involves taking the application offline, conducting the migration, and bginging the application back online on CockroachDB. @@ -40,29 +40,29 @@ How much downtime can your application tolerate during the migration? This is on - **Minimal downtime** impacts as few customers as possible, ideally without impacting their regular usage. If your application is intentionally offline at certain times (e.g., outside business hours), you can migrate the data without users noticing. Alternatively, if your application's functionality is not time-sensitive (e.g., it sends batched messages or emails), you can queue requests while the system is offline and process them after completing the migration to CockroachDB. -- **Near-zero downtime** is necessary for mission-critical applications. For these migrations, consider cutover strategies that keep applications online for as long as possible, and which utilize [continuous replication](). +- **Near-zero downtime** is necessary for mission-critical applications. For these migrations, consider cutover strategies that keep applications online for as long as possible, and which utilize [continuous replication]({% link molt/migration-considerations-replication.md %}). In addition to downtime duration, consider whether your application could support windows of **reduced functionality** in which some, but not all, application functionality is brought offline. For example, you can disable writes but not reads while you migrate the application data, and queue data to be written after completing the migration. ### Migration timeframe and allowable complexity -When do you need to complete the migration? How many team members can be allocated for this effort? How much complex orchestration can your team manage? These factors may influence your choices for [migration granularity](), [continuous replication](), and [cutover strategy](). +When do you need to complete the migration? How many team members can be allocated for this effort? How much complex orchestration can your team manage? These factors may influence your choices for [migration granularity]({% link molt/migration-considerations-phases.md %}), [continuous replication]({% link molt/migration-considerations-replication.md %}), and [cutover strategy]({% link molt/migration-considerations-cutover.md %}). -- Migrations with a short timeline, or which cannot accommodate high complexity, may want to migrate data [all at once](), without utilizing [continuous replication](), and requiring [manual reconciliation]() in the event of migration failure. +- Migrations with a short timeline, or which cannot accommodate high complexity, may want to migrate data [all at once]({% link molt/migration-considerations-phases.md %}), without utilizing [continuous replication]({% link molt/migration-considerations-replication.md %}), and requiring [manual reconciliation]({% link molt/migration-considerations-rollback.md %}) in the event of migration failure. -- Migrations with a long timeline, or which can accomodate complexity, may want to migrate data [in phases](). If the migration requires minimal downtime, these migrations may also want to utilize [continuous replication](). If the migration is low in risk-tolerance, these migrations may also want to enable [failback](). +- Migrations with a long timeline, or which can accomodate complexity, may want to migrate data [in phases]({% link molt/migration-considerations-phases.md %}). If the migration requires minimal downtime, these migrations may also want to utilize [continuous replication]({% link molt/migration-considerations-replication.md %}). If the migration is low in risk-tolerance, these migrations may also want to enable [failback]({% link molt/migration-considerations-rollback.md %}). ### Risk tolerance -How much risk is your organization willing to accept during the migration? This may influence your choices for [migration granularity](), [validation strategy](), and [rollback plan](). +How much risk is your organization willing to accept during the migration? This may influence your choices for [migration granularity]({% link molt/migration-considerations-phases.md %}), [validation strategy]({% link molt/migration-considerations-validation.md %}), and [rollback plan]({% link molt/migration-considerations-rollback.md %}). -- Risk-averse migrations should prefer [phased migrations]() that limit the blast radius of any issues. Start with low-risk slices (e.g., a small cohort of tenants or a non-critical service), [validate thoroughly](), and progressively expand to higher-value workloads. These migrations may also prefer [rollback plans]() that enable quick recovery in the event of migration issues. +- Risk-averse migrations should prefer [phased migrations]({% link molt/migration-considerations-phases.md %}) that limit the blast radius of any issues. Start with low-risk slices (e.g., a small cohort of tenants or a non-critical service), [validate thoroughly]({% link molt/migration-considerations-validation.md %}), and progressively expand to higher-value workloads. These migrations may also prefer [rollback plans]({% link molt/migration-considerations-rollback.md %}) that enable quick recovery in the event of migration issues. -- For risk-tolerant migrations, it may be acceptable to migrate [all of your data at once](). Less stringent [validation strategies]() and [manual reconciliation]() in the event of a migration failure may also be acceptable. +- For risk-tolerant migrations, it may be acceptable to migrate [all of your data at once]({% link molt/migration-considerations-phases.md %}). Less stringent [validation strategies]({% link molt/migration-considerations-validation.md %}) and [manual reconciliation]({% link molt/migration-considerations-rollback.md %}) in the event of a migration failure may also be acceptable. ___ -These above factors are only a subset of all of what you'll want to consider in the decision-making about your CockroachDB migration, along with your specific business requirements and technical constraints. It's recommended that you document these decisions and the reasoning behind them as part of your [migration plan](). +These above factors are only a subset of all of what you'll want to consider in the decision-making about your CockroachDB migration, along with your specific business requirements and technical constraints. It's recommended that you document these decisions and the reasoning behind them as part of your [migration plan]({% link molt/migration-strategy.md %}#develop-a-migration-plan). ## See also diff --git a/src/current/molt/migration-overview.md b/src/current/molt/migration-overview.md index 748f725a602..800da53cab7 100644 --- a/src/current/molt/migration-overview.md +++ b/src/current/molt/migration-overview.md @@ -13,7 +13,6 @@ This page provides an overview of the following: - Overall [migration sequence](#migration-sequence) - [MOLT tools](#molt-tools) -- Supported [migration flows](#migration-flows) ## Migration sequence @@ -48,8 +47,6 @@ The MOLT (Migrate Off Legacy Technology) toolkit enables safe, minimal-downtime MOLT tooling overview -For more details, refer to [Migration flows](#migration-flows). - ## MOLT tools [MOLT (Migrate Off Legacy Technology)]({% link releases/molt.md %}) is a set of tools for schema conversion, data load, replication, and validation. Migrations with MOLT are resilient, restartable, and scalable to large data sets. @@ -103,7 +100,7 @@ The [MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}) [MOLT Fetch]({% link molt/molt-fetch.md %}) performs the initial data load to CockroachDB. It supports: -- [Multiple migration flows](#migration-flows) via `IMPORT INTO` or `COPY FROM`. +- Multiple migration flows via `IMPORT INTO` or `COPY FROM`. - Data movement via [cloud storage, local file servers, or direct copy]({% link molt/molt-fetch.md %}#data-path). - [Concurrent data export]({% link molt/molt-fetch.md %}#best-practices) from multiple source tables and shards. - [Schema transformation rules]({% link molt/molt-fetch.md %}#transformations). diff --git a/src/current/molt/migration-strategy.md b/src/current/molt/migration-strategy.md index 769b7f1164a..b6e76d0c14f 100644 --- a/src/current/molt/migration-strategy.md +++ b/src/current/molt/migration-strategy.md @@ -10,10 +10,9 @@ A successful migration to CockroachDB requires planning for downtime, applicatio This page outlines key decisions, infrastructure considerations, and best practices for a resilient and repeatable high-level migration strategy: - [Develop a migration plan](#develop-a-migration-plan). -- Evaluate your [downtime approach](#approach-to-downtime). - [Size the target CockroachDB cluster](#capacity-planning). - Implement [application changes](#application-changes) to address necessary [schema changes](#schema-design-best-practices), [transaction contention](#handling-transaction-contention), and [unimplemented features](#unimplemented-features-and-syntax-incompatibilities). -- [Prepare for migration](#prepare-for-migration) by running a [pre-mortem](#run-a-migration-pre-mortem), setting up [metrics](#set-up-monitoring-and-alerting), [loading test data](#load-test-data), [validating application queries](#validate-queries) for correctness and performance, performing a [migration dry run](#perform-a-dry-run), and reviewing your [cutover strategy](#cutover-strategy). +- [Prepare for migration](#prepare-for-migration) by running a [pre-mortem](#run-a-migration-pre-mortem), setting up [metrics](#set-up-monitoring-and-alerting), [loading test data](#load-test-data), [validating application queries](#validate-queries) for correctness and performance, performing a [migration dry run](#perform-a-dry-run), and reviewing your cutover strategy. {% assign variable = value %} {{site.data.alerts.callout_success}} For help migrating to CockroachDB, contact our sales team. @@ -96,7 +95,7 @@ Based on the error budget you [defined in your migration plan](#develop-a-migrat ### Load test data -It's useful to load test data into CockroachDB so that you can [test your application queries](#validate-queries). Refer to [Migration flows]({% link molt/migration-overview.md %}#migration-flows). +It's useful to load test data into CockroachDB so that you can [test your application queries](#validate-queries). MOLT Fetch [supports both `IMPORT INTO` and `COPY FROM`]({% link molt/molt-fetch.md %}#data-load-mode) for loading data into CockroachDB: diff --git a/src/current/molt/molt-fetch-best-practices.md b/src/current/molt/molt-fetch-best-practices.md deleted file mode 100644 index 873eca5b331..00000000000 --- a/src/current/molt/molt-fetch-best-practices.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: MOLT Fetch Best Practices -summary: Learn the best ways to run MOLT Fetch, considering individual business and technical constraints. -toc: true -docs_area: migrate ---- - -## Security - -Cockroach Labs strongly recommends the following security practices. - -### Connection security - -{% include molt/molt-secure-connection-strings.md %} - -{{site.data.alerts.callout_info}} -By default, insecure connections (i.e., `sslmode=disable` on PostgreSQL; `sslmode` not set on MySQL) are disallowed. When using an insecure connection, `molt fetch` returns an error. To override this check, you can enable the `--allow-tls-mode-disable` flag. Do this **only** when testing, or if a secure SSL/TLS connection to the source or target database is not possible. -{{site.data.alerts.end}} - -### Cloud storage security - -{% include molt/fetch-secure-cloud-storage.md %} - -## Best practices - -### Test and validate - -To verify that your connections and configuration work properly, run MOLT Fetch in a staging environment before migrating any data in production. Use a test or development environment that closely resembles production. - -### Configure the source database and connection - -- To prevent connections from terminating prematurely during the [data export phase](#data-export-phase), set the following to high values on the source database: - - - **Maximum allowed number of connections.** MOLT Fetch can export data across multiple connections. The number of connections it will create is the number of shards ([`--export-concurrency`](#global-flags)) multiplied by the number of tables ([`--table-concurrency`](#global-flags)) being exported concurrently. - - {{site.data.alerts.callout_info}} - With the default numerical range sharding, only tables with [primary key]({% link {{ site.current_cloud_version }}/primary-key.md %}) types of [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) can be sharded. PostgreSQL users can enable [`--use-stats-based-sharding`](#global-flags) to use statistics-based sharding for tables with primary keys of any data type. For details, refer to [Table sharding](#table-sharding). - {{site.data.alerts.end}} - - - **Maximum lifetime of a connection.** - -- If a PostgreSQL database is set as a [source](#source-and-target-databases), ensure that [`idle_in_transaction_session_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT) on PostgreSQL is either disabled or set to a value longer than the duration of the [data export phase](#data-export-phase). Otherwise, the connection will be prematurely terminated. To estimate the time needed to export the PostgreSQL tables, you can perform a dry run and sum the value of [`molt_fetch_table_export_duration_ms`](#monitoring) for all exported tables. - -### Optimize performance - -- {% include molt/molt-drop-constraints-indexes.md %} - -- For PostgreSQL sources using [`--use-stats-based-sharding`](#global-flags), run [`ANALYZE`]({% link {{ site.current_cloud_version }}/create-statistics.md %}) on source tables before migration to ensure optimal shard distribution. This is especially important for large tables where even distribution can significantly improve export performance. - -- To prevent memory outages during `READ COMMITTED` [data export](#data-export-phase) of tables with large rows, estimate the amount of memory used to export a table: - - ~~~ - --row-batch-size * --export-concurrency * average size of the table rows - ~~~ - - If you are exporting more than one table at a time (i.e., [`--table-concurrency`](#global-flags) is set higher than `1`), add the estimated memory usage for the tables with the largest row sizes. Ensure that you have sufficient memory to run `molt fetch`, and adjust `--row-batch-size` accordingly. For details on how concurrency and sharding interact, refer to [Table sharding](#table-sharding). - -- If a table in the source database is much larger than the other tables, [filter and export the largest table](#schema-and-table-selection) in its own `molt fetch` task. Repeat this for each of the largest tables. Then export the remaining tables in another task. - -- Ensure that the machine running MOLT Fetch is large enough to handle the amount of data being migrated. Fetch performance can sometimes be limited by available resources, but should always be making progress. To identify possible resource constraints, observe the `molt_fetch_rows_exported` [metric](#monitoring) for decreases in the number of rows being processed. You can use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view metrics. For details on optimizing export performance through sharding, refer to [Table sharding](#table-sharding). - -### Import and continuation handling - -- When using [`IMPORT INTO`](#data-load-mode) during the [data import phase](#data-import-phase) to load tables into CockroachDB, if the fetch task terminates before the import job completes, the hanging import job on the target database will keep the table offline. To make this table accessible again, [manually resume or cancel the job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs). Then resume `molt fetch` using [continuation](#fetch-continuation), or restart the task from the beginning. - -## See also - -- X diff --git a/src/current/molt/molt-fetch-flags.md b/src/current/molt/molt-fetch-flags.md deleted file mode 100644 index 48913756236..00000000000 --- a/src/current/molt/molt-fetch-flags.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: MOLT Fetch Flags -summary: Reference doc for all of the commands and flags to be used with MOLT Fetch. -toc: true -docs_area: migrate ---- - - -## Commands - -| Command | Usage | -|---------|---------------------------------------------------------------------------------------------------| -| `fetch` | Start the fetch task. This loads data from a source database to a target CockroachDB database. | - -### Subcommands - -| Command | Usage | -|--------------|----------------------------------------------------------------------| -| `tokens list` | List active [continuation tokens](#list-active-continuation-tokens). | - -## Flags - -### Global flags - -| Flag | Description | -|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `--source` | (Required) Connection string used to connect to the Oracle PDB (in a CDB/PDB architecture) or to a standalone database (non‑CDB). For details, refer to [Source and target databases](#source-and-target-databases). | -| `--source-cdb` | Connection string for the Oracle container database (CDB) when using a multitenant (CDB/PDB) architecture. Omit this flag on a non‑multitenant Oracle database. For details, refer to [Source and target databases](#source-and-target-databases). | -| `--target` | (Required) Connection string for the target database. For details, refer to [Source and target databases](#source-and-target-databases). | -| `--allow-tls-mode-disable` | Allow insecure connections to databases. Secure SSL/TLS connections should be used by default. This should be enabled **only** if secure SSL/TLS connections to the source or target database are not possible. | -| `--assume-role` | Service account to use for assume role authentication. `--use-implicit-auth` must be included. For example, `--assume-role='user-test@cluster-ephemeral.iam.gserviceaccount.com' --use-implicit-auth`. For details, refer to [Cloud Storage Authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}). | -| `--bucket-path` | The path within the [cloud storage](#bucket-path) bucket where intermediate files are written (e.g., `'s3://bucket/path'` or `'gs://bucket/path'`). Only the URL path is used; query parameters (e.g., credentials) are ignored. To pass in query parameters, use the appropriate flags: `--assume-role`, `--import-region`, `--use-implicit-auth`. | -| `--case-sensitive` | Toggle case sensitivity when comparing table and column names on the source and target. To disable case sensitivity, set `--case-sensitive=false`. If `=` is **not** included (e.g., `--case-sensitive false`), the flag is interpreted as `--case-sensitive` (i.e., `--case-sensitive=true`).

**Default:** `false` | -| `--cleanup` | Whether to delete intermediate files after moving data using [cloud or local storage](#data-path). **Note:** Cleanup does not occur on [continuation](#fetch-continuation). | -| `--compression` | Compression method for data when using [`IMPORT INTO`](#data-load-mode) (`gzip`/`none`).

**Default:** `gzip` | -| `--continuation-file-name` | Restart fetch at the specified filename if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation](#fetch-continuation). | -| `--continuation-token` | Restart fetch at a specific table, using the specified continuation token, if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation](#fetch-continuation). | -| `--crdb-pts-duration` | The duration for which each timestamp used in data export from a CockroachDB source is protected from garbage collection. This ensures that the data snapshot remains consistent. For example, if set to `24h`, each timestamp is protected for 24 hours from the initiation of the export job. This duration is extended at regular intervals specified in `--crdb-pts-refresh-interval`.

**Default:** `24h0m0s` | -| `--crdb-pts-refresh-interval` | The frequency at which the protected timestamp's validity is extended. This interval maintains protection of the data snapshot until data export from a CockroachDB source is completed. For example, if set to `10m`, the protected timestamp's expiration will be extended by the duration specified in `--crdb-pts-duration` (e.g., `24h`) every 10 minutes while export is not complete.

**Default:** `10m0s` | -| `--direct-copy` | Enables [direct copy](#direct-copy), which copies data directly from source to target without using an intermediate store. | -| `--export-concurrency` | Number of shards to export at a time per table, each on a dedicated thread. This controls how many shards are created for each individual table during the [data export phase](#data-export-phase) and is distinct from `--table-concurrency`, which controls how many tables are processed simultaneously. The total number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`. Tables can be sharded with a range-based or stats-based mechanism. For details, refer to [Table sharding](#table-sharding).

**Default:** `4` | -| `--export-retry-max-attempts` | Maximum number of retry attempts for source export queries when connection failures occur. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `3` | -| `--export-retry-max-duration` | Maximum total duration for retrying source export queries. If `0`, no time limit is enforced. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `5m0s` | -| `--filter-path` | Path to a JSON file defining row-level filters for the [data import phase](#data-import-phase). Refer to [Selective data movement](#selective-data-movement). | -| `--fetch-id` | Restart fetch task corresponding to the specified ID. If `--continuation-file-name` or `--continuation-token` are not specified, fetch restarts for all failed tables. | -| `--flush-rows` | Number of rows before the source data is flushed to intermediate files. **Note:** If `--flush-size` is also specified, the fetch behavior is based on the flag whose criterion is met first. | -| `--flush-size` | Size (in bytes) before the source data is flushed to intermediate files. **Note:** If `--flush-rows` is also specified, the fetch behavior is based on the flag whose criterion is met first. | -| `--ignore-replication-check` | Skip querying for replication checkpoints such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle. This option is intended for use during bulk load migrations or when doing a one-time data export from a read replica. | -| `--import-batch-size` | The number of files to be imported at a time to the target database during the [data import phase](#data-import-phase). This applies only when using [`IMPORT INTO`](#data-load-mode) for data movement. **Note:** Increasing this value can improve the performance of full-scan queries on the target database shortly after fetch completes, but very high values are not recommended. If any individual file in the import batch fails, you must [retry](#fetch-continuation) the entire batch.

**Default:** `1000` | -| `--import-region` | The region of the [cloud storage](#bucket-path) bucket. This applies only to [Amazon S3 buckets](#bucket-path). Set this flag only if you need to specify an `AWS_REGION` explicitly when using [`IMPORT INTO`](#data-load-mode) for data movement. For example, `--import-region=ap-south-1`. | -| `--local-path` | The path within the [local file server](#local-path) where intermediate files are written (e.g., `data/migration/cockroach`). `--local-path-listen-addr` must be specified. | -| `--local-path-crdb-access-addr` | Address of a [local file server](#local-path) that is **publicly accessible**. This flag is only necessary if CockroachDB cannot reach the local address specified with `--local-path-listen-addr` (e.g., when moving data to a CockroachDB {{ site.data.products.cloud }} deployment). `--local-path` and `--local-path-listen-addr` must be specified.

**Default:** Value of `--local-path-listen-addr`. | -| `--local-path-listen-addr` | Write intermediate files to a [local file server](#local-path) at the specified address (e.g., `'localhost:3000'`). `--local-path` must be specified. | -| `--log-file` | Write messages to the specified log filename. If no filename is provided, messages write to `fetch-{datetime}.log`. If `"stdout"` is provided, messages write to `stdout`. | -| `--logging` | Level at which to log messages (`trace`/`debug`/`info`/`warn`/`error`/`fatal`/`panic`).

**Default:** `info` | -| `--metrics-listen-addr` | Address of the Prometheus metrics endpoint, which has the path `{address}/metrics`. For details on important metrics to monitor, refer to [Monitoring](#monitoring).

**Default:** `'127.0.0.1:3030'` | -| `--mode` | Configure the MOLT Fetch behavior: `data-load`, `export-only`, or `import-only`. For details, refer to [Fetch mode](#fetch-mode).

**Default:** `data-load` | -| `--non-interactive` | Run the fetch task without interactive prompts. This is recommended **only** when running `molt fetch` in an automated process (i.e., a job or continuous integration). | -| `--pprof-listen-addr` | Address of the pprof endpoint.

**Default:** `'127.0.0.1:3031'` | -| `--row-batch-size` | Number of rows per shard to export at a time. For details on sharding, refer to [Table sharding](#table-sharding). See also [Best practices](#best-practices).

**Default:** `100000` | -| `--schema-filter` | Move schemas that match a specified [regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | -| `--skip-pk-check` | Skip primary-key matching to allow data load when source or target tables have missing or mismatched primary keys. Disables sharding and bypasses `--export-concurrency` and `--row-batch-size` settings. Refer to [Skip primary key matching](#skip-primary-key-matching).

**Default:** `false` | -| `--table-concurrency` | Number of tables to export at a time. The number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`.

**Default:** `4` | -| `--table-exclusion-filter` | Exclude tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

This value **cannot** be set to `'.*'`, which would cause every table to be excluded.

**Default:** Empty string | -| `--table-filter` | Move tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | -| `--table-handling` | How tables are initialized on the target database (`none`/`drop-on-target-and-recreate`/`truncate-if-exists`). For details, see [Target table handling](#target-table-handling).

**Default:** `none` | -| `--transformations-file` | Path to a JSON file that defines transformations to be performed on the target schema during the fetch task. Refer to [Transformations](#transformations). | -| `--type-map-file` | Path to a JSON file that contains explicit type mappings for automatic schema creation, when enabled with `--table-handling drop-on-target-and-recreate`. For details on the JSON format and valid type mappings, see [type mapping](#type-mapping). | -| `--use-console-writer` | Use the console writer, which has cleaner log output but introduces more latency.

**Default:** `false` (log as structured JSON) | -| `--use-copy` | Use [`COPY FROM`](#data-load-mode) to move data. This makes tables queryable during data load, but is slower than using `IMPORT INTO`. For details, refer to [Data movement](#data-load-mode). | -| `--use-implicit-auth` | Use [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}) for [cloud storage](#bucket-path) URIs. | -| `--use-stats-based-sharding` | Enable statistics-based sharding for PostgreSQL sources. This allows sharding of tables with primary keys of any data type and can create more evenly distributed shards compared to the default numerical range sharding. Requires PostgreSQL 11+ and access to `pg_stats`. For details, refer to [Table sharding](#table-sharding). | - - -### `tokens list` flags - -| Flag | Description | -|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------| -| `--conn-string` | (Required) Connection string for the target database. For details, see [List active continuation tokens](#list-active-continuation-tokens). | -| `-n`, `--num-results` | Number of results to return. | - -## See also - -- X \ No newline at end of file diff --git a/src/current/molt/molt-fetch-install.md b/src/current/molt/molt-fetch-install.md deleted file mode 100644 index a8b720d1e94..00000000000 --- a/src/current/molt/molt-fetch-install.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: MOLT Fetch Installation -summary: Learn how to install the MOLT Fetch tool to move data from a source database to CockroachDB. -toc: true -docs_area: migrate ---- - -## Prerequisites - -### Supported databases - -The following source databases are supported: - -- PostgreSQL 11-16 -- MySQL 5.7, 8.0 and later -- Oracle Database 19c (Enterprise Edition) and 21c (Express Edition) - -### Database configuration - -Ensure that the source and target schemas are identical, unless you enable automatic schema creation with the [`drop-on-target-and-recreate`](#target-table-handling) option. If you are creating the target schema manually, review the behaviors in [Mismatch handling](#mismatch-handling). - -{{site.data.alerts.callout_info}} -MOLT Fetch does not support migrating sequences. If your source database contains sequences, refer to the [guidance on indexing with sequential keys]({% link {{site.current_cloud_version}}/sql-faqs.md %}#how-do-i-generate-unique-slowly-increasing-sequential-numbers-in-cockroachdb). If a sequential key is necessary in your CockroachDB table, you must create it manually. After using MOLT Fetch to load the data onto the target, but before cutover, make sure to update each sequence's current value using [`setval()`]({% link {{site.current_cloud_version}}/functions-and-operators.md %}#sequence-functions) so that new inserts continue from the correct point. -{{site.data.alerts.end}} - -If you plan to use cloud storage for the data migration, follow the steps in [Cloud storage security](#cloud-storage-security). - -### User permissions - -The SQL user running MOLT Fetch requires specific privileges on both the source and target databases: - -| Database | Required Privileges | Details | -|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------| -| PostgreSQL source |
  • `CONNECT` on database.
  • `USAGE` on schema.
  • `SELECT` on tables to migrate.
| [Create PostgreSQL migration user]({% link molt/migrate-bulk-load.md %}#create-migration-user-on-source-database) | -| MySQL source |
  • `SELECT` on tables to migrate.
| [Create MySQL migration user]({% link molt/migrate-bulk-load.md %}?filters=mysql#create-migration-user-on-source-database) | -| Oracle source |
  • `CONNECT` and `CREATE SESSION`.
  • `SELECT` and `FLASHBACK` on tables to migrate.
  • `SELECT` on metadata views (`ALL_USERS`, `DBA_USERS`, `DBA_OBJECTS`, `DBA_SYNONYMS`, `DBA_TABLES`).
| [Create Oracle migration user]({% link molt/migrate-bulk-load.md %}?filters=oracle#create-migration-user-on-source-database) | -| CockroachDB target |
  • `ALL` on target database.
  • `CREATE` on schema.
  • `SELECT`, `INSERT`, `UPDATE`, `DELETE` on target tables.
  • For `IMPORT INTO`: `SELECT`, `INSERT`, `DROP` on target tables. Optionally `EXTERNALIOIMPLICITACCESS` for implicit cloud storage authentication.
  • For `COPY FROM`: `admin` role.
| [Create CockroachDB user]({% link molt/migrate-bulk-load.md %}#create-the-sql-user) | - -## Installation - -{% include molt/molt-install.md %} - -### Docker usage - -{% include molt/molt-docker.md %} - -## See also - -- X \ No newline at end of file diff --git a/src/current/molt/molt-fetch-monitoring.md b/src/current/molt/molt-fetch-monitoring.md deleted file mode 100644 index 18d98b836fe..00000000000 --- a/src/current/molt/molt-fetch-monitoring.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: MOLT Fetch Monitoring -summary: Learn how to use the monitoring functionality made available with MOLT Fetch. -toc: true -docs_area: migrate ---- - -## Monitoring - -### Metrics - -By default, MOLT Fetch exports [Prometheus](https://prometheus.io/) metrics at `127.0.0.1:3030/metrics`. You can configure this endpoint with the `--metrics-listen-addr` [flag](#global-flags). - -Cockroach Labs recommends monitoring the following metrics: - -| Metric Name | Description | -|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------| -| `molt_fetch_num_tables` | Number of tables that will be moved from the source. | -| `molt_fetch_num_task_errors` | Number of errors encountered by the fetch task. | -| `molt_fetch_overall_duration` | Duration (in seconds) of the fetch task. | -| `molt_fetch_rows_exported` | Number of rows that have been exported from a table. For example:
`molt_fetch_rows_exported{table="public.users"}` | -| `molt_fetch_rows_imported` | Number of rows that have been imported from a table. For example:
`molt_fetch_rows_imported{table="public.users"}` | -| `molt_fetch_table_export_duration_ms` | Duration (in milliseconds) of a table's export. For example:
`molt_fetch_table_export_duration_ms{table="public.users"}` | -| `molt_fetch_table_import_duration_ms` | Duration (in milliseconds) of a table's import. For example:
`molt_fetch_table_import_duration_ms{table="public.users"}` | - -You can also use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view the preceding metrics. - -## See also - -- X \ No newline at end of file diff --git a/src/current/molt/molt-fetch-overview.md b/src/current/molt/molt-fetch-overview.md deleted file mode 100644 index d71ffaba7ba..00000000000 --- a/src/current/molt/molt-fetch-overview.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -title: MOLT Fetch Overview -summary: Learn how to use the MOLT Fetch tool to move data from a source database to CockroachDB. -toc: true -docs_area: migrate ---- - -MOLT Fetch moves data from a source database into CockroachDB as part of a [database migration]({% link molt/migration-overview.md %}). - -MOLT Fetch uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to move the source data to cloud storage (Google Cloud Storage, Amazon S3, or Azure Blob Storage), a local file server, or local memory. Once the data is exported, MOLT Fetch loads the data into a target CockroachDB database. For details, refer to [Migration phases](#migration-phases). - -## Terminology - -- *Shard*: A portion of a table's data exported concurrently during the data export phase. Tables are divided into shards to enable parallel processing. For details, refer to [Table sharding](#table-sharding). -- *Continuation token*: An identifier that marks the progress of a fetch task. Used to resume data loading from the point of interruption if a fetch task fails. For details, refer to [Fetch continuation](#fetch-continuation). -- *Intermediate files*: Temporary data files written to cloud storage or a local file server during the data export phase. These files are used to stage exported data before importing it into CockroachDB during the data import phase. For details, refer to [Data path](#data-path). - - -## Migration phases - -MOLT Fetch operates in distinct phases to move data from source databases to CockroachDB. For details on available modes, refer to [Fetch mode](#fetch-mode). - -### Data export phase - -MOLT Fetch connects to the source database and exports table data to intermediate storage. Data is written to [cloud storage](#bucket-path) (Amazon S3, Google Cloud Storage, Azure Blob Storage), a [local file server](#local-path), or [directly to CockroachDB memory](#direct-copy). Multiple tables and table shards can be exported simultaneously using [`--table-concurrency`](#global-flags) and [`--export-concurrency`](#global-flags), with large tables divided into shards for parallel processing. For details, refer to: - -- [Fetch mode](#fetch-mode) -- [Table sharding](#table-sharding) - -### Data import phase - -MOLT Fetch loads the exported data into the target CockroachDB database. The process uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) (faster, tables offline during import) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) (slower, tables remain queryable) to move data. Data files are imported in configurable batches using [`--import-batch-size`](#global-flags), and target tables can be automatically created, truncated, or left unchanged based on [`--table-handling`](#global-flags) settings. For details, refer to: - -- [Data movement](#data-load-mode) -- [Target table handling](#target-table-handling) - -## Common workflows - -### Bulk data load - -To perform a bulk data load migration from your source database to CockroachDB, run the `molt fetch` command with the required flags. - -Specify the source and target database connections. For connection string formats, refer to [Source and target databases](#source-and-target-databases): - -{% include_cached copy-clipboard.html %} -~~~ ---source $SOURCE ---target $TARGET -~~~ - -Specify how to move data to CockroachDB. Use [cloud storage](#bucket-path) for intermediate file storage: - -{% include_cached copy-clipboard.html %} -~~~ ---bucket-path 's3://bucket/path' -~~~ - -Alternatively, use a [local file server](#local-path) for intermediate storage: - -{% include_cached copy-clipboard.html %} -~~~ ---local-path /migration/data/cockroach ---local-path-listen-addr 'localhost:3000' -~~~ - -Alternatively, use [direct copy](#direct-copy) to move data directly without intermediate storage: - -{% include_cached copy-clipboard.html %} -~~~ ---direct-copy -~~~ - -Optionally, filter which schemas and tables to migrate. By default, all schemas and tables are migrated. For details, refer to [Schema and table selection](#schema-and-table-selection): - -{% include_cached copy-clipboard.html %} -~~~ ---schema-filter 'public' ---table-filter '.*user.*' -~~~ - -Specify how to handle target tables. By default, `--table-handling` is set to `none`, which loads data without changing existing data in the tables. For details, refer to [Target table handling](#target-table-handling): - -{% include_cached copy-clipboard.html %} -~~~ ---table-handling truncate-if-exists -~~~ - -When performing a bulk load without subsequent replication, use `--ignore-replication-check` to skip querying for replication checkpoints (such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle). This is appropriate when: - -- Performing a one-time data migration with no plan to replicate ongoing changes. -- Exporting data from a read replica where replication checkpoints are unavailable. - -{% include_cached copy-clipboard.html %} -~~~ ---ignore-replication-check -~~~ - -At minimum, the `molt fetch` command should include the source, target, data path, and `--ignore-replication-check` flags: - -{% include_cached copy-clipboard.html %} -~~~ shell -molt fetch \ ---source $SOURCE \ ---target $TARGET \ ---bucket-path 's3://bucket/path' \ ---ignore-replication-check -~~~ - -For detailed steps, refer to [Bulk load migration]({% link molt/migrate-bulk-load.md %}). - -### Load before replication - -To perform an initial data load before setting up ongoing replication with [MOLT Replicator]({% link molt/molt-replicator.md %}), run the `molt fetch` command without `--ignore-replication-check`. This captures replication checkpoints during the data load. - -The workflow is the same as [Bulk data load](#bulk-data-load), except: - -- Exclude `--ignore-replication-check`. MOLT Fetch will query and record replication checkpoints. -- After the data load completes, check the [CDC cursor](#cdc-cursor) in the output for the checkpoint value to use with MOLT Replicator. - -At minimum, the `molt fetch` command should include the source, target, and data path flags: - -{% include_cached copy-clipboard.html %} -~~~ shell -molt fetch \ ---source $SOURCE \ ---target $TARGET \ ---bucket-path 's3://bucket/path' -~~~ - -The output will include a `cdc_cursor` value at the end of the fetch task: - -~~~ json -{"level":"info","type":"summary","fetch_id":"735a4fe0-c478-4de7-a342-cfa9738783dc","num_tables":1,"tables":["public.employees"],"cdc_cursor":"b7f9e0fa-2753-1e1f-5d9b-2402ac810003:3-21","net_duration_ms":4879.890041,"net_duration":"000h 00m 04s","time":"2024-03-18T12:37:02-04:00","message":"fetch complete"} -~~~ - -Use this `cdc_cursor` value when starting MOLT Replicator to ensure replication begins from the correct position. For detailed steps, refer to [Load and replicate]({% link molt/migrate-load-replicate.md %}). - -## See also - -- X \ No newline at end of file diff --git a/src/current/molt/molt-fetch-troubleshooting.md b/src/current/molt/molt-fetch-troubleshooting.md deleted file mode 100644 index 20d9fe9bad8..00000000000 --- a/src/current/molt/molt-fetch-troubleshooting.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: MOLT Fetch Troubleshooting -summary: Learn how to troubleshoot MOLT Fetch, how to handle errors. -toc: true -docs_area: migrate ---- - -## Troubleshooting - -
- - - -
- -{% include molt/molt-troubleshooting-fetch.md %} - -## See also - -- X diff --git a/src/current/molt/molt-fetch-usage.md b/src/current/molt/molt-fetch-usage.md deleted file mode 100644 index d949a6cad2c..00000000000 --- a/src/current/molt/molt-fetch-usage.md +++ /dev/null @@ -1,667 +0,0 @@ ---- -title: MOLT Fetch Usage -summary: Learn how to use MOLT Fetch, including the main flags and commands. -toc: true -docs_area: migrate ---- - -## Usage - -The following sections describe how to use the `molt fetch` [flags](#flags). - -### Source and target databases - -{{site.data.alerts.callout_success}} -Follow the recommendations in [Connection security](#connection-security). -{{site.data.alerts.end}} - -`--source` specifies the connection string of the source database. - -PostgreSQL or CockroachDB connection string: - -{% include_cached copy-clipboard.html %} -~~~ ---source 'postgresql://{username}:{password}@{host}:{port}/{database}' -~~~ - -MySQL connection string: - -{% include_cached copy-clipboard.html %} -~~~ ---source 'mysql://{username}:{password}@{protocol}({host}:{port})/{database}' -~~~ - -Oracle connection string: - -{% include_cached copy-clipboard.html %} -~~~ ---source 'oracle://{username}:{password}@{host}:{port}/{service_name}' -~~~ - -For Oracle Multitenant databases, `--source-cdb` specifies the container database (CDB) connection. `--source` specifies the pluggable database (PDB): - -{% include_cached copy-clipboard.html %} -~~~ ---source 'oracle://{username}:{password}@{host}:{port}/{pdb_service_name}' ---source-cdb 'oracle://{username}:{password}@{host}:{port}/{cdb_service_name}' -~~~ - -`--target` specifies the [CockroachDB connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url): - -{% include_cached copy-clipboard.html %} -~~~ ---target 'postgresql://{username}:{password}@{host}:{port}/{database}' -~~~ - -### Fetch mode - -`--mode` specifies the MOLT Fetch behavior. - -`data-load` (default) instructs MOLT Fetch to load the source data into CockroachDB: - -{% include_cached copy-clipboard.html %} -~~~ ---mode data-load -~~~ - -`export-only` instructs MOLT Fetch to export the source data to the specified [cloud storage](#bucket-path) or [local file server](#local-path). It does not load the data into CockroachDB: - -{% include_cached copy-clipboard.html %} -~~~ ---mode export-only -~~~ - -`import-only` instructs MOLT Fetch to load the source data in the specified [cloud storage](#bucket-path) or [local file server](#local-path) into the CockroachDB target: - -{% include_cached copy-clipboard.html %} -~~~ ---mode import-only -~~~ - -### Data load mode - -MOLT Fetch can use either [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to load data into CockroachDB. - -By default, MOLT Fetch uses `IMPORT INTO`: - -- `IMPORT INTO` achieves the highest throughput, but [requires taking the CockroachDB tables **offline**]({% link {{site.current_cloud_version}}/import-into.md %}#considerations) to achieve its import speed. Tables are taken back online once an [import job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs) completes successfully. See [Best practices](#best-practices). -- `IMPORT INTO` supports compression using the `--compression` flag, which reduces the amount of storage used. - -`--use-copy` configures MOLT Fetch to use `COPY FROM`: - -- `COPY FROM` enables your tables to remain online and accessible. However, it is slower than using [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}). -- `COPY FROM` does not support compression. - -{{site.data.alerts.callout_info}} -`COPY FROM` is also used for [direct copy](#direct-copy). -{{site.data.alerts.end}} - -### Table sharding - -During the [data export phase](#data-export-phase), MOLT Fetch can divide large tables into multiple shards for concurrent export. - -To control the number of shards created per table, use the `--export-concurrency` flag. For example: - -{% include_cached copy-clipboard.html %} -~~~ ---export-concurrency=4 -~~~ - -{{site.data.alerts.callout_success}} -For performance considerations with concurrency settings, refer to [Best practices](#best-practices). -{{site.data.alerts.end}} - -Two sharding mechanisms are available: - -- **Range-based sharding (default):** Tables are divided based on numerical ranges found in primary key values. Only tables with [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) primary keys can use range-based sharding. Tables with other primary key data types export as a single shard. - -- **Stats-based sharding (PostgreSQL only):** Enable with [`--use-stats-based-sharding`](#global-flags) for PostgreSQL 11+ sources. Tables are divided by analyzing the [`pg_stats`](https://www.postgresql.org/docs/current/view-pg-stats.htm) view to create more evenly distributed shards, up to a maximum of 200 shards. Primary keys of any data type are supported. - -Stats-based sharding requires that the user has `SELECT` permissions on source tables and on each table's `pg_stats` view. The latter permission is automatically granted to users that can read the table. - -To optimize stats-based sharding, run [`ANALYZE`](https://www.postgresql.org/docs/current/sql-analyze.html) on source tables before migration to ensure that table statistics are up-to-date and shards are evenly distributed. This requires `MAINTAIN` or `OWNER` permissions on the table. You can analyze specific primary key columns or the entire table. For example: - -{% include_cached copy-clipboard.html %} -~~~ sql -ANALYZE table_name(PK1, PK2, PK3); -~~~ - -{% include_cached copy-clipboard.html %} -~~~ sql -ANALYZE table_name; -~~~ - -Large tables may take time to analyze, but `ANALYZE` can run in the background. You can run `ANALYZE` with `MAINTAIN` or `OWNER` privileges during migration preparation, then perform the actual migration with standard `SELECT` privileges. - -{{site.data.alerts.callout_info}} -Migration without running `ANALYZE` will still work, but shard distribution may be less even. -{{site.data.alerts.end}} - -When using `--use-stats-based-sharding`, monitor the log output for each table you want to migrate. - -If stats-based sharding is successful on a table, MOLT logs the following `INFO` message: - -~~~ -Stats based sharding enabled for table {table_name} -~~~ - -If stats-based sharding fails on a table, MOLT logs the following `WARNING` message and defaults to range-based sharding: - -~~~ -Warning: failed to shard table {table_name} using stats based sharding: {reason_for_failure}, falling back to non stats based sharding -~~~ - -The number of shards is dependent on the number of distinct values in the first primary key column of the table to be migrated. If this is different from the number of shards requested with `--export-concurrency`, MOLT logs the following `WARNING` and continues with the migration: - -~~~ -number of shards formed: {num_shards_formed} is not equal to number of shards requested: {num_shards_requested} for table {table_name} -~~~ - -Because stats-based sharding analyzes the entire table, running `--use-stats-based-sharding` with [`--filter-path`](#global-flags) (refer to [Selective data movement](#selective-data-movement)) will cause imbalanced shards to form. - -### Data path - -MOLT Fetch can move the source data to CockroachDB via [cloud storage](#bucket-path), a [local file server](#local-path), or [directly](#direct-copy) without an intermediate store. - -#### Bucket path - -{{site.data.alerts.callout_success}} -Only the path specified in `--bucket-path` is used. Query parameters, such as credentials, are ignored. To authenticate cloud storage, follow the steps in [Secure cloud storage](#cloud-storage-security). -{{site.data.alerts.end}} - -`--bucket-path` instructs MOLT Fetch to write intermediate files to a path within [Google Cloud Storage](https://cloud.google.com/storage/docs/buckets), [Amazon S3](https://aws.amazon.com/s3/), or [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) to which you have the necessary permissions. Use additional [flags](#global-flags), shown in the following examples, to specify authentication or region parameters as required for bucket access. - -Connect to a Google Cloud Storage bucket with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#google-cloud-storage-implicit) and [assume role]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#set-up-google-cloud-storage-assume-role): - -{% include_cached copy-clipboard.html %} -~~~ ---bucket-path 'gs://migration/data/cockroach' ---assume-role 'user-test@cluster-ephemeral.iam.gserviceaccount.com' ---use-implicit-auth -~~~ - -Connect to an Amazon S3 bucket and explicitly specify the `ap_south-1` region: - -{% include_cached copy-clipboard.html %} -~~~ ---bucket-path 's3://migration/data/cockroach' ---import-region 'ap-south-1' -~~~ - -{{site.data.alerts.callout_info}} -When `--import-region` is set, `IMPORT INTO` must be used for [data movement](#data-load-mode). -{{site.data.alerts.end}} - -Connect to an Azure Blob Storage container with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}?filters=azure#azure-blob-storage-implicit-authentication): - -{% include_cached copy-clipboard.html %} -~~~ ---bucket-path 'azure-blob://migration/data/cockroach' ---use-implicit-auth -~~~ - -#### Local path - -`--local-path` instructs MOLT Fetch to write intermediate files to a path within a [local file server]({% link {{site.current_cloud_version}}/use-a-local-file-server.md %}). `local-path-listen-addr` specifies the address of the local file server. For example: - -{% include_cached copy-clipboard.html %} -~~~ ---local-path /migration/data/cockroach ---local-path-listen-addr 'localhost:3000' -~~~ - -In some cases, CockroachDB will not be able to use the local address specified by `--local-path-listen-addr`. This will depend on where CockroachDB is deployed, the runtime OS, and the source dialect. - -For example, if you are migrating to CockroachDB {{ site.data.products.cloud }}, such that the {{ site.data.products.cloud }} cluster is in a different physical location than the machine running `molt fetch`, then CockroachDB cannot reach an address such as `localhost:3000`. In these situations, use `--local-path-crdb-access-addr` to specify an address for the local file server that is **publicly accessible**. For example: - -{% include_cached copy-clipboard.html %} -~~~ ---local-path /migration/data/cockroach ---local-path-listen-addr 'localhost:3000' ---local-path-crdb-access-addr '44.55.66.77:3000' -~~~ - -{{site.data.alerts.callout_success}} -[Cloud storage](#bucket-path) is often preferable to a local file server, which can require considerable disk space. -{{site.data.alerts.end}} - -#### Direct copy - -`--direct-copy` specifies that MOLT Fetch should use `COPY FROM` to move the source data directly to CockroachDB without an intermediate store: - -- Because the data is held in memory, the machine must have sufficient RAM for the data currently in flight: - - ~~~ - average size of each row * --row-batch-size * --export-concurrency * --table-concurrency - ~~~ - -- Direct copy does not support compression or [continuation](#fetch-continuation). -- The [`--use-copy`](#data-load-mode) flag is redundant with `--direct-copy`. - -### Schema and table selection - -By default, MOLT Fetch moves all data from the [`--source`](#source-and-target-databases) database to CockroachDB. Use the following flags to move a subset of data. - -`--schema-filter` specifies a range of schema objects to move to CockroachDB, formatted as a POSIX regex string. For example, to move every table in the source database's `public` schema: - -{% include_cached copy-clipboard.html %} -~~~ ---schema-filter 'public' -~~~ - -`--table-filter` and `--table-exclusion-filter` specify tables to include and exclude from the migration, respectively, formatted as POSIX regex strings. For example, to move every source table that has "user" in the table name and exclude every source table that has "temp" in the table name: - -{% include_cached copy-clipboard.html %} -~~~ ---table-filter '.*user.*' --table-exclusion-filter '.*temp.*' -~~~ - -### Selective data movement - -Use `--filter-path` to specify the path to a JSON file that defines row-level filtering for data load. This enables you to move a subset of data in a table, rather than all data in the table. To apply row-level filters during replication, use [MOLT Replicator]({% link molt/molt-replicator.md %}) with userscripts. - -{% include_cached copy-clipboard.html %} -~~~ ---filter-path 'data-filter.json' -~~~ - -The JSON file should contain one or more entries in `filters`, each with a `resource_specifier` (`schema` and `table`) and a SQL expression `expr`. For example, the following example exports only rows from `public.t1` where `v > 100`: - -~~~ json -{ - "filters": [ - { - "resource_specifier": { - "schema": "public", - "table": "t1" - }, - "expr": "v > 100" - } - ] -} -~~~ - -`expr` is case-sensitive and must be valid in your source dialect. For example, when using Oracle as the source, quote all identifiers and escape embedded quotes: - -~~~ json -{ - "filters": [ - { - "resource_specifier": { - "schema": "C##FETCHORACLEFILTERTEST", - "table": "FILTERTBL" - }, - "expr": "ABS(\"X\") > 10 AND CEIL(\"X\") < 100 AND FLOOR(\"X\") > 0 AND ROUND(\"X\", 2) < 100.00 AND TRUNC(\"X\", 0) > 0 AND MOD(\"X\", 2) = 0 AND FLOOR(\"X\" / 3) > 1" - } - ] -} -~~~ - -{{site.data.alerts.callout_info}} -If the expression references columns that are not indexed, MOLT Fetch will emit a warning like: `filter expression ‘v > 100' contains column ‘v' which is not indexed. This may lead to performance issues.` -{{site.data.alerts.end}} - -{% comment %} -#### `--filter-path` userscript for replication - -To use `--filter-path` with replication, create and save a TypeScript userscript (e.g., `filter-script.ts`). The following script ensures that only rows where `v > 100` are replicated to `defaultdb.public.t1`: - -{% include_cached copy-clipboard.html %} -~~~ ts -import * as api from "replicator@v1"; -function disp(doc, meta) { - if (Number(doc.v) > 100) { - return { "defaultdb.public.t1" : [ doc ] }; - } -} -// Always put target schema. -api.configureSource("defaultdb.public", { - deletesTo: disp, - dispatch: disp, -}); -~~~ - -Apply the userscript with the `--userscript` replication flag: - -{% include_cached copy-clipboard.html %} -~~~ ---userscript 'filter-script.ts' -~~~ -{% endcomment %} - -### Target table handling - -`--table-handling` defines how MOLT Fetch loads data on the CockroachDB tables that [match the selection](#schema-and-table-selection). - -To load the data without changing the existing data in the tables, use `none`: - -{% include_cached copy-clipboard.html %} -~~~ ---table-handling none -~~~ - -To [truncate]({% link {{site.current_cloud_version}}/truncate.md %}) tables before loading the data, use `truncate-if-exists`: - -{% include_cached copy-clipboard.html %} -~~~ ---table-handling truncate-if-exists -~~~ - -To drop existing tables and create new tables before loading the data, use `drop-on-target-and-recreate`: - -{% include_cached copy-clipboard.html %} -~~~ ---table-handling drop-on-target-and-recreate -~~~ - -When using the `drop-on-target-and-recreate` option, MOLT Fetch creates a new CockroachDB table to load the source data if one does not already exist. To guide the automatic schema creation, you can [explicitly map source types to CockroachDB types](#type-mapping). `drop-on-target-and-recreate` does **not** create indexes or constraints other than [`PRIMARY KEY`]({% link {{site.current_cloud_version}}/primary-key.md %}) and [`NOT NULL`]({% link {{site.current_cloud_version}}/not-null.md %}). - -#### Mismatch handling - -If either [`none`](#target-table-handling) or [`truncate-if-exists`](#target-table-handling) is set, `molt fetch` loads data into the existing tables on the target CockroachDB database. If the target schema mismatches the source schema, `molt fetch` will exit early in certain cases, and will need to be re-run from the beginning. For details, refer to [Fetch exits early due to mismatches](#fetch-exits-early-due-to-mismatches). - -{{site.data.alerts.callout_info}} -This does not apply when [`drop-on-target-and-recreate`](#target-table-handling) is specified, since this option automatically creates a compatible CockroachDB schema. -{{site.data.alerts.end}} - -#### Skip primary key matching - -`--skip-pk-check` removes the [requirement that source and target tables share matching primary keys](#fetch-exits-early-due-to-mismatches) for data load. When this flag is set: - -- The data load proceeds even if the source or target table lacks a primary key, or if their primary key columns do not match. -- [Table sharding](#table-sharding) is disabled. Each table is exported in a single batch within one shard, bypassing `--export-concurrency` and `--row-batch-size`. As a result, memory usage and execution time may increase due to full table scans. -- If the source table contains duplicate rows but the target has [`PRIMARY KEY`]({% link {{ site.current_cloud_version }}/primary-key.md %}) or [`UNIQUE`]({% link {{ site.current_cloud_version }}/unique.md %}) constraints, duplicate rows are deduplicated during import. - -When `--skip-pk-check` is set, all tables are treated as if they lack a primary key, and are thus exported in a single unsharded batch. To avoid performance issues, use this flag with `--table-filter` to target only tables **without** a primary key. - -For example: - -{% include_cached copy-clipboard.html %} -~~~ shell -molt fetch \ - --mode data-load \ - --table-filter 'nopktbl' \ - --skip-pk-check -~~~ - -Example log output when `--skip-pk-check` is enabled: - -~~~json -{"level":"info","message":"sharding is skipped for table public.nopktbl - flag skip-pk-check is specified and thus no PK for source table is specified"} -~~~ - -#### Type mapping - -If [`drop-on-target-and-recreate`](#target-table-handling) is set, MOLT Fetch automatically creates a CockroachDB schema that is compatible with the source data. The column types are determined as follows: - -- PostgreSQL types are mapped to existing CockroachDB [types]({% link {{site.current_cloud_version}}/data-types.md %}) that have the same [`OID`]({% link {{site.current_cloud_version}}/oid.md %}). -- The following MySQL types are mapped to corresponding CockroachDB types: - - | MySQL type | CockroachDB type | Notes | - |-----------------------------------------------------|-------------------------------------------------------------------------------------------|--------------------------------------------------------------| - | `CHAR`, `CHARACTER`, `VARCHAR`, `NCHAR`, `NVARCHAR` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | - | `TINYTEXT`, `TEXT`, `MEDIUMTEXT`, `LONGTEXT` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | - | `GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | - | `LINESTRING` | [`LINESTRING`]({% link {{site.current_cloud_version}}/linestring.md %}) | Spatial type (PostGIS-style) | - | `POINT` | [`POINT`]({% link {{site.current_cloud_version}}/point.md %}) | Spatial type (PostGIS-style) | - | `POLYGON` | [`POLYGON`]({% link {{site.current_cloud_version}}/polygon.md %}) | Spatial type (PostGIS-style) | - | `MULTIPOINT` | [`MULTIPOINT`]({% link {{site.current_cloud_version}}/multipoint.md %}) | Spatial type (PostGIS-style) | - | `MULTILINESTRING` | [`MULTILINESTRING`]({% link {{site.current_cloud_version}}/multilinestring.md %}) | Spatial type (PostGIS-style) | - | `MULTIPOLYGON` | [`MULTIPOLYGON`]({% link {{site.current_cloud_version}}/multipolygon.md %}) | Spatial type (PostGIS-style) | - | `GEOMETRYCOLLECTION`, `GEOMCOLLECTION` | [`GEOMETRYCOLLECTION`]({% link {{site.current_cloud_version}}/geometrycollection.md %}) | Spatial type (PostGIS-style) | - | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | - | `TINYINT`, `INT1` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | - | `BLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `SMALLINT`, `INT2` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | - | `MEDIUMINT`, `INT`, `INTEGER`, `INT4` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | - | `BIGINT`, `INT8` | [`INT`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | - | `FLOAT` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | - | `DOUBLE` | [`FLOAT`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | - | `DECIMAL`, `NUMERIC`, `REAL` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | - | `BINARY`, `VARBINARY` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `DATETIME` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time (no time zone) | - | `TIMESTAMP` | [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time with time zone | - | `TIME` | [`TIME`]({% link {{site.current_cloud_version}}/time.md %}) | Time of day (no date) | - | `BIT` | [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) | Variable-length bit array | - | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | - | `TINYBLOB`, `MEDIUMBLOB`, `LONGBLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `BOOL`, `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | - -- The following Oracle types are mapped to CockroachDB types: - - | Oracle type(s) | CockroachDB type | Notes | - |---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| - | `NCHAR`, `CHAR`, `CHARACTER` | [`CHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`CHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Fixed-length character; falls back to unbounded if length not specified | - | `VARCHAR`, `VARCHAR2`, `NVARCHAR2` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | - | `STRING` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | - | `SMALLINT` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | - | `INTEGER`, `INT`, `SIMPLE_INTEGER` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | - | `LONG` | [`INT8`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | - | `FLOAT`, `BINARY_FLOAT`, `REAL` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | - | `DOUBLE`, `BINARY_DOUBLE` | [`FLOAT8`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | - | `DEC`, `NUMBER`, `DECIMAL`, `NUMERIC` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %})(p, s) or [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | - | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | - | `BLOB`, `RAW`, `LONG RAW` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | - | `CLOB`, `NCLOB` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as large text | - | `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | - | `TIMESTAMP` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) or [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | If `WITH TIME ZONE` → `TIMESTAMPTZ`, else `TIMESTAMP` | - | `ROWID`, `UROWID` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as opaque identifier | - | `SDO_GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | - | `XMLTYPE` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Stored as text | - -- To override the default mappings for automatic schema creation, you can map source to target CockroachDB types explicitly. These are defined in the JSON file indicated by the `--type-map-file` flag. The allowable custom mappings are valid CockroachDB aliases, casts, and the following mappings specific to MOLT Fetch and [Verify]({% link molt/molt-verify.md %}): - - - [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) <> [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) - - [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) <> [`UUID`]({% link {{site.current_cloud_version}}/uuid.md %}) - - [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) <> [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) - - [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) - - [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) <> [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) - - [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) - - [`INET`]({% link {{site.current_cloud_version}}/inet.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) - -`--type-map-file` specifies the path to the JSON file containing the explicit type mappings. For example: - -{% include_cached copy-clipboard.html %} -~~~ ---type-map-file 'type-mappings.json' -~~~ - -The following JSON example defines two type mappings: - -~~~ json - [ - { - "table": "public.t1", - "column_type_map": [ - { - "column": "*", - "source_type": "int", - "crdb_type": "INT2" - }, - { - "column": "name", - "source_type": "varbit", - "crdb_type": "string" - } - ] - } -] -~~~ - -- `table` specifies the table that will use the custom type mappings in `column_type_map`. The value is written as `{schema}.{table}`. -- `column` specifies the column that will use the custom type mapping. If `*` is specified, then all columns in the `table` with the matching `source_type` are converted. -- `source_type` specifies the source type to be mapped. -- `crdb_type` specifies the target CockroachDB [type]({% link {{ site.current_cloud_version }}/data-types.md %}) to be mapped. - -### Transformations - -You can define transformation rules to be performed on the target schema during the fetch task. These can be used to: - -- Map [computed columns]({% link {{ site.current_cloud_version }}/computed-columns.md %}) to a target schema. -- Map [partitioned tables]({% link {{ site.current_cloud_version }}/partitioning.md %}) to a single target table. -- Rename tables on the target schema. - -Transformation rules are defined in the JSON file indicated by the `--transformations-file` flag. For example: - -{% include_cached copy-clipboard.html %} -~~~ ---transformations-file 'transformation-rules.json' -~~~ - -The following JSON example defines two transformation rules: - -~~~ json -{ - "transforms": [ - { - "id": 1, - "resource_specifier": { - "schema": ".*", - "table": ".*" - }, - "column_exclusion_opts": { - "add_computed_def": true, - "column": "^age$" - } - }, - { - "id": 2, - "resource_specifier": { - "schema": "public", - "table": "charges_part.*" - }, - "table_rename_opts": { - "value": "charges" - } - } - ] -} -~~~ - -- `resource_specifier` configures the following options for transformation rules: - - `schema` specifies the schemas to be affected by the transformation rule, formatted as a POSIX regex string. - - `table` specifies the tables to be affected by the transformation rule, formatted as a POSIX regex string. -- `column_exclusion_opts` configures the following options for column exclusions and computed columns: - - `column` specifies source columns to exclude from being mapped to regular columns on the target schema. It is formatted as a POSIX regex string. - - `add_computed_def`, when set to `true`, specifies that each matching `column` should be mapped to a [computed column]({% link {{ site.current_cloud_version }}/computed-columns.md %}) on the target schema. Instead of being moved from the source, the column data is generated on the target using [`ALTER TABLE ... ADD COLUMN`]({% link {{ site.current_cloud_version }}/alter-table.md %}#add-column) and the computed column definition from the source schema. This assumes that all matching columns are computed columns on the source. - {{site.data.alerts.callout_danger}} - Columns that match the `column` regex will **not** be moved to CockroachDB if `add_computed_def` is omitted or set to `false` (default), or if a matching column is a non-computed column. - {{site.data.alerts.end}} -- `table_rename_opts` configures the following option for table renaming: - - `value` specifies the table name to which the matching `resource_specifier` is mapped. If only one source table matches `resource_specifier`, it is renamed to `table_rename_opts.value` on the target. If more than one table matches `resource_specifier` (i.e., an n-to-1 mapping), the fetch task assumes that all matching tables are [partitioned tables]({% link {{ site.current_cloud_version }}/partitioning.md %}) with the same schema, and moves their data to a table named `table_rename_opts.value` on the target. Otherwise, the task will error. - - Additionally, in an n-to-1 mapping situation: - - - Specify [`--use-copy`](#data-load-mode) or [`--direct-copy`](#direct-copy) for data movement. This is because the data from the source tables is loaded concurrently into the target table. - - Create the target table schema manually, and do **not** use [`--table-handling drop-on-target-and-recreate`](#target-table-handling) for target table handling. - -The preceding JSON example therefore defines two rules: - -- Rule `1` maps all source `age` columns on the source database to [computed columns]({% link {{ site.current_cloud_version }}/computed-columns.md %}) on CockroachDB. This assumes that all matching `age` columns are defined as computed columns on the source. -- Rule `2` maps all table names with prefix `charges_part` from the source database to a single `charges` table on CockroachDB (i.e., an n-to-1 mapping). This assumes that all matching `charges_part.*` tables have the same schema. - -Each rule is applied in the order it is defined. If two rules overlap, the later rule will override the earlier rule. - -To verify that the logging shows that the computed columns are being created: - -When running `molt fetch`, set `--logging debug` and look for `ALTER TABLE ... ADD COLUMN` statements with the `STORED` or `VIRTUAL` keywords in the log output: - -~~~ json -{"level":"debug","time":"2024-07-22T12:01:51-04:00","message":"running: ALTER TABLE IF EXISTS public.computed ADD COLUMN computed_col INT8 NOT NULL AS ((col1 + col2)) STORED"} -~~~ - -After running `molt fetch`, issue a `SHOW CREATE TABLE` statement on CockroachDB: - -{% include_cached copy-clipboard.html %} -~~~ sql -SHOW CREATE TABLE computed; -~~~ - -~~~ - table_name | create_statement --------------+------------------------------------------------------------------- - computed | CREATE TABLE public.computed ( - ... - | computed_col INT8 NOT NULL AS (col1 + col2) STORED - | ) -~~~ - -### Fetch continuation - -If MOLT Fetch fails while loading data into CockroachDB from intermediate files, it exits with an error message, fetch ID, and [continuation token](#list-active-continuation-tokens) for each table that failed to load on the target database. You can use this information to continue the task from the *continuation point* where it was interrupted. - -Continuation is only possible under the following conditions: - -- All data has been exported from the source database into intermediate files on [cloud](#bucket-path) or [local storage](#local-path). -- The *initial load* of source data into the target CockroachDB database is incomplete. - -{{site.data.alerts.callout_info}} -Only one fetch ID and set of continuation tokens, each token corresponding to a table, are active at any time. See [List active continuation tokens](#list-active-continuation-tokens). -{{site.data.alerts.end}} - -To retry all data starting from the continuation point, reissue the `molt fetch` command and include the `--fetch-id`. - -{% include_cached copy-clipboard.html %} -~~~ ---fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 -~~~ - -To retry a specific table that failed, include both `--fetch-id` and `--continuation-token`. The latter flag specifies a token string that corresponds to a specific table on the source database. A continuation token is written in the `molt fetch` output for each failed table. If the fetch task encounters a subsequent error, it generates a new token for each failed table. See [List active continuation tokens](#list-active-continuation-tokens). - -{{site.data.alerts.callout_info}} -This will retry only the table that corresponds to the continuation token. If the fetch task succeeds, there may still be source data that is not yet loaded into CockroachDB. -{{site.data.alerts.end}} - -{% include_cached copy-clipboard.html %} -~~~ ---fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 ---continuation-token 011762e5-6f70-43f8-8e15-58b4de10a007 -~~~ - -To retry all data starting from a specific file, include both `--fetch-id` and `--continuation-file-name`. The latter flag specifies the filename of an intermediate file in [cloud or local storage](#data-path). All filenames are prepended with `part_` and have the `.csv.gz` or `.csv` extension, depending on compression type (gzip by default). For example: - -{% include_cached copy-clipboard.html %} -~~~ ---fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 ---continuation-file-name part_00000003.csv.gz -~~~ - -{{site.data.alerts.callout_info}} -Continuation is not possible when using [direct copy](#direct-copy). -{{site.data.alerts.end}} - -#### List active continuation tokens - -To view all active continuation tokens, issue a `molt fetch tokens list` command along with `--conn-string`, which specifies the [connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url) for the target CockroachDB database. For example: - -{% include_cached copy-clipboard.html %} -~~~ shell -molt fetch tokens list \ ---conn-string 'postgres://root@localhost:26257/defaultdb?sslmode=verify-full' -~~~ - -~~~ -+--------------------------------------+--------------------------------------+------------------+----------------------+ -| ID | FETCH ID | TABLE NAME | FILE NAME | -+--------------------------------------+--------------------------------------+------------------+----------------------+ -| f6f0284c-d9c1-43c9-8fde-af609d0dbd82 | 66443597-5689-4df3-a7b9-9fc5e27180eb | public.employees | part_00000001.csv.gz | -+--------------------------------------+--------------------------------------+------------------+----------------------+ -Continuation Tokens. -~~~ - -### CDC cursor - -A change data capture (CDC) cursor is written to the output as `cdc_cursor` at the beginning and end of the fetch task. For example: - -~~~ json -{"level":"info","type":"summary","fetch_id":"735a4fe0-c478-4de7-a342-cfa9738783dc","num_tables":1,"tables":["public.employees"],"cdc_cursor":"b7f9e0fa-2753-1e1f-5d9b-2402ac810003:3-21","net_duration_ms":4879.890041,"net_duration":"000h 00m 04s","time":"2024-03-18T12:37:02-04:00","message":"fetch complete"} -~~~ - -Use the `cdc_cursor` value as the checkpoint for MySQL or Oracle replication with [MOLT Replicator]({% link molt/molt-replicator.md %}#replication-checkpoints). - -You can also use the `cdc_cursor` value with an external change data capture (CDC) tool to continuously replicate subsequent changes from the source database to CockroachDB. - -## See also - -- X \ No newline at end of file From d1196eb520951365f6011517df31cf09865f1dc2 Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Fri, 12 Dec 2025 10:57:14 -0500 Subject: [PATCH 06/15] more progress on considerations: granularity, rollback, replication --- .../molt/migration-considerations-phases.md | 25 +++ .../migration-considerations-replication.md | 104 ++++++++- .../molt/migration-considerations-rollback.md | 115 +++++++++- ...migration-considerations-transformation.md | 147 ++++++++++++- .../migration-considerations-validation.md | 202 +++++++++++++++++- src/current/molt/migration-considerations.md | 12 +- 6 files changed, 591 insertions(+), 14 deletions(-) diff --git a/src/current/molt/migration-considerations-phases.md b/src/current/molt/migration-considerations-phases.md index 46c36907491..e477bb8680e 100644 --- a/src/current/molt/migration-considerations-phases.md +++ b/src/current/molt/migration-considerations-phases.md @@ -44,6 +44,31 @@ Tips for picking slices: | Timeline | Shorter migration time | Longer calendar time but safer path | | Best for | Small/medium datasets, simple integrations | Larger datasets, data with natural partitions or multiple tenants, risk-averse migrations | +## Decision framework + +Use these questions to guide your approach: + +**How large is your dataset and how long will a full migration take?** +If you can migrate the entire dataset within an acceptable downtime window, all-at-once is simpler. If the migration would take hours or days, phased migrations reduce the risk and downtime per phase. + +**Does your data have natural partitions?** +If you can clearly partition by tenant, service, region, or table with minimal cross-dependencies, phased migration is well-suited. If your data is highly interconnected with complex foreign-key relationships, all-at-once may be easier. + +**What is your risk tolerance?** +If a migration failure affecting the entire system is unacceptable, phased migration limits the blast radius. If you can afford to roll back the entire migration in case of issues, all-at-once is faster. + +**How much downtime can you afford per cutover?** +Phased migrations spread downtime across multiple smaller windows, each affecting only a subset of users or services. All-at-once requires a single larger window affecting everyone. + +**What is your team's capacity for orchestration?** +Phased migrations require repeated cycles of migration, validation, and cutover, with careful coordination of routing and monitoring. All-at-once is a single coordinated event. + +**Do you need to validate incrementally?** +If you want fast feedback loops and the ability to adjust your migration strategy based on early phases, phased migration provides incremental validation. All-at-once validates everything once at the end. + +**Can you route traffic selectively?** +Phased migrations require the ability to route specific tenants, services, or regions to CockroachDB while others remain on the source. If your application can't easily support this, all-at-once may be necessary. + ## MOLT toolkit support Phased and unphased migrations are both supported natively by MOLT. diff --git a/src/current/molt/migration-considerations-replication.md b/src/current/molt/migration-considerations-replication.md index e90dc40e996..193c4733898 100644 --- a/src/current/molt/migration-considerations-replication.md +++ b/src/current/molt/migration-considerations-replication.md @@ -1,8 +1,108 @@ --- title: Continuous Replication -summary: Learn about continuous replication, and how it might be useful for a data migration. +summary: Learn when and how to use continuous replication during data migration to minimize downtime and keep the target synchronized with the source. toc: true docs_area: migrate --- -TBD \ No newline at end of file +Continuous replication can be used during a migration to keep a CockroachDB target cluster synchronized with a live source database. This is often used to minimize downtime at cutover. It can complement bulk data loading or be used independently. + +This page explains when to choose continuous replication, how to combine it with bulk loading, and how to use MOLT tools effectively for each approach. + +In general: + +- Choose to **bulk load only** if you can schedule a downtime window long enough to complete the entire data load and do not need to capture ongoing changes during migration. + +- Choose a **hybrid approach (bulk load + continuous replication)** when you need to minimize downtime and keep the target synchronized with ongoing source database changes until cutover. + +- You can choose **continuous replication only** for tables with transient data, or in other contexts where you only need to capture ongoing changes and are not concerned with migrating a large initial dataset. + +## Permissible downtime + +Downtime is the primary factor to consider in determining your migration's approach to continuous replication. + +If your migration can accommodate a window of **planned downtime** that's made known to your users in advance, a bulk load approach is simpler. A pure bulk load approach is well-suited for test or pre-production refreshes, or with migrations that can successfully move data within a planned downtime window. + +If your migration needs to **minimize downtime**, you will likely need to keep the source database live for as long as possible, continuing to allow write traffic to the source until cutover. In this case, an initial bulk load will need to be followed by a replication period, during which you stream incremental changes from the source to the target CockroachDB cluster. This is ideal for large datasets that are impractical to move within a narrow downtime window, or when you need validation time with a live, continuously synced target before switching traffic. The final downtime is minimized to a brief pause to let replication drain before switching traffic, with the pause length driven by write volume and observed replication lag. + +If you're migrating your data [in mulitple phases]({% link molt/migration-considerations-phases.md %}), consider the fact that each phase can have its own separate downtime window and cutover, and that migrating in phases can reduce the length of each individual downtime window. + +## Tradeoffs + +| | Bulk load only | Hybrid (bulk + replication) | Continuous replication only | +|---|---|---|---| +| **Downtime** | Requires full downtime for entire load | Minimal final downtime (brief pause to drain) | Minimal if resuming from checkpoint | +| **Performance** | Fastest overall if window allows | Spreads work: bulk moves mass, replication handles ongoing changes | Depends on catch-up time from checkpoint | +| **Complexity** | Fewer moving parts, simpler orchestration | Requires replication infrastructure and monitoring | Requires checkpoint management | +| **Risk management** | Full commit at once; rollback more disruptive | Supports failback flows for rollback options | Lower risk when resuming known state | +| **Cutover** | Traffic off until entire load completes | Traffic paused briefly while replication drains | Brief pause to verify sync | +| **Timeline** | Shortest migration time if downtime permits | Longer preparation but safer path | Short catch-up phase | +| **Best for** | Simple moves, test environments, scheduled maintenance | Production migrations, large datasets, high availability requirements | Recovery scenarios, post-load sync | + +## Decision framework + +Use these questions to guide your approach: + +**What downtime can you tolerate?** +If you can't guarantee a window long enough for the full load, favor the hybrid approach to minimize downtime at cutover. + +**How large is the dataset and how fast can you bulk-load it?** +If load time fits inside downtime, bulk-only is simplest. Otherwise, hybrid. + +**How active is the source (write rate and burstiness)?** +Higher write rates mean a longer final drain; this pushes you toward hybrid with close monitoring of replication lag before cutover. + +**Do you need a safety net?** +If rollback is a requirement, design for replication and failback pathways, which the MOLT flow supports. + +**How much validation do you require pre-cutover?** +Hybrid gives you time to validate a live, synchronized target before switching traffic. + +## MOLT toolkit support + +The MOLT toolkit provides two complementary tools for data migration: [MOLT Fetch]({% link molt/molt-fetch.md %}) for bulk loading the initial dataset, and [MOLT Replicator]({% link molt/molt-replicator.md %}) for continuous replication. These tools work independently or together depending on your chosen replication approach. + +### Bulk load only + +Use MOLT Fetch to export and load data to CockroachDB. + +For pure bulk migrations, set the `--ignore-replication-check` flag to skip gathering replication checkpoints. This simplifies the workflow when you don't need to track change positions for subsequent replication. + +MOLT Fetch supports both `IMPORT INTO` (default, for highest throughput with offline tables) and `COPY FROM` (for online tables) loading methods. Because a pure bulk load approach will likely involve substantial application downtime, you may benefit from using `IMPORT INTO`. In this case, do not use the `--use-copy` flag. Learn more about Fetch's [data load modes]({% link molt/molt-fetch.md %}#data-load-mode). + +A migration that does not utilize continuous replication would not need to use MOLT Replicator. + + + +### Hybrid (bulk load + continuous replication) + +Use MOLT Fetch to export and load the inital dataset to CockroachDB. Then start MOLT Replicator to begin streaming changes from the source database to CockroachDB. + +When you run MOLT Fetch without `--ignore-replication-check`, it emits a checkpoint value that marks the point in time when the bulk load snapshot was taken. After MOLT Fetch completes, the checkpoint is stored in the target database. MOLT Replicator then uses this checkpoint to begin streaming changes from exactly that point, ensuring no data is missed between the bulk load and continuous replication. Learn more about [replication checkpoints]({% link molt/molt-replicator.md %}#replication-checkpoints). + +MOLT Fetch supports both `IMPORT INTO` (default, for highest throughput with offline tables) and `COPY FROM` (for online tables) loading methods. Because a hybrid approach will likely aim to have less downtime, you may need to use `COPY FROM` if your tables remain online. In this case, use the `--use-copy` flag. Learn more about Fetch's [data load modes]({% link molt/molt-fetch.md %}#data-load-mode). + +MOLT Replicator replicates full tables by default. If you choose to combine continuous replication with a [phased migration]({% link molt/migration-considerations-phases.md %}), you will either need to select phases that include whole tables, or else use [userscripts]({% link molt/molt-replicator.md %}#flags) to select rows to replicate. + +MOLT Replicator can be stopped after cutover, or it can remain online to continue streaming changes indefinitely. + +### Continuous replication only + +If you're only interested in capturing recent changes, skip MOLT Fetch entirely and just use MOLT Replicator. + +## Example sequences + +## See also + +- [Migration Overview]({% link molt/migration-overview.md %}) +- [Migration Considerations]({% link molt/migration-considerations.md %}) +- [Migration Granularity]({% link molt/migration-considerations-phases.md %}) +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [MOLT Replicator]({% link molt/molt-replicator.md %}) +- [MOLT Verify]({% link molt/molt-verify.md %}) diff --git a/src/current/molt/migration-considerations-rollback.md b/src/current/molt/migration-considerations-rollback.md index da38fa50b86..3ce21ad1838 100644 --- a/src/current/molt/migration-considerations-rollback.md +++ b/src/current/molt/migration-considerations-rollback.md @@ -1,8 +1,119 @@ --- title: Rollback Plan -summary: Learn why it might be useful to have a rollback plan in case something goes wrong in the middle of a migration. +summary: Learn how to plan rollback options to limit risk and preserve data integrity during migration. toc: true docs_area: migrate --- -TBD \ No newline at end of file +A rollback plan defines how you will undo or recover from a failed migration. A clear rollback strategy limits risk during migration, minimizes business impact, and preserves data integrity so that you can retry the migration with confidence. + +This page explains four common rollback options, their trade-offs, and how the MOLT toolkit supports each approach. + +In general: + +- **Manual reconciliation** is sufficient for low-risk systems or low-complexity migrations where automated rollback is not necessary. + +- Utilize **failback replication** to maintain synchronization between the CockroachDB cluster and the original source database after cutover to CockroachDB. + +- Utilize **bidirectional replication** (simultaneous forward and failback replication) to maximize database synchronization without requiring app changes, accepting the operational overhead of running two replication streams. + +- Choose a **dual-write** strategy for the fastest rollback with minimal orchestration, accepting higher application complexity during the trial window. + +## Why plan for rollback + +Many things can go wrong during a migration. Performance issues may surface under production load that didn't appear in testing. Application compatibility problems might emerge that require additional code changes. Data discrepancies could be discovered that necessitate investigation and remediation. In any of these scenarios, the ability to quickly and safely return to the source database is critical to minimizing business impact. + +Your rollback strategy should align with your migration's risk profile, downtime tolerance, and operational capabilities. High-stakes production migrations typically require faster rollback paths with minimal data loss, while test environments or low-traffic systems can tolerate simpler manual approaches. + +### Failback replication + +[Continuous (forward) replication]({% link molt/migration-considerations-replication.md %}), which serves to minimize downtime windows, keeps two databases in sync by replicating changes from the source to the target. In contrast, **failback replication** synchronizes data in the opposite direction, from the target back to the source. + +Failback replication is useful for rollback because it keeps the source database synchronized with writes that occur on CockroachDB after cutover. If problems emerge during your trial period and you need to roll back, the source database already has all the data that was written to CockroachDB. This enables a quick rollback without data loss. + +Failback and forward replication can be used simultaneously (**bidirectional replication**). This is especially useful if the source and the target databases can receive simultaneous, but disparate write traffic. In that case, bidirectional replication is necessary to ensure that both databases stay in sync. It's also useful if downtime windows are long or if cutover is gradual, increasing the likelihood that the two databases receive independent writes. + +### Dual-write + +Failback replication requires an external replication system (like [MOLT Replicator]({% link molt/molt-replicator.md %})) to keep two databases synchronized. Alternatively, you can modify the application code itself to enable **dual-writes**, wherein the application writes to both the source database and CockroachDB during a trial window. If rollback is needed, you can then redirect traffic to the source without additional data movement. + +This enables faster rollback, but increases application complexity as you need to manage two write paths. + +## Tradeoffs + +| | Manual reconciliation | Failback replication (on-demand) | Bidirectional replication | Dual-write | +|---|---|---|---|---| +| **Rollback speed (RTO)** | Slow | Moderate | Fast | Fast | +| **Data loss risk (RPO)** | Medium-High | Low | Low | Low-Medium (app-dependent) | +| **Synchronization mechanism** | None (backups/scripts) | Activate failback when needed | Continuous forward + failback | Application writes to both | +| **Application changes** | None | None | None | Required | +| **Operational complexity** | Low (tooling), High (manual) | Medium (runbook activation) | High (two replication streams) | High (app layer) | +| **Overhead during trial** | Low | Low-Medium | High (two replication streams) | Medium (two write paths) | +| **Best for** | Low-risk systems, simple migrations | Moderate RTO tolerance, lower ongoing cost | Strict RTO/RPO, long or complex cutovers | Short trials, resilient app teams | + +## Decision framework + +Use these questions to guide your rollback strategy: + +**What is your rollback RTO/RPO requirement?** +If rollback must be immediate with near-zero data loss, prefer dual-write or bidirectional replication. For moderate RTO, reverse unidirectional suffices. For generous RTO and low risk, manual may be acceptable. + +**What is your write topology and conflict risk?** +If multiple writers can touch the same keys, avoid bidirectional replication unless you have conflict avoidance (partitioning by tenant/service) or deterministic conflict resolution. + +**What is your operational maturity?** +Bidirectional replication requires monitoring, alerting, and practiced runbooks. Reverse unidirectional requires a tested activation runbook. Dual-write requires app-layer resiliency and observability across write paths. + +**Can you modify the application?** +If app changes are expensive or risky, prefer database-level options (reverse unidirectional or bidirectional) over dual-write. + +**What are your source and target capabilities?** +Ensure your source supports required CDC/replication characteristics and retention for the migration window. Verify that CockroachDB changefeeds can deliver necessary backfill for failback in your environment. + +## MOLT toolkit support + +The MOLT toolkit provides tools that enable different rollback strategies. + +### MOLT Replicator (forward and failback) + +[MOLT Replicator]({% link molt/molt-replicator.md %}) streams ongoing changes between databases: + +- **Forward replication**: Streams changes from PostgreSQL, MySQL, or Oracle to CockroachDB for minimal-downtime migrations. +- **Failback**: Streams changes from CockroachDB back to the source using a CockroachDB changefeed to preserve rollback options. + +**Key capabilities for rollback:** + +- **Staging database**: Persists checkpoints and metadata in a CockroachDB staging schema (`--stagingSchema`, created with `--stagingCreateSchema`). +- **Connections**: `--targetConn` points to the destination for applied changes; `--stagingConn` points to the CockroachDB staging database. +- **Metrics**: `--metricsAddr` exposes a Prometheus endpoint for replication lag, throughput, and applied mutations. +- **Webhook endpoint**: `--bindAddr` receives changefeed events during failback. +- **Prerequisites**: For self-hosted clusters, enable rangefeeds to support changefeeds in failback workflows. + +**Usage by rollback option:** + +- **Dual-write**: Use Replicator for forward replication into CockroachDB; keep failback tooling pre-validated on standby. +- **Bidirectional**: Run forward replication and failback concurrently during trial; monitor both metrics endpoints. +- **Reverse unidirectional**: Before cutover, confirm you can start failback quickly with known flags; at rollback time, follow the failback runbook to start Replicator and create the changefeed. +- **Manual**: Not applicable; no automated replication during rollback. + +### MOLT Fetch + +[MOLT Fetch]({% link molt/molt-fetch.md %}) performs initial one-time data load and pairs with Replicator for minimal-downtime migrations. Rollback choice primarily affects Replicator usage after initial load rather than Fetch. + +### MOLT Verify + +[MOLT Verify]({% link molt/molt-verify.md %}) compares schema and row-level data between source and CockroachDB to surface discrepancies: + +- **Dual-write or bidirectional**: Run Verify to catch drift during the coexistence window. +- **Reverse unidirectional or manual**: Run before activating rollback to estimate catch-up effort; run again after failback or manual repair to confirm consistency. + +## See also + +- [Migration Overview]({% link molt/migration-overview.md %}) +- [Migration Considerations]({% link molt/migration-considerations.md %}) +- [Continuous Replication]({% link molt/migration-considerations-replication.md %}) +- [Validation Strategy]({% link molt/migration-considerations-validation.md %}) +- [MOLT Replicator]({% link molt/molt-replicator.md %}) +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [MOLT Verify]({% link molt/molt-verify.md %}) +- [Migrate with Failback]({% link molt/migrate-failback.md %}) diff --git a/src/current/molt/migration-considerations-transformation.md b/src/current/molt/migration-considerations-transformation.md index b911679ed09..48c677c6012 100644 --- a/src/current/molt/migration-considerations-transformation.md +++ b/src/current/molt/migration-considerations-transformation.md @@ -1,8 +1,151 @@ --- title: Data Transformation Strategy -summary: Learn about the different approaches to applying data transformations during a migration. +summary: Learn about the different approaches to applying data transformations during a migration and how to choose the right strategy for your use case. toc: true docs_area: migrate --- -TBD \ No newline at end of file +Most migrations require some level of data transformation—whether schema conversion, type mapping, row filtering, or value normalization. The key decision is **where** these transformations occur: on the source database, in flight during the migration pipeline, or on the target CockroachDB cluster. Each approach has distinct trade-offs in terms of performance, operational complexity, and downtime tolerance. + +This page explains the types of transformations to expect, where they can be applied, and how these choices shape your use of MOLT tooling. + +In general: + +- Choose **source-side transformations** when you want to minimize data volume across the network, or when transformations are straightforward to express in SQL. + +- Choose **in-flight transformations** for minimal-downtime migrations where the same transformation logic must apply consistently to both the initial bulk load and continuous replication streams. + +- Choose **target-side transformations** when you want to minimize changes to the source system, or when you can leverage CockroachDB features like computed columns for convenience. + +## Common transformation types + +Most migrations require a mix of schema-level and data-level changes: + +- **Schema conversion**: Rewrite unsupported DDL and apply CockroachDB best practices using MOLT Schema Conversion Tool. +- **Type mapping**: Align source types with CockroachDB types, especially for dialect-specific types (e.g., MySQL `ENUM`). +- **Primary key strategy**: Replace source sequences or auto-increment patterns with CockroachDB-friendly IDs (UUIDs, sequences). +- **Table reshaping**: Consolidate partitioned tables, rename tables, or retarget to different schemas. +- **Column changes**: Exclude deprecated columns, or map computed columns. +- **Row filtering**: Move only a subset of rows by tenant, region, or timeframe. +- **Constraints and indexes**: Drop non-primary-key constraints and secondary indexes before bulk load for performance, then recreate after. +- **Value normalization**: Apply value transforms during replication to ensure consistent processing of bulk and streaming data. + +## Where to transform + +### Transform on the source (before export) + +Apply transformations directly on the source database before exporting data. + +**Best for:** Minimizing data volume across the network; leveraging existing source database features for filtering or aggregation. + +**Advantages:** Smallest extract sets reduce network transfer and storage; simple bulk-load path where downstream receives transformed data. + +**Disadvantages:** Adds load to source database; complex logic may be harder to express in SQL; may need to replicate transformation logic for continuous replication. + +### Transform in flight (inside the MOLT pipeline) + +Apply transformations within the migration pipeline, between source and target. + +**Best for:** Minimal-downtime migrations where the same logic must apply to both initial load and continuous replication deltas; complex transformations that benefit from code rather than SQL. + +**Advantages:** One code layer (TypeScript userscripts) for transform/filter/route logic; version-controlled and testable; separates transformation from databases. + +**Disadvantages:** Requires operating a custom code path with observability and error handling; adds CPU to migration's critical path. + +{{site.data.alerts.callout_info}} +MOLT Fetch's JSON transformations are for schema shaping (rename/merge/exclude/computed) rather than arbitrary per-value masking. Use MOLT Replicator userscripts for value-level transformations. +{{site.data.alerts.end}} + +### Transform on the target (after load or during target DDL) + +Apply transformations in CockroachDB after data has been loaded. + +**Best for:** Minimizing changes to the source system; leveraging CockroachDB-specific features. + +**Advantages:** Minimizes source changes; works well for schema reshaping with CockroachDB DDL; can leverage distributed processing. + +**Disadvantages:** Full data volume crosses the network; may require post-load processing. + +## Pairing with migration patterns + +Different migration patterns favor different transformation approaches: + +- **Planned downtime / bulk-load**: Prefer source-side filtering and target-side reshaping (computed columns, renames) to keep the pipeline straightforward. Use MOLT Fetch transformations for schema-level changes. + +- **Load-then-replicate (minimal downtime)**: Use in-flight userscripts for continuous replication to ensure consistent transformation logic across bulk and streaming loads. Source-side filtering can reduce initial volume. + +- **Continuous replication-first**: Emphasize in-flight transforms (userscripts) to ensure ongoing changes are normalized and reshaped consistently until cutover and beyond. + +## Combining approaches + +You can and often should combine approaches to meet operational requirements: + +- **Source + in flight**: Coarse-grained filtering at source to reduce volume, then complex transformations in-flight for CDC consistency. +- **Source + target**: Source-side views or staging tables for data preparation, plus target computed columns or table renames. +- **In flight + target**: Userscripts for row-level logic, plus target DDL for schema conveniences (computed columns, index recreation). + +## Tradeoffs + +| | Source | In flight | Target | +|---|---|---|---| +| **Network transfer** | Reduced (transformed data only) | Full volume crosses network | Full volume crosses network | +| **Source impact** | Adds load to source database | No source changes required | No source changes required | +| **Complexity** | SQL-based, tied to source dialect | Requires custom code and monitoring | DDL-based, CockroachDB native | +| **Downtime impact** | May require source schema changes | Independent of source/target schemas | May require post-load processing | +| **Reusability** | Logic tied to source database | Version-controlled, portable code | Tied to target database | +| **Testing** | Test with source database tools | Test userscripts independently | Test with CockroachDB tools | +| **Best for** | Volume reduction, SQL-friendly transforms | Minimal-downtime migrations, complex logic | Simple migrations, CockroachDB-native features | + +## Decision framework + +Use these questions to guide your transformation strategy: + +- **What is your downtime tolerance?** Near-zero downtime pushes you toward in-flight transforms that apply consistently to bulk and streaming loads. +- **Can your team test and maintain transformations more easily in SQL or code?** This influences whether to use source-side SQL, in-flight TypeScript userscripts, or target-side CockroachDB DDL. +- **Will transformation logic be reused post-cutover?** If you need ongoing sync or failback, prefer deterministic, version-controlled in-flight transformations. +- **How complex are the transformations?** Simple schema reshaping favors MOLT Fetch transformations or target DDL. Complex value normalization or routing favors in-flight userscripts. +- **What is your network and performance budget?** Source-side pushdown reduces volume across the wire. In-flight logic adds CPU to the pipeline. Balance throughput needs with transformation requirements. +- **Can you modify the source database?** Source-side transformations require permission and capacity to create views, staging tables, or run transformation queries. + +## MOLT toolkit support + +The MOLT toolkit provides specialized features for implementing transformations at each stage of the migration pipeline. + +### MOLT Schema Conversion Tool + +Use the [Schema Conversion Tool]() first to convert your schema and apply CockroachDB best practices. This reduces downstream transformation pressure by addressing DDL incompatibilities upfront. + +### MOLT Fetch + +[MOLT Fetch]({% link molt/molt-fetch.md %}) supports transformations during initial data load: + +- **Row filtering**: `--filter-path` specifies a JSON file with table-to-SQL-predicate mappings evaluated in the source dialect before export. Ensure filtered columns are indexed for performance. +- **Schema shaping**: `--transformations-file` defines table renames, n→1 merges (consolidate partitioned tables), and column exclusions. For n→1 merges, use `--use-copy` or `--direct-copy` and pre-create the target table. +- **Type alignment**: `--type-map-file` specifies explicit type mappings when auto-creating target tables. +- **Table lifecycle**: `--table-handling` controls whether to truncate, drop-and-recreate, or assume tables exist. + +For bulk-only flows, use `--ignore-replication-check` to skip replication checkpoint capture. + +### MOLT Replicator + +[MOLT Replicator]({% link molt/molt-replicator.md %}) uses TypeScript **userscripts** to implement in-flight transformations for continuous replication: + +- **Capabilities**: Transform or normalize values, route rows to different tables, enrich data, filter rows, merge partitioned sources. +- **Structure**: Userscripts export functions (`configureTargetTables`, `onRowUpsert`, `onRowDelete`) that process change data before commit to CockroachDB. +- **Coordination**: For hybrid migrations, run MOLT Fetch for the initial load (which emits a `cdc_cursor` checkpoint), then start MOLT Replicator with the same transformation logic to process ongoing changes from that checkpoint. +- **Staging schema**: Replicator uses a CockroachDB staging schema to store replication state and buffered mutations (`--stagingSchema` and `--stagingCreateSchema`). + +### MOLT Verify + +Use [MOLT Verify]({% link molt/molt-verify.md %}) to compare schemas and data between source and target. For deliberate differences (e.g., masked columns or changed types), focus on intended equivalence: row counts, unchanged columns, and referential integrity. Run before replication starts (optional baseline) and before final cutover. + +## See also + +- [Migration Overview]({% link molt/migration-overview.md %}) +- [Migration Considerations]({% link molt/migration-considerations.md %}) +- [Migration Granularity]({% link molt/migration-considerations-phases.md %}) +- [Continuous Replication]({% link molt/migration-considerations-replication.md %}) +- [MOLT Schema Conversion Tool]() +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [MOLT Replicator]({% link molt/molt-replicator.md %}) +- [MOLT Verify]({% link molt/molt-verify.md %}) diff --git a/src/current/molt/migration-considerations-validation.md b/src/current/molt/migration-considerations-validation.md index dc5d50e7e39..f42513860db 100644 --- a/src/current/molt/migration-considerations-validation.md +++ b/src/current/molt/migration-considerations-validation.md @@ -1,8 +1,206 @@ --- title: Validation Strategy -summary: Learn what different validation strategies can be used when migrating data. +summary: Learn when and how to validate data during migration to ensure correctness, completeness, and consistency. toc: true docs_area: migrate --- -TBD \ No newline at end of file +A successful migration to CockroachDB requires a clear validation strategy that proves the target holds the right data, in the right shape, and behaves correctly for your application. Validation is not a single step—it occurs at multiple checkpoints throughout the migration process, with increasing rigor as you approach cutover. + +This page explains what to validate, when to validate during different migration flows, and how these choices shape your use of MOLT tooling. + +In general: + +- Validate **early and often** to catch issues when they're easier to fix—during design, after initial load, throughout replication, and before cutover. + +- Align validation scope and timing with your **migration pattern**: bulk load requires full validation during downtime; load-then-replicate needs live-aware validation; phased migrations validate each subset independently. + +- Combine **automated data comparison** (MOLT Verify) with **application-level testing** to ensure both row-level correctness and end-to-end behavioral equivalence. + +## What to validate + +Validation occurs in layers, from structural to behavioral: + +### Schema parity + +Verify that table structure, column names, types, nullability, and constraints match between source and target. This catches DDL conversion issues early. + +### Row-level correctness + +Confirm that no rows are missing or extraneous, and that row values match. This is the core of data integrity validation. + +### Type and collation compatibility + +Account for intentional differences: type conversions (e.g., `AUTO_INCREMENT` to `UUID`), collation differences on `STRING` primary keys, and unsupported comparisons (e.g., geospatial types). Plan how to handle these before running validation. + +### Application behavior + +Validate critical queries and transactions using shadow traffic or targeted tests on a production-sized CockroachDB cluster. This catches semantic differences that row-by-row comparison cannot reveal, such as isolation-level semantics or query plan changes. + +## When to validate + +Use natural checkpoints in your migration flow, increasing rigor as you approach cutover: + +### Pre-migration (design and dry-run) + +Validate converted schema and resolve type mapping issues. Run a dry-run migration on test data and begin query validation to catch behavioral differences early. + +### After initial data load + +Run comprehensive validation to confirm schema and row-level parity before re-adding constraints and indexes that were dropped to accelerate load. This is your first full data integrity checkpoint. + +### During continuous replication + +If using replication, run validation periodically to ensure the target converges with the source. Use live-aware validation to reduce false positives from in-flight changes. This gives you confidence that replication is working correctly. + +### Pre-cutover gate + +Once replication has drained (no backlog), run final validation on the complete cutover scope and verify critical application queries. This is your go/no-go decision point. + +### Post-cutover confidence checks + +After traffic moves to CockroachDB, run targeted validation on critical tables and application smoke tests to confirm steady state. + +## How validation changes by migration pattern + +Different migration patterns require different validation approaches: + +### Bulk load with planned downtime + +Run full-schema and full-table validation on all in-scope tables immediately after bulk load. If you dropped constraints and indexes for performance, validate before re-adding them, then re-run on critical tables afterward. + +**Characteristics:** Strongest guarantees at a single point in time; requires downtime sufficient for load plus validation. + +### Load-then-replicate (minimal downtime) + +Validate after initial load, then use live-aware validation during replication to monitor convergence. Wait for replication to drain, then run comprehensive final validation immediately before cutover. + +**Characteristics:** Short downtime but longer total calendar time; must coordinate replication lag, GC retention, and validation runtime. + +### Phased migration + +Validate each phase independently using schema and table filters. Each phase becomes its own mini-cutover with phase-specific validation gates. + +**Characteristics:** Smaller blast radius and faster feedback per phase; requires orchestrating multiple validation cycles. + +## Tradeoffs + +| | Bulk load | Load-then-replicate | Phased | +|---|---|---|---| +| **Validation scope** | Full dataset at once | Full initial + continuous monitoring | Subset per phase | +| **Timing** | During downtime window | After load + during replication + pre-cutover | Repeated per phase | +| **Complexity** | Single comprehensive run | Multiple checkpoints with live awareness | Multiple scoped runs | +| **Downtime impact** | Extends downtime window | Minimal impact on downtime | Minimal per phase | +| **Confidence level** | Strongest single-point guarantee | Continuous convergence verification | Incremental confidence | +| **Best for** | Scheduled maintenance, smaller datasets | Production migrations, large datasets | Risk-averse migrations, natural data partitions | + +## Decision framework + +Use these questions to guide your validation strategy: + +**What is your data volume and validation timeline?** +Larger datasets require more validation time. Consider concurrency tuning, phased validation, or off-peak runs to fit within windows. + +**Is the source database active during migration?** +Active sources require live-aware validation and continuous monitoring during replication. Plan for replication drain before final validation. + +**Are there intentional schema or type differences?** +Expect validation to flag type conversions and collation differences. Decide upfront whether to accept conditional successes or redesign to enable strict parity. + +**Which tables are most critical?** +Prioritize critical data (compliance, transactions, authentication) for comprehensive validation. Use targeted validation loops on high-churn tables during replication. + +**Do you have unsupported column types?** +For types that cannot be compared automatically (e.g., geospatial), plan alternative checks like row counts or application-level validation. + +## MOLT toolkit support + +The MOLT toolkit provides validation capabilities that integrate naturally with migration workflows. + +### MOLT Verify + +[MOLT Verify]({% link molt/molt-verify.md %}) performs structural and row-level comparison between source and CockroachDB: + +- **Schema verification**: Compares table structure, column definitions, types, and constraints. +- **Row verification**: Compares row values and identifies missing, mismatched, or extraneous rows. +- **Scope control**: `--schema-filter` and `--table-filter` restrict validation to specific schemas or tables using regular expressions. Essential for phased migrations. +- **Performance tuning**: `--concurrency` increases parallelism; `--row-batch-size` balances memory and retry granularity. +- **Live awareness**: `--live` retries rows that may change between batches, reducing transient mismatch noise during active imports or replication. +- **Continuous monitoring**: `--continuous` loops validation to observe convergence over time on critical tables during replication. + +**Limitations to plan for:** +- Detects collation mismatches on `STRING` primary keys; align collations or plan exceptions. +- Compares one MySQL database to a whole CockroachDB schema (`public` by default); scope accordingly. +- Geospatial types not yet compared; supplement with alternative checks. + +### MOLT Fetch + +[MOLT Fetch]({% link molt/molt-fetch.md %}) bulk loads data and defines the first validation checkpoint. After Fetch completes, run MOLT Verify before re-adding constraints and indexes that were dropped for performance. + +### MOLT Replicator + +[MOLT Replicator]({% link molt/molt-replicator.md %}) streams ongoing changes and provides health signals for validation timing: + +- Enable metrics (`--metricsAddr`) to monitor replication lag and confirm steady-state. +- Use lag signals to determine when replication has "drained" before running final validation. +- Ensure GC TTL is configured so checkpoint positions remain valid during the migration window. + +### Validation checkpoints in MOLT flows + +MOLT prescribes natural validation checkpoints: + +1. **After initial load**: Before restoring indexes and constraints (all migration patterns). +2. **During replication**: Continuous or periodic validation with `--live` mode (load-then-replicate pattern). +3. **Pre-cutover**: Comprehensive validation after replication drains (minimal-downtime patterns). +4. **Per-phase**: Scoped validation at phase boundaries (phased migrations). + +## Validation by migration stage + +| Stage | Purpose | Approach | +|---|---|---| +| **Design & dry-run** | Catch schema and type issues early | Convert schema, load test data, validate critical queries, note differences to waive or fix | +| **After bulk load** | Prove parity before resuming constraints | Run MOLT Verify on full scope; resolve mismatches; re-add non-PK constraints/indexes | +| **During replication** | Ensure convergence while source is live | Run MOLT Verify with `--live` and optionally `--continuous` on critical tables; monitor Replicator metrics | +| **Pre-cutover gate** | Final correctness guarantee | Confirm Replicator drained; run comprehensive MOLT Verify; validate critical query suite | +| **Post-cutover** | Confidence in steady state | Targeted MOLT Verify on high-risk tables; application smoke tests | + +## Common validation pitfalls + +**Collation on STRING primary keys:** +Different collations between source and target can cause validation failures. Align collations where possible or plan documented exceptions. + +**Type differences by design:** +Converting `AUTO_INCREMENT` to `UUID` or other intentional type changes will flag column mismatches. Review conditional successes and decide whether to accept or redesign. + +**Unsupported comparison types:** +Geospatial and certain other types cannot be automatically compared. Use row counts, subset spot checks, or application-level validation, and document residual risk. + +**Validation runtime in tight windows:** +Large datasets may not fit validation within downtime windows. Plan phased validation, increase concurrency, or use off-peak periods for comprehensive runs. + +**False positives during live replication:** +Active sources can cause transient mismatches. Always use `--live` mode during replication to retry rows before flagging errors. + +## Coordinating validation with migration flow + +Your migration pattern determines validation orchestration: + +**Bulk load with downtime:** +Single comprehensive validation run after load fits within downtime window. Favor completeness over speed; this is your only checkpoint. + +**Load-then-replicate:** +Multiple validation checkpoints with different goals—initial load for bulk correctness, continuous for convergence monitoring, final for cutover readiness. Monitor replication lag to time the final gate. + +**Phased migration:** +Repeated scoped validation per phase using schema and table filters. Each phase has independent validation gates, reducing risk but increasing orchestration. + +## See also + +- [Migration Overview]({% link molt/migration-overview.md %}) +- [Migration Considerations]({% link molt/migration-considerations.md %}) +- [Migration Granularity]({% link molt/migration-considerations-phases.md %}) +- [Continuous Replication]({% link molt/migration-considerations-replication.md %}) +- [Data Transformation Strategy]({% link molt/migration-considerations-transformation.md %}) +- [MOLT Verify]({% link molt/molt-verify.md %}) +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [MOLT Replicator]({% link molt/molt-replicator.md %}) diff --git a/src/current/molt/migration-considerations.md b/src/current/molt/migration-considerations.md index 07f6151b71f..236803953cc 100644 --- a/src/current/molt/migration-considerations.md +++ b/src/current/molt/migration-considerations.md @@ -36,11 +36,11 @@ How much downtime can your application tolerate during the migration? This is on To succeed, you should estimate the amount of downtime required to migrate your data, and ideally schedule the downtime outside of peak hours. Scheduling downtime is easiest if your application traffic is "periodic", meaning that it varies by the time of day, day of week, or day of month. - If you can support planned downtime, you may want to migrate your data [all at once]({% link molt/migration-considerations-phases.md %}), and _without_ [continuous replication]({% link molt/migration-considerations-replication.md %}). + If you can support planned downtime, you may want to migrate your data all at once, and _without_ continuous replication. - **Minimal downtime** impacts as few customers as possible, ideally without impacting their regular usage. If your application is intentionally offline at certain times (e.g., outside business hours), you can migrate the data without users noticing. Alternatively, if your application's functionality is not time-sensitive (e.g., it sends batched messages or emails), you can queue requests while the system is offline and process them after completing the migration to CockroachDB. -- **Near-zero downtime** is necessary for mission-critical applications. For these migrations, consider cutover strategies that keep applications online for as long as possible, and which utilize [continuous replication]({% link molt/migration-considerations-replication.md %}). +- **Near-zero downtime** is necessary for mission-critical applications. For these migrations, consider cutover strategies that keep applications online for as long as possible, and which utilize continuous replication. In addition to downtime duration, consider whether your application could support windows of **reduced functionality** in which some, but not all, application functionality is brought offline. For example, you can disable writes but not reads while you migrate the application data, and queue data to be written after completing the migration. @@ -48,17 +48,17 @@ In addition to downtime duration, consider whether your application could suppor When do you need to complete the migration? How many team members can be allocated for this effort? How much complex orchestration can your team manage? These factors may influence your choices for [migration granularity]({% link molt/migration-considerations-phases.md %}), [continuous replication]({% link molt/migration-considerations-replication.md %}), and [cutover strategy]({% link molt/migration-considerations-cutover.md %}). -- Migrations with a short timeline, or which cannot accommodate high complexity, may want to migrate data [all at once]({% link molt/migration-considerations-phases.md %}), without utilizing [continuous replication]({% link molt/migration-considerations-replication.md %}), and requiring [manual reconciliation]({% link molt/migration-considerations-rollback.md %}) in the event of migration failure. +- Migrations with a short timeline, or which cannot accommodate high complexity, may want to migrate data all at once, without utilizing continuous replication, and requiring manual reconciliation in the event of migration failure. -- Migrations with a long timeline, or which can accomodate complexity, may want to migrate data [in phases]({% link molt/migration-considerations-phases.md %}). If the migration requires minimal downtime, these migrations may also want to utilize [continuous replication]({% link molt/migration-considerations-replication.md %}). If the migration is low in risk-tolerance, these migrations may also want to enable [failback]({% link molt/migration-considerations-rollback.md %}). +- Migrations with a long timeline, or which can accomodate complexity, may want to migrate data in phases. If the migration requires minimal downtime, these migrations may also want to utilize continuous replication. If the migration is low in risk-tolerance, these migrations may also want to enable failback. ### Risk tolerance How much risk is your organization willing to accept during the migration? This may influence your choices for [migration granularity]({% link molt/migration-considerations-phases.md %}), [validation strategy]({% link molt/migration-considerations-validation.md %}), and [rollback plan]({% link molt/migration-considerations-rollback.md %}). -- Risk-averse migrations should prefer [phased migrations]({% link molt/migration-considerations-phases.md %}) that limit the blast radius of any issues. Start with low-risk slices (e.g., a small cohort of tenants or a non-critical service), [validate thoroughly]({% link molt/migration-considerations-validation.md %}), and progressively expand to higher-value workloads. These migrations may also prefer [rollback plans]({% link molt/migration-considerations-rollback.md %}) that enable quick recovery in the event of migration issues. +- Risk-averse migrations should prefer phased migrations that limit the blast radius of any issues. Start with low-risk slices (e.g., a small cohort of tenants or a non-critical service), validate thoroughly, and progressively expand to higher-value workloads. These migrations may also prefer rollback plans that enable quick recovery in the event of migration issues. -- For risk-tolerant migrations, it may be acceptable to migrate [all of your data at once]({% link molt/migration-considerations-phases.md %}). Less stringent [validation strategies]({% link molt/migration-considerations-validation.md %}) and [manual reconciliation]({% link molt/migration-considerations-rollback.md %}) in the event of a migration failure may also be acceptable. +- For risk-tolerant migrations, it may be acceptable to migrate all of your data at once. Less stringent validation strategies and manual reconciliation in the event of a migration failure may also be acceptable. ___ From d7722fcbe5548bd8d7d4c3ecf6b426c107988d51 Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Sun, 14 Dec 2025 19:23:36 -0500 Subject: [PATCH 07/15] added validation strategy consideration --- .../v25.4/sidebar-data/migrate-new.json | 6 - src/current/images/molt/molt_flows_4.svg | 885 ++++++++++++++++++ .../molt/migration-considerations-phases.md | 4 +- .../migration-considerations-replication.md | 12 + .../molt/migration-considerations-rollback.md | 58 +- .../migration-considerations-validation.md | 143 +-- src/current/molt/migration-considerations.md | 1 - src/current/molt/migration-overview.md | 8 - 8 files changed, 966 insertions(+), 151 deletions(-) create mode 100644 src/current/images/molt/molt_flows_4.svg diff --git a/src/current/_includes/v25.4/sidebar-data/migrate-new.json b/src/current/_includes/v25.4/sidebar-data/migrate-new.json index 41e84edb91a..a3149d53066 100644 --- a/src/current/_includes/v25.4/sidebar-data/migrate-new.json +++ b/src/current/_includes/v25.4/sidebar-data/migrate-new.json @@ -46,12 +46,6 @@ "urls": [ "/molt/migration-considerations-rollback.html" ] - }, - { - "title": "Cutover Plan", - "urls": [ - "/molt/migration-considerations-cutover.html" - ] } ] }, diff --git a/src/current/images/molt/molt_flows_4.svg b/src/current/images/molt/molt_flows_4.svg new file mode 100644 index 00000000000..34363f84aa3 --- /dev/null +++ b/src/current/images/molt/molt_flows_4.svg @@ -0,0 +1,885 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/current/molt/migration-considerations-phases.md b/src/current/molt/migration-considerations-phases.md index e477bb8680e..35d451dc0fd 100644 --- a/src/current/molt/migration-considerations-phases.md +++ b/src/current/molt/migration-considerations-phases.md @@ -81,13 +81,13 @@ Similarly, you can use [MOLT Verify]({% link molt/molt-verify.md %})'s `--schema ## Example sequences -### Migrating all data at once +#### Migrating all data at once
MOLT tooling overview
-### Phased migration +#### Phased migration
MOLT tooling overview diff --git a/src/current/molt/migration-considerations-replication.md b/src/current/molt/migration-considerations-replication.md index 193c4733898..e9cd08d9cb2 100644 --- a/src/current/molt/migration-considerations-replication.md +++ b/src/current/molt/migration-considerations-replication.md @@ -98,6 +98,18 @@ If you're only interested in capturing recent changes, skip MOLT Fetch entirely ## Example sequences +#### Bulk load only + +
+MOLT tooling overview +
+ +#### Hybrid approach + +
+MOLT tooling overview +
+ ## See also - [Migration Overview]({% link molt/migration-overview.md %}) diff --git a/src/current/molt/migration-considerations-rollback.md b/src/current/molt/migration-considerations-rollback.md index 3ce21ad1838..5db81cf11c0 100644 --- a/src/current/molt/migration-considerations-rollback.md +++ b/src/current/molt/migration-considerations-rollback.md @@ -55,57 +55,35 @@ This enables faster rollback, but increases application complexity as you need t Use these questions to guide your rollback strategy: -**What is your rollback RTO/RPO requirement?** -If rollback must be immediate with near-zero data loss, prefer dual-write or bidirectional replication. For moderate RTO, reverse unidirectional suffices. For generous RTO and low risk, manual may be acceptable. +**How quickly do you need to roll back if problems occur?** +If you need immediate rollback, choose dual-write or bidirectional replication. If you can tolerate some delay to activate failback replication, one-way failback replication is sufficient. For low-risk migrations with generous time windows, manual reconciliation may be acceptable. -**What is your write topology and conflict risk?** -If multiple writers can touch the same keys, avoid bidirectional replication unless you have conflict avoidance (partitioning by tenant/service) or deterministic conflict resolution. +**How much data can you afford to lose during rollback?** +If you cannot lose any data written after cutover, choose bidirectional replication or on-demand failback (both preserve all writes). Dual-write can also preserve data if implemented carefully. Manual reconciliation typically accepts some data loss. -**What is your operational maturity?** -Bidirectional replication requires monitoring, alerting, and practiced runbooks. Reverse unidirectional requires a tested activation runbook. Dual-write requires app-layer resiliency and observability across write paths. +**Will writes occur to both databases during the trial period?** +If traffic might split between source and target (e.g., during gradual cutover or in multi-region scenarios), bidirectional replication keeps both databases synchronized. If traffic cleanly shifts from source to target, on-demand failback or dual-write is sufficient. -**Can you modify the application?** -If app changes are expensive or risky, prefer database-level options (reverse unidirectional or bidirectional) over dual-write. +**Can you modify the application code?** +If application changes are expensive or risky, use database-level replication (bidirectional or on-demand failback) instead of dual-write. -**What are your source and target capabilities?** -Ensure your source supports required CDC/replication characteristics and retention for the migration window. Verify that CockroachDB changefeeds can deliver necessary backfill for failback in your environment. +**What is your team's operational capacity?** +Bidirectional replication requires monitoring and managing two active replication streams. On-demand failback requires a tested runbook for activating failback quickly. Dual-write requires application-layer resilience and observability. Manual reconciliation has the lowest operational complexity. -## MOLT toolkit support - -The MOLT toolkit provides tools that enable different rollback strategies. - -### MOLT Replicator (forward and failback) - -[MOLT Replicator]({% link molt/molt-replicator.md %}) streams ongoing changes between databases: - -- **Forward replication**: Streams changes from PostgreSQL, MySQL, or Oracle to CockroachDB for minimal-downtime migrations. -- **Failback**: Streams changes from CockroachDB back to the source using a CockroachDB changefeed to preserve rollback options. +**What are your database capabilities?** +Ensure your source database supports the change data capture requirements for the migration window. Verify that CockroachDB changefeeds can provide the necessary failback support for your environment. -**Key capabilities for rollback:** - -- **Staging database**: Persists checkpoints and metadata in a CockroachDB staging schema (`--stagingSchema`, created with `--stagingCreateSchema`). -- **Connections**: `--targetConn` points to the destination for applied changes; `--stagingConn` points to the CockroachDB staging database. -- **Metrics**: `--metricsAddr` exposes a Prometheus endpoint for replication lag, throughput, and applied mutations. -- **Webhook endpoint**: `--bindAddr` receives changefeed events during failback. -- **Prerequisites**: For self-hosted clusters, enable rangefeeds to support changefeeds in failback workflows. - -**Usage by rollback option:** - -- **Dual-write**: Use Replicator for forward replication into CockroachDB; keep failback tooling pre-validated on standby. -- **Bidirectional**: Run forward replication and failback concurrently during trial; monitor both metrics endpoints. -- **Reverse unidirectional**: Before cutover, confirm you can start failback quickly with known flags; at rollback time, follow the failback runbook to start Replicator and create the changefeed. -- **Manual**: Not applicable; no automated replication during rollback. +## MOLT toolkit support -### MOLT Fetch +[MOLT Replicator]({% link molt/molt-replicator.md %}) uses change data to stream changes from one database to another. It's used for both [forward replication]({% link molt/migration-considerations-replication.md %}) and [failback replication](#failback-replication). -[MOLT Fetch]({% link molt/molt-fetch.md %}) performs initial one-time data load and pairs with Replicator for minimal-downtime migrations. Rollback choice primarily affects Replicator usage after initial load rather than Fetch. +To use MOLT Replicator in failback mode, run the [`replicator start`]({% link molt/molt-replicator.md %}#commands) command with its various [flags]({% link molt/molt-replicator.md %}#start-failback-flags). -### MOLT Verify +When enabling failback replication, the original source database becomes the replication target, and the original target CockroachDB cluster becomes the replication source. Use the `--sourceConn` flag to indicate the CockroachDB cluster, and use the `--targetConn` flag to indicate the PostgreSQL, MySQL, or Oracle database from which data is being migrated. -[MOLT Verify]({% link molt/molt-verify.md %}) compares schema and row-level data between source and CockroachDB to surface discrepancies: +MOLT Replicator can be stopped after cutover, or it can remain online to continue streaming changes indefinitely. This could be useful for as long as you want as you want the migration source database to serve as a backup to the new CockroachDB cluster. -- **Dual-write or bidirectional**: Run Verify to catch drift during the coexistence window. -- **Reverse unidirectional or manual**: Run before activating rollback to estimate catch-up effort; run again after failback or manual repair to confirm consistency. +Rollback plans that do not utilize failback replication will require external tooling, or in the case of a dual-write strategy, changes to application code. You can still use [MOLT Verify]({% link molt/molt-verify.md %}) to ensure parity between the two databases. ## See also diff --git a/src/current/molt/migration-considerations-validation.md b/src/current/molt/migration-considerations-validation.md index f42513860db..0a890fada67 100644 --- a/src/current/molt/migration-considerations-validation.md +++ b/src/current/molt/migration-considerations-validation.md @@ -5,98 +5,77 @@ toc: true docs_area: migrate --- -A successful migration to CockroachDB requires a clear validation strategy that proves the target holds the right data, in the right shape, and behaves correctly for your application. Validation is not a single step—it occurs at multiple checkpoints throughout the migration process, with increasing rigor as you approach cutover. +Validation strategies are critical to ensuring a successful data migration. They're how you confirm that the right data has been moved correctly, is complete, and is usable in the new environment. A validation strategy is defined by **what** validations you want to run and **when** you want to run them. -This page explains what to validate, when to validate during different migration flows, and how these choices shape your use of MOLT tooling. +This page explains how to think about different validation strategies and how to use MOLT tooling to enable validation. -In general: + ## What to validate -Validation occurs in layers, from structural to behavioral: +Running any of the following validations can help you feel confident that the data in the CockroachDB cluster matches the data in the migration source database. -### Schema parity +- **Row Count Validation**: Ensures the number of records matches between source and target. -Verify that table structure, column names, types, nullability, and constraints match between source and target. This catches DDL conversion issues early. +- **Checksum/Hash Validation**: Compares hashed values of rows or columns to detect changes or corruption. -### Row-level correctness +- **Data Sampling**: Randomly sample and manually compare rows between systems. -Confirm that no rows are missing or extraneous, and that row values match. This is the core of data integrity validation. +- **Column-Level Comparison**: Validate individual field values across systems. -### Type and collation compatibility +- **Business Rule Validation**: Apply domain rules to validate logic or derived values. -Account for intentional differences: type conversions (e.g., `AUTO_INCREMENT` to `UUID`), collation differences on `STRING` primary keys, and unsupported comparisons (e.g., geospatial types). Plan how to handle these before running validation. +- **Boundary Testing**: Ensure edge-case data (nulls, max values, etc.) are correctly migrated. -### Application behavior +- **Referential Integrity**: Validate that relationships (foreign keys) are intact in the target. -Validate critical queries and transactions using shadow traffic or targeted tests on a production-sized CockroachDB cluster. This catches semantic differences that row-by-row comparison cannot reveal, such as isolation-level semantics or query plan changes. +- **Data Type Validation**: Confirm that fields conform to expected types/formats. -## When to validate - -Use natural checkpoints in your migration flow, increasing rigor as you approach cutover: - -### Pre-migration (design and dry-run) - -Validate converted schema and resolve type mapping issues. Run a dry-run migration on test data and begin query validation to catch behavioral differences early. - -### After initial data load - -Run comprehensive validation to confirm schema and row-level parity before re-adding constraints and indexes that were dropped to accelerate load. This is your first full data integrity checkpoint. +- **Null/Default Value Checks**: Validate expected default values or NULLs post-migration. -### During continuous replication +- **ETL Process Validation**: Check logs, counts, or errors from migration tools. -If using replication, run validation periodically to ensure the target converges with the source. Use live-aware validation to reduce false positives from in-flight changes. This gives you confidence that replication is working correctly. +- **Automated Testing**: Use scripts or tools to compare results and flag mismatches. -### Pre-cutover gate +The rigor of your validations (the set of validations you perform) will depend on your organization's risk tolerance and the complexity of the migration. -Once replication has drained (no backlog), run final validation on the complete cutover scope and verify critical application queries. This is your go/no-go decision point. - -### Post-cutover confidence checks - -After traffic moves to CockroachDB, run targeted validation on critical tables and application smoke tests to confirm steady state. +## When to validate -## How validation changes by migration pattern +A migration can be a long process, and depending on the choices made in designing a migration, it can be complex. If the dataset is small or the migration is low in complexity, it may be sufficient to simply run validations when you're ready to cut over application traffic to CockroachDB. However, there are several opportunities to validate your data in advance of cutover. -Different migration patterns require different validation approaches: +It's often useful to find natural checkpoints in your migration flow to run validations, and to increase the rigor of those validations as you approach cutover. -### Bulk load with planned downtime +If performing a migration [in phases]({% link molt/migration-considerations-phases.md %}), the checkpoints below can be considered in the context of each individual phase. A rigorous validation approach might choose to run validations after each phase, while a more risk-tolerant approach might choose to run them after all of the phases have been migrated but before cutover. -Run full-schema and full-table validation on all in-scope tables immediately after bulk load. If you dropped constraints and indexes for performance, validate before re-adding them, then re-run on critical tables afterward. +#### Pre-migration (design and dry-run) -**Characteristics:** Strongest guarantees at a single point in time; requires downtime sufficient for load plus validation. +Validate converted schema and resolve type mapping issues. Run a dry-run migration on test data and begin query validation to catch behavioral differences early. -### Load-then-replicate (minimal downtime) +#### After a bulk data load -Validate after initial load, then use live-aware validation during replication to monitor convergence. Wait for replication to drain, then run comprehensive final validation immediately before cutover. +Run comprehensive validations to confirm schema and row-level parity before re-adding constraints and indexes that were dropped to accelerate load. -**Characteristics:** Short downtime but longer total calendar time; must coordinate replication lag, GC retention, and validation runtime. +#### During continuous replication -### Phased migration +If using [continuous replication]({% link molt/migration-considerations-replication.md %}), run validation periodically to ensure the target converges with the source. Use live-aware validation to reduce false positives from in-flight changes. This gives you confidence that replication is working correctly. -Validate each phase independently using schema and table filters. Each phase becomes its own mini-cutover with phase-specific validation gates. +#### Before cutover -**Characteristics:** Smaller blast radius and faster feedback per phase; requires orchestrating multiple validation cycles. +Once replication has drained, run final validation on the complete cutover scope and verify critical application queries. -## Tradeoffs +#### Post-cutover confidence checks -| | Bulk load | Load-then-replicate | Phased | -|---|---|---|---| -| **Validation scope** | Full dataset at once | Full initial + continuous monitoring | Subset per phase | -| **Timing** | During downtime window | After load + during replication + pre-cutover | Repeated per phase | -| **Complexity** | Single comprehensive run | Multiple checkpoints with live awareness | Multiple scoped runs | -| **Downtime impact** | Extends downtime window | Minimal impact on downtime | Minimal per phase | -| **Confidence level** | Strongest single-point guarantee | Continuous convergence verification | Incremental confidence | -| **Best for** | Scheduled maintenance, smaller datasets | Production migrations, large datasets | Risk-averse migrations, natural data partitions | +After traffic moves to CockroachDB, run targeted validation on critical tables and application smoke tests to confirm steady state. ## Decision framework -Use these questions to guide your validation strategy: +Use these questions to help you determine what validations you want to perform, and when you want to peform them: **What is your data volume and validation timeline?** Larger datasets require more validation time. Consider concurrency tuning, phased validation, or off-peak runs to fit within windows. @@ -115,25 +94,23 @@ For types that cannot be compared automatically (e.g., geospatial), plan alterna ## MOLT toolkit support -The MOLT toolkit provides validation capabilities that integrate naturally with migration workflows. +[MOLT Verify]({% link molt/molt-verify.md %}) performs structural and row-level comparison between the source database and the CockroachDB cluster. MOLT Verify performs the following verifications to ensure data integrity during a migration: -### MOLT Verify +- Table Verification: Check that the structure of tables between the source database and the target database are the same. -[MOLT Verify]({% link molt/molt-verify.md %}) performs structural and row-level comparison between source and CockroachDB: +- Column Definition Verification: Check that the column names, data types, constraints, nullability, and other attributes between the source database and the target database are the same. -- **Schema verification**: Compares table structure, column definitions, types, and constraints. -- **Row verification**: Compares row values and identifies missing, mismatched, or extraneous rows. -- **Scope control**: `--schema-filter` and `--table-filter` restrict validation to specific schemas or tables using regular expressions. Essential for phased migrations. -- **Performance tuning**: `--concurrency` increases parallelism; `--row-batch-size` balances memory and retry granularity. -- **Live awareness**: `--live` retries rows that may change between batches, reducing transient mismatch noise during active imports or replication. -- **Continuous monitoring**: `--continuous` loops validation to observe convergence over time on critical tables during replication. +- Row Value Verification: Check that the actual data in the tables is the same between the source database and the target database. -**Limitations to plan for:** -- Detects collation mismatches on `STRING` primary keys; align collations or plan exceptions. -- Compares one MySQL database to a whole CockroachDB schema (`public` by default); scope accordingly. -- Geospatial types not yet compared; supplement with alternative checks. +Other validations beyond those supported by MOLT Verify would need to be run by a third-party tool, but could be run in tandem with MOLT Verify. -### MOLT Fetch +If performing a [phased migration]({% link molt/migration-considerations-phases.md %}), you can use MOLT Verify's `--schema-filter` and `--table-filter` flags to specify specific schemas or tables to run the validations on. + +If using [continuous replication]({% link molt/migration-considerations-replication.md %}), you can use MOLT Verify's `--continuous` and `--live` flags to enable continuous verification. + +Check MOLT Verify's [known limitations]({% link molt/molt-verify.md %}#known-limitations) to ensure the tool's suitability for your validation strategy. + + -## Validation by migration stage + + ## See also diff --git a/src/current/molt/migration-considerations.md b/src/current/molt/migration-considerations.md index 236803953cc..5118e1bb3ab 100644 --- a/src/current/molt/migration-considerations.md +++ b/src/current/molt/migration-considerations.md @@ -20,7 +20,6 @@ Learn more about each migration variable by clicking the links in the left-hand | [**Data transformation strategy**]({% link molt/migration-considerations-transformation.md %}) | If there are discrepancies between the source and target schema, how will you define those data transformations, and when will those transformations occur? | - No data transformation
- Transform at source
- Tranform in flight
- Transform at target | | [**Validation strategy**]({% link molt/migration-considerations-validation.md %}) | How and when will you verify that the data in CockroachDB matches the source database? | - After initial load
During sync
After cutover
QA sign-off | | [**Rollback plan**]({% link molt/migration-considerations-rollback.md %}) | What approach will you use to roll back the migration if issues arise during or after cutover? | - Dual-write
- Bidirectional replication
- Failback (reverse replication)
- Manual reconciliation | -| [**Cutover strategy**]({% link molt/migration-considerations-cutover.md %}) | How will you transition application traffic from the source database to CockroachDB? | - Big-bang cutover
- Minimal-downtime cutover (with replication)
- Progressive cutover (per-slice) | The combination of these variables largely defines your migration approach. While you'll typically choose one primary option for each variable, some migrations may involve a hybrid approach depending on your specific requirements. diff --git a/src/current/molt/migration-overview.md b/src/current/molt/migration-overview.md index 800da53cab7..1bc8b86892b 100644 --- a/src/current/molt/migration-overview.md +++ b/src/current/molt/migration-overview.md @@ -162,14 +162,6 @@ There are several different ways of verifying that the data in the source and th Until the migration is complete, migration failures may make you decide to roll back application traffic entirely to the source database. You may therefore need a way of keeping the source database up to date with new writes to the target. This is especially important for risk-averse migrations that aim to minimize downtime. -### Cutover plan - -*Cutover* is the process of switching application traffic from the source database to CockroachDB. - -There are many different approaches to cutover. It can happen all at once, it can occur in multiple steps (in tandem with different [migration phases](#migration-granularity)). It's possible to cut over read and write traffic at different times. The possibilities are varied. - -The decision of how to cut over application traffic is closely linked with many of the other choices above. - --- [Learn more about the different migration variables]({% link molt/migration-considerations.md %}), how you should consider the different options for each variable, and how to use the MOLT toolkit for each variable. From d3ffe008fc9c0a33d646d53ac9ebc070cb871fce Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Sun, 14 Dec 2025 19:46:18 -0500 Subject: [PATCH 08/15] removed dead links --- src/current/molt/migration-considerations-transformation.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/current/molt/migration-considerations-transformation.md b/src/current/molt/migration-considerations-transformation.md index 48c677c6012..67c9d2c4f09 100644 --- a/src/current/molt/migration-considerations-transformation.md +++ b/src/current/molt/migration-considerations-transformation.md @@ -113,7 +113,7 @@ The MOLT toolkit provides specialized features for implementing transformations ### MOLT Schema Conversion Tool -Use the [Schema Conversion Tool]() first to convert your schema and apply CockroachDB best practices. This reduces downstream transformation pressure by addressing DDL incompatibilities upfront. +Use the Schema Conversion Tool first to convert your schema and apply CockroachDB best practices. This reduces downstream transformation pressure by addressing DDL incompatibilities upfront. ### MOLT Fetch @@ -145,7 +145,6 @@ Use [MOLT Verify]({% link molt/molt-verify.md %}) to compare schemas and data be - [Migration Considerations]({% link molt/migration-considerations.md %}) - [Migration Granularity]({% link molt/migration-considerations-phases.md %}) - [Continuous Replication]({% link molt/migration-considerations-replication.md %}) -- [MOLT Schema Conversion Tool]() - [MOLT Fetch]({% link molt/molt-fetch.md %}) - [MOLT Replicator]({% link molt/molt-replicator.md %}) - [MOLT Verify]({% link molt/molt-verify.md %}) From 95de160e31e8ce007db4c28dae9c08e495b48808 Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Mon, 15 Dec 2025 11:36:36 -0500 Subject: [PATCH 09/15] added data transformation strategy --- ...migration-considerations-transformation.md | 98 ++++--------------- src/current/molt/migration-considerations.md | 14 +-- 2 files changed, 25 insertions(+), 87 deletions(-) diff --git a/src/current/molt/migration-considerations-transformation.md b/src/current/molt/migration-considerations-transformation.md index 67c9d2c4f09..7d517761dad 100644 --- a/src/current/molt/migration-considerations-transformation.md +++ b/src/current/molt/migration-considerations-transformation.md @@ -5,140 +5,78 @@ toc: true docs_area: migrate --- -Most migrations require some level of data transformation—whether schema conversion, type mapping, row filtering, or value normalization. The key decision is **where** these transformations occur: on the source database, in flight during the migration pipeline, or on the target CockroachDB cluster. Each approach has distinct trade-offs in terms of performance, operational complexity, and downtime tolerance. +Data transformations are applied to data as it moves from the source system to the target system. Transformations ensure that the data is compatible, consistent, and valuable in the destination. They are a key part of a migration to CockroachDB. When planning a migration, it's important to determine **what** transformations are necessary and **where** they need to occur. This page explains the types of transformations to expect, where they can be applied, and how these choices shape your use of MOLT tooling. -In general: - -- Choose **source-side transformations** when you want to minimize data volume across the network, or when transformations are straightforward to express in SQL. - -- Choose **in-flight transformations** for minimal-downtime migrations where the same transformation logic must apply consistently to both the initial bulk load and continuous replication streams. - -- Choose **target-side transformations** when you want to minimize changes to the source system, or when you can leverage CockroachDB features like computed columns for convenience. - ## Common transformation types -Most migrations require a mix of schema-level and data-level changes: +If the source and target schemas are not identical, some sort of transformation is likely to be necessary during a migration. The set of necessary transformations will depend on the differences between your source database schema and your target CockroachDB schema, as well as any data quality or formatting requirements for your application. -- **Schema conversion**: Rewrite unsupported DDL and apply CockroachDB best practices using MOLT Schema Conversion Tool. -- **Type mapping**: Align source types with CockroachDB types, especially for dialect-specific types (e.g., MySQL `ENUM`). +- **Type mapping**: Align source types with CockroachDB types, especially for dialect-specific types. +- **Format conversion**: Change the format or encoding of certain value to align with the target schema (for example, `2024-03-01T00:00:00Z` to `03/01/2024`). +- **Field renaming**: Rename fields to fit target schemas or conventions. - **Primary key strategy**: Replace source sequences or auto-increment patterns with CockroachDB-friendly IDs (UUIDs, sequences). - **Table reshaping**: Consolidate partitioned tables, rename tables, or retarget to different schemas. - **Column changes**: Exclude deprecated columns, or map computed columns. - **Row filtering**: Move only a subset of rows by tenant, region, or timeframe. +- **Null/default handling**: Replace, remove, or infer missing values. - **Constraints and indexes**: Drop non-primary-key constraints and secondary indexes before bulk load for performance, then recreate after. -- **Value normalization**: Apply value transforms during replication to ensure consistent processing of bulk and streaming data. ## Where to transform -### Transform on the source (before export) - -Apply transformations directly on the source database before exporting data. - -**Best for:** Minimizing data volume across the network; leveraging existing source database features for filtering or aggregation. - -**Advantages:** Smallest extract sets reduce network transfer and storage; simple bulk-load path where downstream receives transformed data. - -**Disadvantages:** Adds load to source database; complex logic may be harder to express in SQL; may need to replicate transformation logic for continuous replication. - -### Transform in flight (inside the MOLT pipeline) - -Apply transformations within the migration pipeline, between source and target. - -**Best for:** Minimal-downtime migrations where the same logic must apply to both initial load and continuous replication deltas; complex transformations that benefit from code rather than SQL. - -**Advantages:** One code layer (TypeScript userscripts) for transform/filter/route logic; version-controlled and testable; separates transformation from databases. +Transformations can occur in the source database, in the target database, or in flight (between the source and the target). Deciding where to perform the transformations is largely determined by technical constraints, including the mutability of the source database and the choice of tooling. -**Disadvantages:** Requires operating a custom code path with observability and error handling; adds CPU to migration's critical path. +#### Transform in the source database -{{site.data.alerts.callout_info}} -MOLT Fetch's JSON transformations are for schema shaping (rename/merge/exclude/computed) rather than arbitrary per-value masking. Use MOLT Replicator userscripts for value-level transformations. -{{site.data.alerts.end}} +Apply transformations directly on the source database before migrating data. This is only possible if the source database can be modified to accommodate the transformations suited for the target database. -### Transform on the target (after load or during target DDL) +This provides the advantage of allowing ample time, before the downtime window, to perform the transformations, but it often is not possible due to technical constraints. -Apply transformations in CockroachDB after data has been loaded. +#### Transform in the target database -**Best for:** Minimizing changes to the source system; leveraging CockroachDB-specific features. +Apply transformations in the CockroachDB cluster after data has been loaded. For any transformations that occur in the target cluster, it's recommended that these occur before cutover, to ensure that live data complies with CockroachDB best practices. Transformations that occur before cutover may extend downtime. -**Advantages:** Minimizes source changes; works well for schema reshaping with CockroachDB DDL; can leverage distributed processing. +#### Transform in flight -**Disadvantages:** Full data volume crosses the network; may require post-load processing. +Apply transformations within the migration pipeline, between the source and target databases. This allows the source database to remain as it is, and it allows the target database to be designed using CockroachDB best practices. It also enables testability by separating transformations from either database. -## Pairing with migration patterns - -Different migration patterns favor different transformation approaches: - -- **Planned downtime / bulk-load**: Prefer source-side filtering and target-side reshaping (computed columns, renames) to keep the pipeline straightforward. Use MOLT Fetch transformations for schema-level changes. - -- **Load-then-replicate (minimal downtime)**: Use in-flight userscripts for continuous replication to ensure consistent transformation logic across bulk and streaming loads. Source-side filtering can reduce initial volume. - -- **Continuous replication-first**: Emphasize in-flight transforms (userscripts) to ensure ongoing changes are normalized and reshaped consistently until cutover and beyond. - -## Combining approaches - -You can and often should combine approaches to meet operational requirements: - -- **Source + in flight**: Coarse-grained filtering at source to reduce volume, then complex transformations in-flight for CDC consistency. -- **Source + target**: Source-side views or staging tables for data preparation, plus target computed columns or table renames. -- **In flight + target**: Userscripts for row-level logic, plus target DDL for schema conveniences (computed columns, index recreation). - -## Tradeoffs - -| | Source | In flight | Target | -|---|---|---|---| -| **Network transfer** | Reduced (transformed data only) | Full volume crosses network | Full volume crosses network | -| **Source impact** | Adds load to source database | No source changes required | No source changes required | -| **Complexity** | SQL-based, tied to source dialect | Requires custom code and monitoring | DDL-based, CockroachDB native | -| **Downtime impact** | May require source schema changes | Independent of source/target schemas | May require post-load processing | -| **Reusability** | Logic tied to source database | Version-controlled, portable code | Tied to target database | -| **Testing** | Test with source database tools | Test userscripts independently | Test with CockroachDB tools | -| **Best for** | Volume reduction, SQL-friendly transforms | Minimal-downtime migrations, complex logic | Simple migrations, CockroachDB-native features | +However, in-flight transformations may require more complex tooling. Tranformation in-flight is largely supported by the [MOLT toolkit](#molt-toolkit-support). ## Decision framework Use these questions to guide your transformation strategy: - **What is your downtime tolerance?** Near-zero downtime pushes you toward in-flight transforms that apply consistently to bulk and streaming loads. -- **Can your team test and maintain transformations more easily in SQL or code?** This influences whether to use source-side SQL, in-flight TypeScript userscripts, or target-side CockroachDB DDL. - **Will transformation logic be reused post-cutover?** If you need ongoing sync or failback, prefer deterministic, version-controlled in-flight transformations. - **How complex are the transformations?** Simple schema reshaping favors MOLT Fetch transformations or target DDL. Complex value normalization or routing favors in-flight userscripts. -- **What is your network and performance budget?** Source-side pushdown reduces volume across the wire. In-flight logic adds CPU to the pipeline. Balance throughput needs with transformation requirements. - **Can you modify the source database?** Source-side transformations require permission and capacity to create views, staging tables, or run transformation queries. ## MOLT toolkit support -The MOLT toolkit provides specialized features for implementing transformations at each stage of the migration pipeline. +The MOLT toolkit provides functionality for implementing transformations at each stage of the migration pipeline. ### MOLT Schema Conversion Tool -Use the Schema Conversion Tool first to convert your schema and apply CockroachDB best practices. This reduces downstream transformation pressure by addressing DDL incompatibilities upfront. +While not a part of the transformation process itself, the [MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}) automates the creation of the target database schema based on the schema of the source database. This reduces downstream transformation pressure by addressing DDL incompatibilities upfront. ### MOLT Fetch -[MOLT Fetch]({% link molt/molt-fetch.md %}) supports transformations during initial data load: +[MOLT Fetch]({% link molt/molt-fetch.md %}) supports transformations during a bulk data load: - **Row filtering**: `--filter-path` specifies a JSON file with table-to-SQL-predicate mappings evaluated in the source dialect before export. Ensure filtered columns are indexed for performance. - **Schema shaping**: `--transformations-file` defines table renames, n→1 merges (consolidate partitioned tables), and column exclusions. For n→1 merges, use `--use-copy` or `--direct-copy` and pre-create the target table. - **Type alignment**: `--type-map-file` specifies explicit type mappings when auto-creating target tables. - **Table lifecycle**: `--table-handling` controls whether to truncate, drop-and-recreate, or assume tables exist. -For bulk-only flows, use `--ignore-replication-check` to skip replication checkpoint capture. - ### MOLT Replicator [MOLT Replicator]({% link molt/molt-replicator.md %}) uses TypeScript **userscripts** to implement in-flight transformations for continuous replication: - **Capabilities**: Transform or normalize values, route rows to different tables, enrich data, filter rows, merge partitioned sources. - **Structure**: Userscripts export functions (`configureTargetTables`, `onRowUpsert`, `onRowDelete`) that process change data before commit to CockroachDB. -- **Coordination**: For hybrid migrations, run MOLT Fetch for the initial load (which emits a `cdc_cursor` checkpoint), then start MOLT Replicator with the same transformation logic to process ongoing changes from that checkpoint. - **Staging schema**: Replicator uses a CockroachDB staging schema to store replication state and buffered mutations (`--stagingSchema` and `--stagingCreateSchema`). -### MOLT Verify - -Use [MOLT Verify]({% link molt/molt-verify.md %}) to compare schemas and data between source and target. For deliberate differences (e.g., masked columns or changed types), focus on intended equivalence: row counts, unchanged columns, and referential integrity. Run before replication starts (optional baseline) and before final cutover. - ## See also - [Migration Overview]({% link molt/migration-overview.md %}) diff --git a/src/current/molt/migration-considerations.md b/src/current/molt/migration-considerations.md index 5118e1bb3ab..dcaa15853e1 100644 --- a/src/current/molt/migration-considerations.md +++ b/src/current/molt/migration-considerations.md @@ -13,13 +13,13 @@ For detailed migration sequencing and tool usage, see [Migration Overview]({% li Learn more about each migration variable by clicking the links in the left-hand column. -| Variable | Description | Options | -|---|---|---| -| [**Migration granularity**]({% link molt/migration-considerations-phases.md %}) | Do you want to migrate all of your data at once, or do you want to split your data up into phases and migrate one phase at a time? | - All at once
- Phased | -| [**Continuous replication**]({% link molt/migration-considerations-replication.md %}) | After the initial data load (or after the initial load of each phase), do you want to stream further changes to that data from the source to the target? | - Bulk load only
- Continuous replication | -| [**Data transformation strategy**]({% link molt/migration-considerations-transformation.md %}) | If there are discrepancies between the source and target schema, how will you define those data transformations, and when will those transformations occur? | - No data transformation
- Transform at source
- Tranform in flight
- Transform at target | -| [**Validation strategy**]({% link molt/migration-considerations-validation.md %}) | How and when will you verify that the data in CockroachDB matches the source database? | - After initial load
During sync
After cutover
QA sign-off | -| [**Rollback plan**]({% link molt/migration-considerations-rollback.md %}) | What approach will you use to roll back the migration if issues arise during or after cutover? | - Dual-write
- Bidirectional replication
- Failback (reverse replication)
- Manual reconciliation | +| Variable | Description | +|---|---| +| [**Migration granularity**]({% link molt/migration-considerations-phases.md %}) | Do you want to migrate all of your data at once, or do you want to split your data up into phases and migrate one phase at a time? | +| [**Continuous replication**]({% link molt/migration-considerations-replication.md %}) | After the initial data load (or after the initial load of each phase), do you want to stream further changes to that data from the source to the target? | +| [**Data transformation strategy**]({% link molt/migration-considerations-transformation.md %}) | If there are discrepancies between the source and target schema, how will you define those data transformations, and when will those transformations occur? | +| [**Validation strategy**]({% link molt/migration-considerations-validation.md %}) | How and when will you verify that the data in CockroachDB matches the source database? | +| [**Rollback plan**]({% link molt/migration-considerations-rollback.md %}) | What approach will you use to roll back the migration if issues arise during or after cutover? | The combination of these variables largely defines your migration approach. While you'll typically choose one primary option for each variable, some migrations may involve a hybrid approach depending on your specific requirements. From 323ec2e9d15240c3821d160ad78e515684628705 Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Tue, 23 Dec 2025 10:49:47 -0500 Subject: [PATCH 10/15] did main splitting of Fetch docs --- .../molt/migration-schema-design-practices.md | 2 +- .../_includes/molt/molt-limitations.md | 2 +- src/current/_includes/molt/molt-setup.md | 2 +- src/current/_includes/sidebar-data-v26.1.json | 2 +- .../v25.4/sidebar-data/migrate-new.json | 39 ++- .../v26.1/sidebar-data/migrate-new.json | 222 ++++++++++++++++ .../_includes/v26.1/sidebar-data/migrate.json | 39 ++- src/current/molt/migration-overview.md | 2 +- src/current/molt/molt-fetch-best-practices.md | 69 +++++ .../molt/molt-fetch-commands-and-flags.md | 87 +++++++ src/current/molt/molt-fetch-installation.md | 52 ++++ src/current/molt/molt-fetch-monitoring.md | 31 +++ .../molt/molt-fetch-troubleshooting.md | 21 ++ src/current/molt/molt-fetch.md | 237 ++---------------- src/current/releases/molt.md | 42 ++-- 15 files changed, 600 insertions(+), 249 deletions(-) create mode 100644 src/current/_includes/v26.1/sidebar-data/migrate-new.json create mode 100644 src/current/molt/molt-fetch-best-practices.md create mode 100644 src/current/molt/molt-fetch-commands-and-flags.md create mode 100644 src/current/molt/molt-fetch-installation.md create mode 100644 src/current/molt/molt-fetch-monitoring.md create mode 100644 src/current/molt/molt-fetch-troubleshooting.md diff --git a/src/current/_includes/molt/migration-schema-design-practices.md b/src/current/_includes/molt/migration-schema-design-practices.md index be799393f6f..b84ad66fc3e 100644 --- a/src/current/_includes/molt/migration-schema-design-practices.md +++ b/src/current/_includes/molt/migration-schema-design-practices.md @@ -15,7 +15,7 @@ Convert the source schema into a CockroachDB-compatible schema. CockroachDB supp - If you create the target schema manually, review how MOLT Fetch handles [type mismatches]({% link molt/molt-fetch.md %}#mismatch-handling). You can use the {% if page.name != "migration-strategy.md" %}[MOLT Schema Conversion Tool](#schema-conversion-tool){% else %}[MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}){% endif %} to create a matching schema.
- - By default, table and column names are case-insensitive in MOLT Fetch. If using the [`--case-sensitive`]({% link molt/molt-fetch.md %}#global-flags) flag, schema, table, and column names must match Oracle's default uppercase identifiers. Use quoted names on the target to preserve case. For example, the following CockroachDB SQL statement will error: + - By default, table and column names are case-insensitive in MOLT Fetch. If using the [`--case-sensitive`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag, schema, table, and column names must match Oracle's default uppercase identifiers. Use quoted names on the target to preserve case. For example, the following CockroachDB SQL statement will error: ~~~ sql CREATE TABLE co.stores (... store_id ...); diff --git a/src/current/_includes/molt/molt-limitations.md b/src/current/_includes/molt/molt-limitations.md index 4e41fb29b93..0e6a4fd2475 100644 --- a/src/current/_includes/molt/molt-limitations.md +++ b/src/current/_includes/molt/molt-limitations.md @@ -12,7 +12,7 @@ - Oracle advises against `LONG RAW` columns and [recommends converting them to `BLOB`](https://www.orafaq.com/wiki/LONG_RAW#History). `LONG RAW` can only store binary values up to 2GB, and only one `LONG RAW` column per table is supported.
-- Only tables with [primary key]({% link {{ site.current_cloud_version }}/primary-key.md %}) types of [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) can be sharded with [`--export-concurrency`]({% link molt/molt-fetch.md %}#best-practices). +- Only tables with [primary key]({% link {{ site.current_cloud_version }}/primary-key.md %}) types of [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) can be sharded with [`--export-concurrency`]({% link molt/molt-fetch-best-practices.md %}#configure-the-source-database-and-connection). {% if page.name != "migrate-bulk-load.md" %} #### Replicator limitations diff --git a/src/current/_includes/molt/molt-setup.md b/src/current/_includes/molt/molt-setup.md index 00f9f642a3b..6e2c83f68be 100644 --- a/src/current/_includes/molt/molt-setup.md +++ b/src/current/_includes/molt/molt-setup.md @@ -14,7 +14,7 @@ - Create a CockroachDB [{{ site.data.products.cloud }}]({% link cockroachcloud/create-your-cluster.md %}) or [{{ site.data.products.core }}]({% link {{ site.current_cloud_version }}/install-cockroachdb-mac.md %}) cluster. - Install the [MOLT (Migrate Off Legacy Technology)]({% link releases/molt.md %}#installation) tools. -- Review the [Fetch]({% link molt/molt-fetch.md %}#best-practices) and {% if page.name != "migrate-bulk-load.md" %}[Replicator]({% link molt/molt-replicator.md %}#best-practices){% endif %} best practices. +- Review the [Fetch]({% link molt/molt-fetch-best-practices.md %}) and {% if page.name != "migrate-bulk-load.md" %}[Replicator]({% link molt/molt-replicator.md %}#best-practices){% endif %} best practices. - Review [Migration Strategy]({% link molt/migration-strategy.md %}).
diff --git a/src/current/_includes/sidebar-data-v26.1.json b/src/current/_includes/sidebar-data-v26.1.json index e5a01978692..51e9a08594f 100644 --- a/src/current/_includes/sidebar-data-v26.1.json +++ b/src/current/_includes/sidebar-data-v26.1.json @@ -11,7 +11,7 @@ {% include_cached v26.1/sidebar-data/feature-overview.json %}, {% include_cached v26.1/sidebar-data/resilience.json %}, {% include_cached v26.1/sidebar-data/connect-to-cockroachdb.json %}, - {% include_cached v26.1/sidebar-data/migrate.json %}, + {% include_cached v26.1/sidebar-data/migrate-new.json %}, {% include_cached v26.1/sidebar-data/cloud-deployments.json %}, {% include_cached v26.1/sidebar-data/self-hosted-deployments.json %}, {% include_cached v26.1/sidebar-data/schema-design.json %}, diff --git a/src/current/_includes/v25.4/sidebar-data/migrate-new.json b/src/current/_includes/v25.4/sidebar-data/migrate-new.json index a3149d53066..a763397c888 100644 --- a/src/current/_includes/v25.4/sidebar-data/migrate-new.json +++ b/src/current/_includes/v25.4/sidebar-data/migrate-new.json @@ -60,8 +60,43 @@ }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Overview", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Monitoring", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { diff --git a/src/current/_includes/v26.1/sidebar-data/migrate-new.json b/src/current/_includes/v26.1/sidebar-data/migrate-new.json new file mode 100644 index 00000000000..a763397c888 --- /dev/null +++ b/src/current/_includes/v26.1/sidebar-data/migrate-new.json @@ -0,0 +1,222 @@ +{ + "title": "Migrate NEW", + "is_top_level": true, + "items": [ + { + "title": "Overview", + "urls": [ + "/molt/migration-overview.html" + ] + }, + { + "title": "Migration Considerations", + "items": [ + { + "title": "Overview", + "urls": [ + "/molt/migration-considerations.html" + ] + }, + { + "title": "Migration Granularity", + "urls": [ + "/molt/migration-considerations-phases.html" + ] + }, + { + "title": "Continuous Replication", + "urls": [ + "/molt/migration-considerations-replication.html" + ] + }, + { + "title": "Data Transformation Strategy", + "urls": [ + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" + ] + } + ] + }, + { + "title": "MOLT Tools", + "items": [ + { + "title": "Schema Conversion Tool", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Fetch", + "items": [ + { + "title": "Overview", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Monitoring", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } + ] + }, + { + "title": "Replicator", + "urls": [ + "/molt/molt-replicator.html" + ] + }, + { + "title": "Verify", + "urls": [ + "/molt/molt-verify.html" + ] + } + ] + }, + { + "title": "Migration Walkthroughs", + "items": [ + { + "title": "Migration with Downtime", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Near-zero Downtime Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Near-zero Downtime Migration with Failback", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, + { + "title": "Third-Party Migration Tools", + "items": [ + { + "title": "AWS DMS", + "urls": [ + "/${VERSION}/aws-dms.html" + ] + }, + { + "title": "Qlik Replicate", + "urls": [ + "/${VERSION}/qlik.html" + ] + }, + { + "title": "Striim", + "urls": [ + "/${VERSION}/striim.html" + ] + }, + { + "title": "Oracle GoldenGate", + "urls": [ + "/${VERSION}/goldengate.html" + ] + }, + { + "title": "Debezium", + "urls": [ + "/${VERSION}/debezium.html" + ] + } + ] + }, + { + "title": "Migrate Data Types", + "items": [ + { + "title": "Migrate from CSV", + "urls": [ + "/${VERSION}/migrate-from-csv.html" + ] + }, + { + "title": "Migrate from Avro", + "urls": [ + "/${VERSION}/migrate-from-avro.html" + ] + }, + { + "title": "Migrate from Shapefiles", + "urls": [ + "/${VERSION}/migrate-from-shapefiles.html" + ] + }, + { + "title": "Migrate from OpenStreetMap", + "urls": [ + "/${VERSION}/migrate-from-openstreetmap.html" + ] + }, + { + "title": "Migrate from GeoJSON", + "urls": [ + "/${VERSION}/migrate-from-geojson.html" + ] + }, + { + "title": "Migrate from GeoPackage", + "urls": [ + "/${VERSION}/migrate-from-geopackage.html" + ] + }, + { + "title": "Import Performance Best Practices", + "urls": [ + "/${VERSION}/import-performance-best-practices.html" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/current/_includes/v26.1/sidebar-data/migrate.json b/src/current/_includes/v26.1/sidebar-data/migrate.json index 77b969311fb..f6e5946877a 100644 --- a/src/current/_includes/v26.1/sidebar-data/migrate.json +++ b/src/current/_includes/v26.1/sidebar-data/migrate.json @@ -54,8 +54,43 @@ }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Overview", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Monitoring", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { diff --git a/src/current/molt/migration-overview.md b/src/current/molt/migration-overview.md index 1bc8b86892b..2a552e9eadf 100644 --- a/src/current/molt/migration-overview.md +++ b/src/current/molt/migration-overview.md @@ -102,7 +102,7 @@ The [MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}) - Multiple migration flows via `IMPORT INTO` or `COPY FROM`. - Data movement via [cloud storage, local file servers, or direct copy]({% link molt/molt-fetch.md %}#data-path). -- [Concurrent data export]({% link molt/molt-fetch.md %}#best-practices) from multiple source tables and shards. +- [Concurrent data export]({% link molt/molt-fetch-best-practices.md %}) from multiple source tables and shards. - [Schema transformation rules]({% link molt/molt-fetch.md %}#transformations). - After exporting data with `IMPORT INTO`, safe [continuation]({% link molt/molt-fetch.md %}#fetch-continuation) to retry failed or interrupted tasks from specific checkpoints. diff --git a/src/current/molt/molt-fetch-best-practices.md b/src/current/molt/molt-fetch-best-practices.md new file mode 100644 index 00000000000..22dfc35abea --- /dev/null +++ b/src/current/molt/molt-fetch-best-practices.md @@ -0,0 +1,69 @@ +--- +title: MOLT Fetch Best Practices +summary: Learn best practices for using MOLT Fetch to migrate data to CockroachDB. +toc: true +docs_area: migrate +--- + +## Test and validate + +To verify that your connections and configuration work properly, run MOLT Fetch in a staging environment before migrating any data in production. Use a test or development environment that closely resembles production. + +## Configure the source database and connection + +- To prevent connections from terminating prematurely during the [data export phase]({% link molt/molt-fetch.md %}#data-export-phase), set the following to high values on the source database: + + - **Maximum allowed number of connections.** MOLT Fetch can export data across multiple connections. The number of connections it will create is the number of shards ([`--export-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags)) multiplied by the number of tables ([`--table-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags)) being exported concurrently. + + {{site.data.alerts.callout_info}} + With the default numerical range sharding, only tables with [primary key]({% link {{ site.current_cloud_version }}/primary-key.md %}) types of [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) can be sharded. PostgreSQL users can enable [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) to use statistics-based sharding for tables with primary keys of any data type. For details, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding). + {{site.data.alerts.end}} + + - **Maximum lifetime of a connection.** + +- If a PostgreSQL database is set as a [source]({% link molt/molt-fetch.md %}#source-and-target-databases), ensure that [`idle_in_transaction_session_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT) on PostgreSQL is either disabled or set to a value longer than the duration of the [data export phase]({% link molt/molt-fetch.md %}#data-export-phase). Otherwise, the connection will be prematurely terminated. To estimate the time needed to export the PostgreSQL tables, you can perform a dry run and sum the value of [`molt_fetch_table_export_duration_ms`]({% link molt/molt-fetch.md %}#monitoring) for all exported tables. + +## Optimize performance + +- {% include molt/molt-drop-constraints-indexes.md %} + +- For PostgreSQL sources using [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), run [`ANALYZE`]({% link {{ site.current_cloud_version }}/create-statistics.md %}) on source tables before migration to ensure optimal shard distribution. This is especially important for large tables where even distribution can significantly improve export performance. + +- To prevent memory outages during `READ COMMITTED` [data export]({% link molt/molt-fetch.md %}#data-export-phase) of tables with large rows, estimate the amount of memory used to export a table: + + ~~~ + --row-batch-size * --export-concurrency * average size of the table rows + ~~~ + + If you are exporting more than one table at a time (i.e., [`--table-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) is set higher than `1`), add the estimated memory usage for the tables with the largest row sizes. Ensure that you have sufficient memory to run `molt fetch`, and adjust `--row-batch-size` accordingly. For details on how concurrency and sharding interact, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding). + +- If a table in the source database is much larger than the other tables, [filter and export the largest table]({% link molt/molt-fetch.md %}#schema-and-table-selection) in its own `molt fetch` task. Repeat this for each of the largest tables. Then export the remaining tables in another task. + +- Ensure that the machine running MOLT Fetch is large enough to handle the amount of data being migrated. Fetch performance can sometimes be limited by available resources, but should always be making progress. To identify possible resource constraints, observe the `molt_fetch_rows_exported` [metric]({% link molt/molt-fetch.md %}#monitoring) for decreases in the number of rows being processed. You can use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view metrics. For details on optimizing export performance through sharding, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding). + +## Import and continuation handling + +- When using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#data-load-mode) during the [data import phase]({% link molt/molt-fetch.md %}#data-import-phase) to load tables into CockroachDB, if the fetch task terminates before the import job completes, the hanging import job on the target database will keep the table offline. To make this table accessible again, [manually resume or cancel the job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs). Then resume `molt fetch` using [continuation]({% link molt/molt-fetch.md %}#fetch-continuation), or restart the task from the beginning. + +## Security + +Cockroach Labs strongly recommends the following security practices. + +### Connection security + +{% include molt/molt-secure-connection-strings.md %} + +{{site.data.alerts.callout_info}} +By default, insecure connections (i.e., `sslmode=disable` on PostgreSQL; `sslmode` not set on MySQL) are disallowed. When using an insecure connection, `molt fetch` returns an error. To override this check, you can enable the `--allow-tls-mode-disable` flag. Do this **only** when testing, or if a secure SSL/TLS connection to the source or target database is not possible. +{{site.data.alerts.end}} + +### Cloud storage security + +{% include molt/fetch-secure-cloud-storage.md %} + +## See also + +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [Migration Overview]({% link molt/migration-overview.md %}) +- [MOLT Replicator]({% link molt/molt-replicator.md %}) +- [MOLT Verify]({% link molt/molt-verify.md %}) diff --git a/src/current/molt/molt-fetch-commands-and-flags.md b/src/current/molt/molt-fetch-commands-and-flags.md new file mode 100644 index 00000000000..f01967293a6 --- /dev/null +++ b/src/current/molt/molt-fetch-commands-and-flags.md @@ -0,0 +1,87 @@ +--- +title: MOLT Fetch Commands and Flags +summary: Reference documentation for MOLT Fetch commands and flags. +toc: true +docs_area: migrate +--- + +## Commands + +| Command | Usage | +|---------|---------------------------------------------------------------------------------------------------| +| `fetch` | Start the fetch task. This loads data from a source database to a target CockroachDB database. | + +### Subcommands + +| Command | Usage | +|--------------|----------------------------------------------------------------------| +| `tokens list` | List active [continuation tokens]({% link molt/molt-fetch.md %}#list-active-continuation-tokens). | + +## Flags + +### Global flags + +| Flag | Description | +|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--source` | (Required) Connection string used to connect to the Oracle PDB (in a CDB/PDB architecture) or to a standalone database (non‑CDB). For details, refer to [Source and target databases]({% link molt/molt-fetch.md %}#source-and-target-databases). | +| `--source-cdb` | Connection string for the Oracle container database (CDB) when using a multitenant (CDB/PDB) architecture. Omit this flag on a non‑multitenant Oracle database. For details, refer to [Source and target databases]({% link molt/molt-fetch.md %}#source-and-target-databases). | +| `--target` | (Required) Connection string for the target database. For details, refer to [Source and target databases]({% link molt/molt-fetch.md %}#source-and-target-databases). | +| `--allow-tls-mode-disable` | Allow insecure connections to databases. Secure SSL/TLS connections should be used by default. This should be enabled **only** if secure SSL/TLS connections to the source or target database are not possible. | +| `--assume-role` | Service account to use for assume role authentication. `--use-implicit-auth` must be included. For example, `--assume-role='user-test@cluster-ephemeral.iam.gserviceaccount.com' --use-implicit-auth`. For details, refer to [Cloud Storage Authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}). | +| `--bucket-path` | The path within the [cloud storage]({% link molt/molt-fetch.md %}#bucket-path) bucket where intermediate files are written (e.g., `'s3://bucket/path'` or `'gs://bucket/path'`). Only the URL path is used; query parameters (e.g., credentials) are ignored. To pass in query parameters, use the appropriate flags: `--assume-role`, `--import-region`, `--use-implicit-auth`. | +| `--case-sensitive` | Toggle case sensitivity when comparing table and column names on the source and target. To disable case sensitivity, set `--case-sensitive=false`. If `=` is **not** included (e.g., `--case-sensitive false`), the flag is interpreted as `--case-sensitive` (i.e., `--case-sensitive=true`).

**Default:** `false` | +| `--cleanup` | Whether to delete intermediate files after moving data using [cloud or local storage]({% link molt/molt-fetch.md %}#data-path). **Note:** Cleanup does not occur on [continuation]({% link molt/molt-fetch.md %}#fetch-continuation). | +| `--compression` | Compression method for data when using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#data-load-mode) (`gzip`/`none`).

**Default:** `gzip` | +| `--continuation-file-name` | Restart fetch at the specified filename if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation]({% link molt/molt-fetch.md %}#fetch-continuation). | +| `--continuation-token` | Restart fetch at a specific table, using the specified continuation token, if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation]({% link molt/molt-fetch.md %}#fetch-continuation). | +| `--crdb-pts-duration` | The duration for which each timestamp used in data export from a CockroachDB source is protected from garbage collection. This ensures that the data snapshot remains consistent. For example, if set to `24h`, each timestamp is protected for 24 hours from the initiation of the export job. This duration is extended at regular intervals specified in `--crdb-pts-refresh-interval`.

**Default:** `24h0m0s` | +| `--crdb-pts-refresh-interval` | The frequency at which the protected timestamp's validity is extended. This interval maintains protection of the data snapshot until data export from a CockroachDB source is completed. For example, if set to `10m`, the protected timestamp's expiration will be extended by the duration specified in `--crdb-pts-duration` (e.g., `24h`) every 10 minutes while export is not complete.

**Default:** `10m0s` | +| `--direct-copy` | Enables [direct copy]({% link molt/molt-fetch.md %}#direct-copy), which copies data directly from source to target without using an intermediate store. | +| `--export-concurrency` | Number of shards to export at a time per table, each on a dedicated thread. This controls how many shards are created for each individual table during the [data export phase]({% link molt/molt-fetch.md %}#data-export-phase) and is distinct from `--table-concurrency`, which controls how many tables are processed simultaneously. The total number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`. Tables can be sharded with a range-based or stats-based mechanism. For details, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding).

**Default:** `4` | +| `--export-retry-max-attempts` | Maximum number of retry attempts for source export queries when connection failures occur. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `3` | +| `--export-retry-max-duration` | Maximum total duration for retrying source export queries. If `0`, no time limit is enforced. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `5m0s` | +| `--filter-path` | Path to a JSON file defining row-level filters for the [data import phase]({% link molt/molt-fetch.md %}#data-import-phase). Refer to [Selective data movement]({% link molt/molt-fetch.md %}#selective-data-movement). | +| `--fetch-id` | Restart fetch task corresponding to the specified ID. If `--continuation-file-name` or `--continuation-token` are not specified, fetch restarts for all failed tables. | +| `--flush-rows` | Number of rows before the source data is flushed to intermediate files. **Note:** If `--flush-size` is also specified, the fetch behavior is based on the flag whose criterion is met first. | +| `--flush-size` | Size (in bytes) before the source data is flushed to intermediate files. **Note:** If `--flush-rows` is also specified, the fetch behavior is based on the flag whose criterion is met first. | +| `--ignore-replication-check` | Skip querying for replication checkpoints such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle. This option is intended for use during bulk load migrations or when doing a one-time data export from a read replica. | +| `--import-batch-size` | The number of files to be imported at a time to the target database during the [data import phase]({% link molt/molt-fetch.md %}#data-import-phase). This applies only when using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#data-load-mode) for data movement. **Note:** Increasing this value can improve the performance of full-scan queries on the target database shortly after fetch completes, but very high values are not recommended. If any individual file in the import batch fails, you must [retry]({% link molt/molt-fetch.md %}#fetch-continuation) the entire batch.

**Default:** `1000` | +| `--import-region` | The region of the [cloud storage]({% link molt/molt-fetch.md %}#bucket-path) bucket. This applies only to [Amazon S3 buckets]({% link molt/molt-fetch.md %}#bucket-path). Set this flag only if you need to specify an `AWS_REGION` explicitly when using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#data-load-mode) for data movement. For example, `--import-region=ap-south-1`. | +| `--local-path` | The path within the [local file server]({% link molt/molt-fetch.md %}#local-path) where intermediate files are written (e.g., `data/migration/cockroach`). `--local-path-listen-addr` must be specified. | +| `--local-path-crdb-access-addr` | Address of a [local file server]({% link molt/molt-fetch.md %}#local-path) that is **publicly accessible**. This flag is only necessary if CockroachDB cannot reach the local address specified with `--local-path-listen-addr` (e.g., when moving data to a CockroachDB {{ site.data.products.cloud }} deployment). `--local-path` and `--local-path-listen-addr` must be specified.

**Default:** Value of `--local-path-listen-addr`. | +| `--local-path-listen-addr` | Write intermediate files to a [local file server]({% link molt/molt-fetch.md %}#local-path) at the specified address (e.g., `'localhost:3000'`). `--local-path` must be specified. | +| `--log-file` | Write messages to the specified log filename. If no filename is provided, messages write to `fetch-{datetime}.log`. If `"stdout"` is provided, messages write to `stdout`. | +| `--logging` | Level at which to log messages (`trace`/`debug`/`info`/`warn`/`error`/`fatal`/`panic`).

**Default:** `info` | +| `--metrics-listen-addr` | Address of the Prometheus metrics endpoint, which has the path `{address}/metrics`. For details on important metrics to monitor, refer to [Monitoring]({% link molt/molt-fetch-monitoring.md %}).

**Default:** `'127.0.0.1:3030'` | +| `--mode` | Configure the MOLT Fetch behavior: `data-load`, `export-only`, or `import-only`. For details, refer to [Fetch mode]({% link molt/molt-fetch.md %}#fetch-mode).

**Default:** `data-load` | +| `--non-interactive` | Run the fetch task without interactive prompts. This is recommended **only** when running `molt fetch` in an automated process (i.e., a job or continuous integration). | +| `--pprof-listen-addr` | Address of the pprof endpoint.

**Default:** `'127.0.0.1:3031'` | +| `--row-batch-size` | Number of rows per shard to export at a time. For details on sharding, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding). See also [Best practices]({% link molt/molt-fetch-best-practices.md %}).

**Default:** `100000` | +| `--schema-filter` | Move schemas that match a specified [regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | +| `--skip-pk-check` | Skip primary-key matching to allow data load when source or target tables have missing or mismatched primary keys. Disables sharding and bypasses `--export-concurrency` and `--row-batch-size` settings. Refer to [Skip primary key matching]({% link molt/molt-fetch.md %}#skip-primary-key-matching).

**Default:** `false` | +| `--table-concurrency` | Number of tables to export at a time. The number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`.

**Default:** `4` | +| `--table-exclusion-filter` | Exclude tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

This value **cannot** be set to `'.*'`, which would cause every table to be excluded.

**Default:** Empty string | +| `--table-filter` | Move tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | +| `--table-handling` | How tables are initialized on the target database (`none`/`drop-on-target-and-recreate`/`truncate-if-exists`). For details, see [Target table handling]({% link molt/molt-fetch.md %}#target-table-handling).

**Default:** `none` | +| `--transformations-file` | Path to a JSON file that defines transformations to be performed on the target schema during the fetch task. Refer to [Transformations]({% link molt/molt-fetch.md %}#transformations). | +| `--type-map-file` | Path to a JSON file that contains explicit type mappings for automatic schema creation, when enabled with `--table-handling drop-on-target-and-recreate`. For details on the JSON format and valid type mappings, see [type mapping]({% link molt/molt-fetch.md %}#type-mapping). | +| `--use-console-writer` | Use the console writer, which has cleaner log output but introduces more latency.

**Default:** `false` (log as structured JSON) | +| `--use-copy` | Use [`COPY FROM`]({% link molt/molt-fetch.md %}#data-load-mode) to move data. This makes tables queryable during data load, but is slower than using `IMPORT INTO`. For details, refer to [Data movement]({% link molt/molt-fetch.md %}#data-load-mode). | +| `--use-implicit-auth` | Use [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}) for [cloud storage]({% link molt/molt-fetch.md %}#bucket-path) URIs. | +| `--use-stats-based-sharding` | Enable statistics-based sharding for PostgreSQL sources. This allows sharding of tables with primary keys of any data type and can create more evenly distributed shards compared to the default numerical range sharding. Requires PostgreSQL 11+ and access to `pg_stats`. For details, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding). | + + +### `tokens list` flags + +| Flag | Description | +|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------| +| `--conn-string` | (Required) Connection string for the target database. For details, see [List active continuation tokens]({% link molt/molt-fetch.md %}#list-active-continuation-tokens). | +| `-n`, `--num-results` | Number of results to return. | + +## See also + +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [MOLT Fetch Best Practices]({% link molt/molt-fetch-best-practices.md %}) +- [MOLT Fetch Monitoring]({% link molt/molt-fetch-monitoring.md %}) +- [MOLT Fetch Troubleshooting]({% link molt/molt-fetch-troubleshooting.md %}) +- [Migration Overview]({% link molt/migration-overview.md %}) diff --git a/src/current/molt/molt-fetch-installation.md b/src/current/molt/molt-fetch-installation.md new file mode 100644 index 00000000000..d8d416f70b5 --- /dev/null +++ b/src/current/molt/molt-fetch-installation.md @@ -0,0 +1,52 @@ +--- +title: MOLT Fetch Installation +summary: Learn how to install MOLT Fetch and configure prerequisites for data migration. +toc: true +docs_area: migrate +--- + +## Prerequisites + +### Supported databases + +The following source databases are supported: + +- PostgreSQL 11-16 +- MySQL 5.7, 8.0 and later +- Oracle Database 19c (Enterprise Edition) and 21c (Express Edition) + +### Database configuration + +Ensure that the source and target schemas are identical, unless you enable automatic schema creation with the [`drop-on-target-and-recreate`]({% link molt/molt-fetch.md %}#target-table-handling) option. If you are creating the target schema manually, review the behaviors in [Mismatch handling]({% link molt/molt-fetch.md %}#mismatch-handling). + +{{site.data.alerts.callout_info}} +MOLT Fetch does not support migrating sequences. If your source database contains sequences, refer to the [guidance on indexing with sequential keys]({% link {{site.current_cloud_version}}/sql-faqs.md %}#how-do-i-generate-unique-slowly-increasing-sequential-numbers-in-cockroachdb). If a sequential key is necessary in your CockroachDB table, you must create it manually. After using MOLT Fetch to load the data onto the target, but before cutover, make sure to update each sequence's current value using [`setval()`]({% link {{site.current_cloud_version}}/functions-and-operators.md %}#sequence-functions) so that new inserts continue from the correct point. +{{site.data.alerts.end}} + +If you plan to use cloud storage for the data migration, follow [Cloud storage security]({% link molt/molt-fetch-best-practices.md %}#cloud-storage-security) best practices. + +### User permissions + +The SQL user running MOLT Fetch requires specific privileges on both the source and target databases: + +| Database | Required Privileges | Details | +|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------| +| PostgreSQL source |
  • `CONNECT` on database.
  • `USAGE` on schema.
  • `SELECT` on tables to migrate.
| [Create PostgreSQL migration user]({% link molt/migrate-bulk-load.md %}#create-migration-user-on-source-database) | +| MySQL source |
  • `SELECT` on tables to migrate.
| [Create MySQL migration user]({% link molt/migrate-bulk-load.md %}?filters=mysql#create-migration-user-on-source-database) | +| Oracle source |
  • `CONNECT` and `CREATE SESSION`.
  • `SELECT` and `FLASHBACK` on tables to migrate.
  • `SELECT` on metadata views (`ALL_USERS`, `DBA_USERS`, `DBA_OBJECTS`, `DBA_SYNONYMS`, `DBA_TABLES`).
| [Create Oracle migration user]({% link molt/migrate-bulk-load.md %}?filters=oracle#create-migration-user-on-source-database) | +| CockroachDB target |
  • `ALL` on target database.
  • `CREATE` on schema.
  • `SELECT`, `INSERT`, `UPDATE`, `DELETE` on target tables.
  • For `IMPORT INTO`: `SELECT`, `INSERT`, `DROP` on target tables. Optionally `EXTERNALIOIMPLICITACCESS` for implicit cloud storage authentication.
  • For `COPY FROM`: `admin` role.
| [Create CockroachDB user]({% link molt/migrate-bulk-load.md %}#create-the-sql-user) | + +## Installation + +{% include molt/molt-install.md %} + +### Docker usage + +{% include molt/molt-docker.md %} + +## See also + +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [MOLT Fetch Commands and Flags]({% link molt/molt-fetch-commands-and-flags.md %}) +- [MOLT Fetch Best Practices]({% link molt/molt-fetch-best-practices.md %}) +- [Migration Overview]({% link molt/migration-overview.md %}) diff --git a/src/current/molt/molt-fetch-monitoring.md b/src/current/molt/molt-fetch-monitoring.md new file mode 100644 index 00000000000..8adde477856 --- /dev/null +++ b/src/current/molt/molt-fetch-monitoring.md @@ -0,0 +1,31 @@ +--- +title: MOLT Fetch Monitoring +summary: Learn how to monitor MOLT Fetch during data migration using Prometheus metrics. +toc: true +docs_area: migrate +--- + +## Metrics + +By default, MOLT Fetch exports [Prometheus](https://prometheus.io/) metrics at `127.0.0.1:3030/metrics`. You can configure this endpoint with the `--metrics-listen-addr` [flag]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags). + +Cockroach Labs recommends monitoring the following metrics: + +| Metric Name | Description | +|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------| +| `molt_fetch_num_tables` | Number of tables that will be moved from the source. | +| `molt_fetch_num_task_errors` | Number of errors encountered by the fetch task. | +| `molt_fetch_overall_duration` | Duration (in seconds) of the fetch task. | +| `molt_fetch_rows_exported` | Number of rows that have been exported from a table. For example:
`molt_fetch_rows_exported{table="public.users"}` | +| `molt_fetch_rows_imported` | Number of rows that have been imported from a table. For example:
`molt_fetch_rows_imported{table="public.users"}` | +| `molt_fetch_table_export_duration_ms` | Duration (in milliseconds) of a table's export. For example:
`molt_fetch_table_export_duration_ms{table="public.users"}` | +| `molt_fetch_table_import_duration_ms` | Duration (in milliseconds) of a table's import. For example:
`molt_fetch_table_import_duration_ms{table="public.users"}` | + +You can also use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view the preceding metrics. + +## See also + +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [MOLT Fetch Best Practices]({% link molt/molt-fetch-best-practices.md %}) +- [Migration Overview]({% link molt/migration-overview.md %}) +- [MOLT Replicator]({% link molt/molt-replicator.md %}) diff --git a/src/current/molt/molt-fetch-troubleshooting.md b/src/current/molt/molt-fetch-troubleshooting.md new file mode 100644 index 00000000000..59555ce78be --- /dev/null +++ b/src/current/molt/molt-fetch-troubleshooting.md @@ -0,0 +1,21 @@ +--- +title: MOLT Fetch Troubleshooting +summary: Troubleshoot common issues when using MOLT Fetch for data migration. +toc: true +docs_area: migrate +--- + +
+ + + +
+ +{% include molt/molt-troubleshooting-fetch.md %} + +## See also + +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [Migration Overview]({% link molt/migration-overview.md %}) +- [MOLT Replicator]({% link molt/molt-replicator.md %}) +- [MOLT Verify]({% link molt/molt-verify.md %}) diff --git a/src/current/molt/molt-fetch.md b/src/current/molt/molt-fetch.md index 02052c16583..e2336ebb41f 100644 --- a/src/current/molt/molt-fetch.md +++ b/src/current/molt/molt-fetch.md @@ -9,50 +9,11 @@ MOLT Fetch moves data from a source database into CockroachDB as part of a [data MOLT Fetch uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to move the source data to cloud storage (Google Cloud Storage, Amazon S3, or Azure Blob Storage), a local file server, or local memory. Once the data is exported, MOLT Fetch loads the data into a target CockroachDB database. For details, refer to [Migration phases](#migration-phases). -## Terminology + ## Migration phases @@ -60,100 +21,26 @@ MOLT Fetch operates in distinct phases to move data from source databases to Coc ### Data export phase -MOLT Fetch connects to the source database and exports table data to intermediate storage. Data is written to [cloud storage](#bucket-path) (Amazon S3, Google Cloud Storage, Azure Blob Storage), a [local file server](#local-path), or [directly to CockroachDB memory](#direct-copy). Multiple tables and table shards can be exported simultaneously using [`--table-concurrency`](#global-flags) and [`--export-concurrency`](#global-flags), with large tables divided into shards for parallel processing. For details, refer to: +MOLT Fetch connects to the source database and exports table data to intermediate storage. Data is written to [cloud storage](#bucket-path) (Amazon S3, Google Cloud Storage, Azure Blob Storage), a [local file server](#local-path), or [directly to CockroachDB memory](#direct-copy). Multiple tables and table shards can be exported simultaneously using [`--table-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) and [`--export-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), with large tables divided into shards for parallel processing. For details, refer to: - [Fetch mode](#fetch-mode) - [Table sharding](#table-sharding) ### Data import phase -MOLT Fetch loads the exported data into the target CockroachDB database. The process uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) (faster, tables offline during import) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) (slower, tables remain queryable) to move data. Data files are imported in configurable batches using [`--import-batch-size`](#global-flags), and target tables can be automatically created, truncated, or left unchanged based on [`--table-handling`](#global-flags) settings. For details, refer to: +MOLT Fetch loads the exported data into the target CockroachDB database. The process uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) (faster, tables offline during import) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) (slower, tables remain queryable) to move data. Data files are imported in configurable batches using [`--import-batch-size`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), and target tables can be automatically created, truncated, or left unchanged based on [`--table-handling`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) settings. For details, refer to: - [Data movement](#data-load-mode) - [Target table handling](#target-table-handling) -## Commands - -| Command | Usage | -|---------|---------------------------------------------------------------------------------------------------| -| `fetch` | Start the fetch task. This loads data from a source database to a target CockroachDB database. | - -### Subcommands - -| Command | Usage | -|--------------|----------------------------------------------------------------------| -| `tokens list` | List active [continuation tokens](#list-active-continuation-tokens). | - -## Flags - -### Global flags - -| Flag | Description | -|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `--source` | (Required) Connection string used to connect to the Oracle PDB (in a CDB/PDB architecture) or to a standalone database (non‑CDB). For details, refer to [Source and target databases](#source-and-target-databases). | -| `--source-cdb` | Connection string for the Oracle container database (CDB) when using a multitenant (CDB/PDB) architecture. Omit this flag on a non‑multitenant Oracle database. For details, refer to [Source and target databases](#source-and-target-databases). | -| `--target` | (Required) Connection string for the target database. For details, refer to [Source and target databases](#source-and-target-databases). | -| `--allow-tls-mode-disable` | Allow insecure connections to databases. Secure SSL/TLS connections should be used by default. This should be enabled **only** if secure SSL/TLS connections to the source or target database are not possible. | -| `--assume-role` | Service account to use for assume role authentication. `--use-implicit-auth` must be included. For example, `--assume-role='user-test@cluster-ephemeral.iam.gserviceaccount.com' --use-implicit-auth`. For details, refer to [Cloud Storage Authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}). | -| `--bucket-path` | The path within the [cloud storage](#bucket-path) bucket where intermediate files are written (e.g., `'s3://bucket/path'` or `'gs://bucket/path'`). Only the URL path is used; query parameters (e.g., credentials) are ignored. To pass in query parameters, use the appropriate flags: `--assume-role`, `--import-region`, `--use-implicit-auth`. | -| `--case-sensitive` | Toggle case sensitivity when comparing table and column names on the source and target. To disable case sensitivity, set `--case-sensitive=false`. If `=` is **not** included (e.g., `--case-sensitive false`), the flag is interpreted as `--case-sensitive` (i.e., `--case-sensitive=true`).

**Default:** `false` | -| `--cleanup` | Whether to delete intermediate files after moving data using [cloud or local storage](#data-path). **Note:** Cleanup does not occur on [continuation](#fetch-continuation). | -| `--compression` | Compression method for data when using [`IMPORT INTO`](#data-load-mode) (`gzip`/`none`).

**Default:** `gzip` | -| `--continuation-file-name` | Restart fetch at the specified filename if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation](#fetch-continuation). | -| `--continuation-token` | Restart fetch at a specific table, using the specified continuation token, if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation](#fetch-continuation). | -| `--crdb-pts-duration` | The duration for which each timestamp used in data export from a CockroachDB source is protected from garbage collection. This ensures that the data snapshot remains consistent. For example, if set to `24h`, each timestamp is protected for 24 hours from the initiation of the export job. This duration is extended at regular intervals specified in `--crdb-pts-refresh-interval`.

**Default:** `24h0m0s` | -| `--crdb-pts-refresh-interval` | The frequency at which the protected timestamp's validity is extended. This interval maintains protection of the data snapshot until data export from a CockroachDB source is completed. For example, if set to `10m`, the protected timestamp's expiration will be extended by the duration specified in `--crdb-pts-duration` (e.g., `24h`) every 10 minutes while export is not complete.

**Default:** `10m0s` | -| `--direct-copy` | Enables [direct copy](#direct-copy), which copies data directly from source to target without using an intermediate store. | -| `--export-concurrency` | Number of shards to export at a time per table, each on a dedicated thread. This controls how many shards are created for each individual table during the [data export phase](#data-export-phase) and is distinct from `--table-concurrency`, which controls how many tables are processed simultaneously. The total number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`. Tables can be sharded with a range-based or stats-based mechanism. For details, refer to [Table sharding](#table-sharding).

**Default:** `4` | -| `--export-retry-max-attempts` | Maximum number of retry attempts for source export queries when connection failures occur. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `3` | -| `--export-retry-max-duration` | Maximum total duration for retrying source export queries. If `0`, no time limit is enforced. Only supported for PostgreSQL and CockroachDB sources.

**Default:** `5m0s` | -| `--filter-path` | Path to a JSON file defining row-level filters for the [data import phase](#data-import-phase). Refer to [Selective data movement](#selective-data-movement). | -| `--fetch-id` | Restart fetch task corresponding to the specified ID. If `--continuation-file-name` or `--continuation-token` are not specified, fetch restarts for all failed tables. | -| `--flush-rows` | Number of rows before the source data is flushed to intermediate files. **Note:** If `--flush-size` is also specified, the fetch behavior is based on the flag whose criterion is met first. | -| `--flush-size` | Size (in bytes) before the source data is flushed to intermediate files. **Note:** If `--flush-rows` is also specified, the fetch behavior is based on the flag whose criterion is met first. | -| `--ignore-replication-check` | Skip querying for replication checkpoints such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle. This option is intended for use during bulk load migrations or when doing a one-time data export from a read replica. | -| `--import-batch-size` | The number of files to be imported at a time to the target database during the [data import phase](#data-import-phase). This applies only when using [`IMPORT INTO`](#data-load-mode) for data movement. **Note:** Increasing this value can improve the performance of full-scan queries on the target database shortly after fetch completes, but very high values are not recommended. If any individual file in the import batch fails, you must [retry](#fetch-continuation) the entire batch.

**Default:** `1000` | -| `--import-region` | The region of the [cloud storage](#bucket-path) bucket. This applies only to [Amazon S3 buckets](#bucket-path). Set this flag only if you need to specify an `AWS_REGION` explicitly when using [`IMPORT INTO`](#data-load-mode) for data movement. For example, `--import-region=ap-south-1`. | -| `--local-path` | The path within the [local file server](#local-path) where intermediate files are written (e.g., `data/migration/cockroach`). `--local-path-listen-addr` must be specified. | -| `--local-path-crdb-access-addr` | Address of a [local file server](#local-path) that is **publicly accessible**. This flag is only necessary if CockroachDB cannot reach the local address specified with `--local-path-listen-addr` (e.g., when moving data to a CockroachDB {{ site.data.products.cloud }} deployment). `--local-path` and `--local-path-listen-addr` must be specified.

**Default:** Value of `--local-path-listen-addr`. | -| `--local-path-listen-addr` | Write intermediate files to a [local file server](#local-path) at the specified address (e.g., `'localhost:3000'`). `--local-path` must be specified. | -| `--log-file` | Write messages to the specified log filename. If no filename is provided, messages write to `fetch-{datetime}.log`. If `"stdout"` is provided, messages write to `stdout`. | -| `--logging` | Level at which to log messages (`trace`/`debug`/`info`/`warn`/`error`/`fatal`/`panic`).

**Default:** `info` | -| `--metrics-listen-addr` | Address of the Prometheus metrics endpoint, which has the path `{address}/metrics`. For details on important metrics to monitor, refer to [Monitoring](#monitoring).

**Default:** `'127.0.0.1:3030'` | -| `--mode` | Configure the MOLT Fetch behavior: `data-load`, `export-only`, or `import-only`. For details, refer to [Fetch mode](#fetch-mode).

**Default:** `data-load` | -| `--non-interactive` | Run the fetch task without interactive prompts. This is recommended **only** when running `molt fetch` in an automated process (i.e., a job or continuous integration). | -| `--pprof-listen-addr` | Address of the pprof endpoint.

**Default:** `'127.0.0.1:3031'` | -| `--row-batch-size` | Number of rows per shard to export at a time. For details on sharding, refer to [Table sharding](#table-sharding). See also [Best practices](#best-practices).

**Default:** `100000` | -| `--schema-filter` | Move schemas that match a specified [regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | -| `--skip-pk-check` | Skip primary-key matching to allow data load when source or target tables have missing or mismatched primary keys. Disables sharding and bypasses `--export-concurrency` and `--row-batch-size` settings. Refer to [Skip primary key matching](#skip-primary-key-matching).

**Default:** `false` | -| `--table-concurrency` | Number of tables to export at a time. The number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`.

**Default:** `4` | -| `--table-exclusion-filter` | Exclude tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

This value **cannot** be set to `'.*'`, which would cause every table to be excluded.

**Default:** Empty string | -| `--table-filter` | Move tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

**Default:** `'.*'` | -| `--table-handling` | How tables are initialized on the target database (`none`/`drop-on-target-and-recreate`/`truncate-if-exists`). For details, see [Target table handling](#target-table-handling).

**Default:** `none` | -| `--transformations-file` | Path to a JSON file that defines transformations to be performed on the target schema during the fetch task. Refer to [Transformations](#transformations). | -| `--type-map-file` | Path to a JSON file that contains explicit type mappings for automatic schema creation, when enabled with `--table-handling drop-on-target-and-recreate`. For details on the JSON format and valid type mappings, see [type mapping](#type-mapping). | -| `--use-console-writer` | Use the console writer, which has cleaner log output but introduces more latency.

**Default:** `false` (log as structured JSON) | -| `--use-copy` | Use [`COPY FROM`](#data-load-mode) to move data. This makes tables queryable during data load, but is slower than using `IMPORT INTO`. For details, refer to [Data movement](#data-load-mode). | -| `--use-implicit-auth` | Use [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}) for [cloud storage](#bucket-path) URIs. | -| `--use-stats-based-sharding` | Enable statistics-based sharding for PostgreSQL sources. This allows sharding of tables with primary keys of any data type and can create more evenly distributed shards compared to the default numerical range sharding. Requires PostgreSQL 11+ and access to `pg_stats`. For details, refer to [Table sharding](#table-sharding). | - - -### `tokens list` flags - -| Flag | Description | -|-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------| -| `--conn-string` | (Required) Connection string for the target database. For details, see [List active continuation tokens](#list-active-continuation-tokens). | -| `-n`, `--num-results` | Number of results to return. | - - ## Usage -The following sections describe how to use the `molt fetch` [flags](#flags). +The following sections describe how to use the `molt fetch` [flags]({% link molt/molt-fetch-commands-and-flags.md %}). ### Source and target databases {{site.data.alerts.callout_success}} -Follow the recommendations in [Connection security](#connection-security). +Follow the recommendations in [Connection security]({% link molt/molt-fetch-best-practices.md %}#connection-security). {{site.data.alerts.end}} `--source` specifies the connection string of the source database. @@ -225,7 +112,7 @@ MOLT Fetch can use either [`IMPORT INTO`]({% link {{site.current_cloud_version}} By default, MOLT Fetch uses `IMPORT INTO`: -- `IMPORT INTO` achieves the highest throughput, but [requires taking the CockroachDB tables **offline**]({% link {{site.current_cloud_version}}/import-into.md %}#considerations) to achieve its import speed. Tables are taken back online once an [import job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs) completes successfully. See [Best practices](#best-practices). +- `IMPORT INTO` achieves the highest throughput, but [requires taking the CockroachDB tables **offline**]({% link {{site.current_cloud_version}}/import-into.md %}#considerations) to achieve its import speed. Tables are taken back online once an [import job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs) completes successfully. See [Best practices]({% link molt/molt-fetch-best-practices.md %}). - `IMPORT INTO` supports compression using the `--compression` flag, which reduces the amount of storage used. `--use-copy` configures MOLT Fetch to use `COPY FROM`: @@ -249,14 +136,14 @@ To control the number of shards created per table, use the `--export-concurrency ~~~ {{site.data.alerts.callout_success}} -For performance considerations with concurrency settings, refer to [Best practices](#best-practices). +For performance considerations with concurrency settings, refer to [Best practices]({% link molt/molt-fetch-best-practices.md %}). {{site.data.alerts.end}} Two sharding mechanisms are available: - **Range-based sharding (default):** Tables are divided based on numerical ranges found in primary key values. Only tables with [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) primary keys can use range-based sharding. Tables with other primary key data types export as a single shard. -- **Stats-based sharding (PostgreSQL only):** Enable with [`--use-stats-based-sharding`](#global-flags) for PostgreSQL 11+ sources. Tables are divided by analyzing the [`pg_stats`](https://www.postgresql.org/docs/current/view-pg-stats.htm) view to create more evenly distributed shards, up to a maximum of 200 shards. Primary keys of any data type are supported. +- **Stats-based sharding (PostgreSQL only):** Enable with [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) for PostgreSQL 11+ sources. Tables are divided by analyzing the [`pg_stats`](https://www.postgresql.org/docs/current/view-pg-stats.htm) view to create more evenly distributed shards, up to a maximum of 200 shards. Primary keys of any data type are supported. Stats-based sharding requires that the user has `SELECT` permissions on source tables and on each table's `pg_stats` view. The latter permission is automatically granted to users that can read the table. @@ -298,7 +185,7 @@ The number of shards is dependent on the number of distinct values in the first number of shards formed: {num_shards_formed} is not equal to number of shards requested: {num_shards_requested} for table {table_name} ~~~ -Because stats-based sharding analyzes the entire table, running `--use-stats-based-sharding` with [`--filter-path`](#global-flags) (refer to [Selective data movement](#selective-data-movement)) will cause imbalanced shards to form. +Because stats-based sharding analyzes the entire table, running `--use-stats-based-sharding` with [`--filter-path`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) (refer to [Selective data movement](#selective-data-movement)) will cause imbalanced shards to form. ### Data path @@ -307,10 +194,10 @@ MOLT Fetch can move the source data to CockroachDB via [cloud storage](#bucket-p #### Bucket path {{site.data.alerts.callout_success}} -Only the path specified in `--bucket-path` is used. Query parameters, such as credentials, are ignored. To authenticate cloud storage, follow the steps in [Secure cloud storage](#cloud-storage-security). +Only the path specified in `--bucket-path` is used. Query parameters, such as credentials, are ignored. To authenticate cloud storage, follow the steps in [Secure cloud storage]({% link molt/molt-fetch-best-practices.md %}#cloud-storage-security). {{site.data.alerts.end}} -`--bucket-path` instructs MOLT Fetch to write intermediate files to a path within [Google Cloud Storage](https://cloud.google.com/storage/docs/buckets), [Amazon S3](https://aws.amazon.com/s3/), or [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) to which you have the necessary permissions. Use additional [flags](#global-flags), shown in the following examples, to specify authentication or region parameters as required for bucket access. +`--bucket-path` instructs MOLT Fetch to write intermediate files to a path within [Google Cloud Storage](https://cloud.google.com/storage/docs/buckets), [Amazon S3](https://aws.amazon.com/s3/), or [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) to which you have the necessary permissions. Use additional [flags]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), shown in the following examples, to specify authentication or region parameters as required for bucket access. Connect to a Google Cloud Storage bucket with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#google-cloud-storage-implicit) and [assume role]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#set-up-google-cloud-storage-assume-role): @@ -803,22 +690,6 @@ Use the `cdc_cursor` value as the checkpoint for MySQL or Oracle replication wit You can also use the `cdc_cursor` value with an external change data capture (CDC) tool to continuously replicate subsequent changes from the source database to CockroachDB. -## Security - -Cockroach Labs strongly recommends the following security practices. - -### Connection security - -{% include molt/molt-secure-connection-strings.md %} - -{{site.data.alerts.callout_info}} -By default, insecure connections (i.e., `sslmode=disable` on PostgreSQL; `sslmode` not set on MySQL) are disallowed. When using an insecure connection, `molt fetch` returns an error. To override this check, you can enable the `--allow-tls-mode-disable` flag. Do this **only** when testing, or if a secure SSL/TLS connection to the source or target database is not possible. -{{site.data.alerts.end}} - -### Cloud storage security - -{% include molt/fetch-secure-cloud-storage.md %} - ## Common workflows ### Bulk data load @@ -920,84 +791,12 @@ The output will include a `cdc_cursor` value at the end of the fetch task: Use this `cdc_cursor` value when starting MOLT Replicator to ensure replication begins from the correct position. For detailed steps, refer to [Load and replicate]({% link molt/migrate-load-replicate.md %}). -## Monitoring - -### Metrics - -By default, MOLT Fetch exports [Prometheus](https://prometheus.io/) metrics at `127.0.0.1:3030/metrics`. You can configure this endpoint with the `--metrics-listen-addr` [flag](#global-flags). - -Cockroach Labs recommends monitoring the following metrics: - -| Metric Name | Description | -|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------| -| `molt_fetch_num_tables` | Number of tables that will be moved from the source. | -| `molt_fetch_num_task_errors` | Number of errors encountered by the fetch task. | -| `molt_fetch_overall_duration` | Duration (in seconds) of the fetch task. | -| `molt_fetch_rows_exported` | Number of rows that have been exported from a table. For example:
`molt_fetch_rows_exported{table="public.users"}` | -| `molt_fetch_rows_imported` | Number of rows that have been imported from a table. For example:
`molt_fetch_rows_imported{table="public.users"}` | -| `molt_fetch_table_export_duration_ms` | Duration (in milliseconds) of a table's export. For example:
`molt_fetch_table_export_duration_ms{table="public.users"}` | -| `molt_fetch_table_import_duration_ms` | Duration (in milliseconds) of a table's import. For example:
`molt_fetch_table_import_duration_ms{table="public.users"}` | - -You can also use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view the preceding metrics. - -## Best practices - -### Test and validate - -To verify that your connections and configuration work properly, run MOLT Fetch in a staging environment before migrating any data in production. Use a test or development environment that closely resembles production. - -### Configure the source database and connection - -- To prevent connections from terminating prematurely during the [data export phase](#data-export-phase), set the following to high values on the source database: - - - **Maximum allowed number of connections.** MOLT Fetch can export data across multiple connections. The number of connections it will create is the number of shards ([`--export-concurrency`](#global-flags)) multiplied by the number of tables ([`--table-concurrency`](#global-flags)) being exported concurrently. - - {{site.data.alerts.callout_info}} - With the default numerical range sharding, only tables with [primary key]({% link {{ site.current_cloud_version }}/primary-key.md %}) types of [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) can be sharded. PostgreSQL users can enable [`--use-stats-based-sharding`](#global-flags) to use statistics-based sharding for tables with primary keys of any data type. For details, refer to [Table sharding](#table-sharding). - {{site.data.alerts.end}} - - - **Maximum lifetime of a connection.** - -- If a PostgreSQL database is set as a [source](#source-and-target-databases), ensure that [`idle_in_transaction_session_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT) on PostgreSQL is either disabled or set to a value longer than the duration of the [data export phase](#data-export-phase). Otherwise, the connection will be prematurely terminated. To estimate the time needed to export the PostgreSQL tables, you can perform a dry run and sum the value of [`molt_fetch_table_export_duration_ms`](#monitoring) for all exported tables. - -### Optimize performance - -- {% include molt/molt-drop-constraints-indexes.md %} - -- For PostgreSQL sources using [`--use-stats-based-sharding`](#global-flags), run [`ANALYZE`]({% link {{ site.current_cloud_version }}/create-statistics.md %}) on source tables before migration to ensure optimal shard distribution. This is especially important for large tables where even distribution can significantly improve export performance. - -- To prevent memory outages during `READ COMMITTED` [data export](#data-export-phase) of tables with large rows, estimate the amount of memory used to export a table: - - ~~~ - --row-batch-size * --export-concurrency * average size of the table rows - ~~~ - - If you are exporting more than one table at a time (i.e., [`--table-concurrency`](#global-flags) is set higher than `1`), add the estimated memory usage for the tables with the largest row sizes. Ensure that you have sufficient memory to run `molt fetch`, and adjust `--row-batch-size` accordingly. For details on how concurrency and sharding interact, refer to [Table sharding](#table-sharding). - -- If a table in the source database is much larger than the other tables, [filter and export the largest table](#schema-and-table-selection) in its own `molt fetch` task. Repeat this for each of the largest tables. Then export the remaining tables in another task. - -- Ensure that the machine running MOLT Fetch is large enough to handle the amount of data being migrated. Fetch performance can sometimes be limited by available resources, but should always be making progress. To identify possible resource constraints, observe the `molt_fetch_rows_exported` [metric](#monitoring) for decreases in the number of rows being processed. You can use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view metrics. For details on optimizing export performance through sharding, refer to [Table sharding](#table-sharding). - -### Import and continuation handling - -- When using [`IMPORT INTO`](#data-load-mode) during the [data import phase](#data-import-phase) to load tables into CockroachDB, if the fetch task terminates before the import job completes, the hanging import job on the target database will keep the table offline. To make this table accessible again, [manually resume or cancel the job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs). Then resume `molt fetch` using [continuation](#fetch-continuation), or restart the task from the beginning. - -## Troubleshooting - -
- - - -
- -{% include molt/molt-troubleshooting-fetch.md %} - ## See also +- [MOLT Fetch Installation]({% link molt/molt-fetch-installation.md %}) +- [MOLT Fetch Commands and Flags]({% link molt/molt-fetch-commands-and-flags.md %}) +- [MOLT Fetch Monitoring]({% link molt/molt-fetch-monitoring.md %}) +- [MOLT Fetch Best Practices]({% link molt/molt-fetch-best-practices.md %}) +- [MOLT Fetch Troubleshooting]({% link molt/molt-fetch-troubleshooting.md %}) - [Migration Overview]({% link molt/migration-overview.md %}) -- [Migration Strategy]({% link molt/migration-strategy.md %}) -- [MOLT Replicator]({% link molt/molt-replicator.md %}) -- [MOLT Verify]({% link molt/molt-verify.md %}) -- [Load and replicate]({% link molt/migrate-load-replicate.md %}) -- [Resume Replication]({% link molt/migrate-resume-replication.md %}) -- [Migration Failback]({% link molt/migrate-failback.md %}) \ No newline at end of file +- [MOLT Replicator]({% link molt/molt-replicator.md %}) \ No newline at end of file diff --git a/src/current/releases/molt.md b/src/current/releases/molt.md index 734b47fa9c8..7de1bd43659 100644 --- a/src/current/releases/molt.md +++ b/src/current/releases/molt.md @@ -48,8 +48,8 @@ MOLT Fetch/Verify 1.3.2 is [available](#installation). MOLT Fetch/Verify 1.3.1 is [available](#installation). -- MOLT Fetch now supports [sharding]({% link molt/molt-fetch.md %}#table-sharding) of primary keys of any data type on PostgreSQL 11+ sources. This can be enabled with the [`--use-stats-based-sharding`]({% link molt/molt-fetch.md %}#global-flags) flag. -- Added the [`--ignore-replication-check`]({% link molt/molt-fetch.md %}#global-flags) flag to allow data loads with planned downtime and no replication setup. The `--pglogical-ignore-wal-check` flag has been removed. +- MOLT Fetch now supports [sharding]({% link molt/molt-fetch.md %}#table-sharding) of primary keys of any data type on PostgreSQL 11+ sources. This can be enabled with the [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag. +- Added the [`--ignore-replication-check`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag to allow data loads with planned downtime and no replication setup. The `--pglogical-ignore-wal-check` flag has been removed. - Added the `--enableParallelApplies` [replication flag]({% link molt/molt-replicator.md %}#flags) to enable parallel application of independent table groups during replication. By default, applies are synchronous. When enabled, this increases throughput at the cost of increased target pool and memory usage. - Improved cleanup logic for scheduled tasks to ensure progress reporting and prevent indefinite hangs. - Added parallelism gating to ensure the parallelism setting is smaller than the `targetMaxPoolSize`. This helps prevent a potential indefinite hang. @@ -100,7 +100,7 @@ MOLT Fetch/Verify 1.2.7 is [available](#installation). MOLT Fetch/Verify 1.2.6 is [available](#installation). -- Fixed a bug in [`--direct-copy` mode]({% link molt/molt-fetch.md %}#direct-copy) that occurred when [`--case-sensitive`]({% link molt/molt-fetch.md %}#global-flags) was set to `false` (default). Previously, the `COPY` query could use incorrect column names in some cases during data transfer, causing errors. The query now uses the correct column names. +- Fixed a bug in [`--direct-copy` mode]({% link molt/molt-fetch.md %}#direct-copy) that occurred when [`--case-sensitive`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) was set to `false` (default). Previously, the `COPY` query could use incorrect column names in some cases during data transfer, causing errors. The query now uses the correct column names. - Fixed a bug in how origin messages were handled during replication from PostgreSQL sources. This allows replication to successfully continue. - `ENUM` types can now be replicated from MySQL 8.0 sources. @@ -126,14 +126,14 @@ MOLT Fetch/Verify 1.2.4 is [available](#installation). MOLT Fetch/Verify 1.2.3 is [available](#installation). -- MOLT Fetch users can now set [`--table-concurrency`]({% link molt/molt-fetch.md %}#global-flags) and [`--export-concurrency`]({% link molt/molt-fetch.md %}#global-flags) to values greater than `1` for MySQL sources. -- MOLT Fetch now supports case-insensitive comparison of table and column names by default. Previously, case-sensitive comparisons could result in `no matching table on target` errors. To disable case-sensitive comparisons explicitly, set [`--case-sensitive=false`]({% link molt/molt-fetch.md %}#global-flags). If `=` is **not** included (e.g., `--case-sensitive false`), this is interpreted as `--case-sensitive` (i.e., `--case-sensitive=true`). +- MOLT Fetch users can now set [`--table-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) and [`--export-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) to values greater than `1` for MySQL sources. +- MOLT Fetch now supports case-insensitive comparison of table and column names by default. Previously, case-sensitive comparisons could result in `no matching table on target` errors. To disable case-sensitive comparisons explicitly, set [`--case-sensitive=false`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags). If `=` is **not** included (e.g., `--case-sensitive false`), this is interpreted as `--case-sensitive` (i.e., `--case-sensitive=true`). ## February 5, 2025 MOLT Fetch/Verify 1.2.2 is [available](#installation). -- Added an [`--import-region`]({% link molt/molt-fetch.md %}#global-flags) flag that is used to set the `AWS_REGION` query parameter explicitly in the [`s3` URL]({% link molt/molt-fetch.md %}#bucket-path). +- Added an [`--import-region`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag that is used to set the `AWS_REGION` query parameter explicitly in the [`s3` URL]({% link molt/molt-fetch.md %}#bucket-path). - Fixed the [`truncate-if-exists`]({% link molt/molt-fetch.md %}#target-table-handling) schema mode for cases where there are uppercase table or schema names. - Fixed an issue with unsigned `BIGINT` values overflowing in replication. - Added a `--schemaRefresh` [replication flag]({% link molt/molt-replicator.md %}#flags) that is used to configure the schema watcher refresh delay in the replication phase. Previously, the refresh delay was set to a constant value of 1 minute. Set the flag as follows: `--replicator-flags "--schemaRefresh {value}"`. @@ -142,7 +142,7 @@ MOLT Fetch/Verify 1.2.2 is [available](#installation). MOLT Fetch/Verify 1.2.1 is [available](#installation). -- MOLT Fetch users now can use [`--assume-role`]({% link molt/molt-fetch.md %}#global-flags) to specify a service account for assume role authentication to cloud storage. `--assume-role` must be used with `--use-implicit-auth`, or the flag will be ignored. +- MOLT Fetch users now can use [`--assume-role`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) to specify a service account for assume role authentication to cloud storage. `--assume-role` must be used with `--use-implicit-auth`, or the flag will be ignored. - MySQL 5.7 and later are now supported with MOLT Fetch replication modes. - Fetch replication mode now defaults to a less verbose `INFO` logging level. To specify `DEBUG` logging, pass in the `--replicator-flags '-v'` setting, or `--replicator-flags '-vv'` for trace logging. - MySQL columns of type `BIGINT UNSIGNED` or `SERIAL` are now auto-mapped to [`DECIMAL`]({% link {{ site.current_cloud_version }}/decimal.md %}) type in CockroachDB. MySQL regular `BIGINT` types are mapped to [`INT`]({% link {{ site.current_cloud_version }}/int.md %}) type in CockroachDB. @@ -155,10 +155,10 @@ MOLT Fetch/Verify 1.2.1 is [available](#installation). MOLT Fetch/Verify 1.2.0 is [available](#installation). - Added `failback` mode to MOLT Fetch, which allows the user to replicate changes on CockroachDB back to the initial source database. Failback is supported for MySQL and PostgreSQL databases. -- The [`--pprof-list-addr` flag]({% link molt/molt-fetch.md %}#global-flags), which specifies the address of the `pprof` endpoint, is now configurable. The default value is `'127.0.0.1:3031'`. +- The [`--pprof-list-addr` flag]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), which specifies the address of the `pprof` endpoint, is now configurable. The default value is `'127.0.0.1:3031'`. - [Fetch modes]({% link molt/molt-fetch.md %}#fetch-mode) involving replication now state that MySQL 8.0 and later are supported for replication between MySQL and CockroachDB. - [Partitioned tables]({% link molt/molt-fetch.md %}#transformations) can now be moved to CockroachDB using [`IMPORT INTO`]({% link {{ site.current_cloud_version }}/import-into.md %}). -- Improved logging for the [Fetch]({% link molt/molt-fetch.md %}) schema check phases under the `trace` logging level, which is set with [`--logging trace`]({% link molt/molt-fetch.md %}#global-flags). +- Improved logging for the [Fetch]({% link molt/molt-fetch.md %}) schema check phases under the `trace` logging level, which is set with [`--logging trace`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags). - Added a [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) for monitoring MOLT tasks. - Fetch now logs the name of the staging database in the target CockroachDB cluster used to store metadata for [replication modes]({% link molt/molt-fetch.md %}#fetch-mode). - String [primary keys]({% link {{ site.current_cloud_version }}/primary-key.md %}) that use `C` [collations]({% link {{ site.current_cloud_version }}/collate.md %}) on PostgreSQL can now be compared to the default `en_US.utf8` on CockroachDB. @@ -200,8 +200,8 @@ MOLT Fetch/Verify 1.1.4 is [available](#installation). MOLT Fetch/Verify 1.1.3 is [available](#installation). - `'infinity'::timestamp` values can now be moved with Fetch. -- Fixed an issue where connections were not being closed immediately after sharding was completed. This could lead to errors if the [maximum number of connections]({% link molt/molt-fetch.md %}#best-practices) was set to a low value. -- Fetch users can now exclude specific tables from migration using the [`--table-exclusion-filter` flag]({% link molt/molt-fetch.md %}#global-flags). +- Fixed an issue where connections were not being closed immediately after sharding was completed. This could lead to errors if the [maximum number of connections]({% link molt/molt-fetch-best-practices.md %}#configure-the-source-database-and-connection) was set to a low value. +- Fetch users can now exclude specific tables from migration using the [`--table-exclusion-filter` flag]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags). ## July 18, 2024 @@ -210,15 +210,15 @@ MOLT Fetch/Verify 1.1.2 is [available](#installation). - Fetch users can now specify columns to exclude from table migrations in order to migrate a subset of their data. This is supported in the schema creation, export, import, and direct copy phases. - Fetch now automatically maps a partitioned table from a PostgreSQL source to the target CockroachDB schema. - Fetch now supports column exclusions and computed column mappings via a new [transformations framework]({% link molt/molt-fetch.md %}#transformations). -- The new Fetch [`--transformations-file`]({% link molt/molt-fetch.md %}#global-flags) flag specifies a JSON file for schema/table/column transformations, which has validation utilities built in. +- The new Fetch [`--transformations-file`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag specifies a JSON file for schema/table/column transformations, which has validation utilities built in. ## July 10, 2024 MOLT Fetch/Verify 1.1.1 is [available](#installation). -- Fixed a bug that led to incorrect list continuation file behavior if a trailing slash was provided in [`--bucket-path`]({% link molt/molt-fetch.md %}#global-flags). +- Fixed a bug that led to incorrect list continuation file behavior if a trailing slash was provided in [`--bucket-path`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags). - Fixed a bug with extracting the filename from a failed import URL. Previously, an older filename was being used, which could result in duplicated data. Now, the filename that is used in import matches what is stored in the exceptions log table. -- Added a [`--use-implicit-auth`]({% link molt/molt-fetch.md %}#global-flags) flag that determines whether [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}) is used for cloud storage import URIs. +- Added a [`--use-implicit-auth`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag that determines whether [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}) is used for cloud storage import URIs. ## July 8, 2024 @@ -233,14 +233,14 @@ MOLT Fetch/Verify 1.1.0 is [available](#installation). MOLT Fetch/Verify 1.0.0 is [available](#installation). -- Renamed the `--table-splits` flag to [`--concurrency-per-table`]({% link molt/molt-fetch.md %}#global-flags), which is more descriptive. -- Increased the default value of [`--import-batch-size`]({% link molt/molt-fetch.md %}#global-flags) to `1000`. This leads to better performance on the target post-migration. Each individual import job will take longer, since more data is now imported in each batch, but the sum total of all jobs should take the same (or less) time. +- Renamed the `--table-splits` flag to [`--concurrency-per-table`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), which is more descriptive. +- Increased the default value of [`--import-batch-size`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) to `1000`. This leads to better performance on the target post-migration. Each individual import job will take longer, since more data is now imported in each batch, but the sum total of all jobs should take the same (or less) time. ## May 29, 2024 MOLT Fetch/Verify 0.3.0 is [available](#installation). -- Added an [`--import-batch-size`]({% link molt/molt-fetch.md %}#global-flags) flag, which configures the number of files to be imported in each `IMPORT` job. +- Added an [`--import-batch-size`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag, which configures the number of files to be imported in each `IMPORT` job. - In some cases on the previous version, binaries would not work due to how `molt` was being built. Updated the build method to use static linking, which creates binaries that should be more portable. - [`VARBIT`]({% link {{ site.current_cloud_version }}/bit.md %}) <> [`BOOL`]({% link {{ site.current_cloud_version }}/bool.md %}) conversion is now allowed for Fetch and Verify. The bit array is first converted to `UINT64`. A resulting `1` or `0` is converted to `true` or `false` accordingly. If the `UINT64` is another value, an error is emitted. @@ -249,7 +249,7 @@ MOLT Fetch/Verify 0.3.0 is [available](#installation). MOLT Fetch/Verify 0.2.1 is [available](#installation). - MOLT tools now enforce secure connections to databases as a default. The `--allow-tls-mode-disable` flag allows users to override that behavior if secure access is not possible. -- When using MySQL as a source, [`--table-concurrency`]({% link molt/molt-fetch.md %}#global-flags) and [`--export-concurrency`]({% link molt/molt-fetch.md %}#global-flags) are strictly set to `1`. +- When using MySQL as a source, [`--table-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) and [`--export-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) are strictly set to `1`. - Fixed a bug involving history retention for [`DECIMAL`]({% link {{ site.current_cloud_version }}/decimal.md %}) values. ## May 3, 2024 @@ -257,9 +257,9 @@ MOLT Fetch/Verify 0.2.1 is [available](#installation). MOLT Fetch/Verify 0.2.0 is [available](#installation). - Fetch now supports CockroachDB [multi-region tables]({% link {{ site.current_cloud_version }}/multiregion-overview.md %}). -- Fetch now supports continuous replication for PostgreSQL and MySQL source databases via the [`--ongoing-replication`]({% link molt/molt-fetch.md %}#global-flags) flag. When Fetch finishes the initial data load phase, it will start the replicator process as a subprocess, which runs indefinitely until the user ends the process with a `SIGTERM` (`ctrl-c`). -- Replicator flags for ([PostgreSQL](https://github.com/cockroachdb/replicator/wiki/PGLogical#postgresql-logical-replication) and [MySQL](https://github.com/cockroachdb/replicator/wiki/MYLogical#mysqlmariadb-replication)) are now supported, allowing users to further configure the [`--ongoing-replication`]({% link molt/molt-fetch.md %}#global-flags) mode for their use case. -- Added the [`--type-map-file`]({% link molt/molt-fetch.md %}#global-flags) flag, which enables custom type mapping for schema creation. +- Fetch now supports continuous replication for PostgreSQL and MySQL source databases via the [`--ongoing-replication`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag. When Fetch finishes the initial data load phase, it will start the replicator process as a subprocess, which runs indefinitely until the user ends the process with a `SIGTERM` (`ctrl-c`). +- Replicator flags for ([PostgreSQL](https://github.com/cockroachdb/replicator/wiki/PGLogical#postgresql-logical-replication) and [MySQL](https://github.com/cockroachdb/replicator/wiki/MYLogical#mysqlmariadb-replication)) are now supported, allowing users to further configure the [`--ongoing-replication`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) mode for their use case. +- Added the [`--type-map-file`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag, which enables custom type mapping for schema creation. - Fixed a bug where primary key positions could be missed when creating a schema with multiple primary keys. - Added a default mode for MySQL sources that ensures consistency and does not leverage parallelism. New text is displayed that alerts the user and links to documentation in cases where fetching from MySQL might not be consistent. - Logging for continuation tokens is now omitted when data export does not successfully complete. From f698b631e59beb5487712001df98bce04b66675d Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Tue, 23 Dec 2025 12:02:09 -0500 Subject: [PATCH 11/15] merged in recent changes to replicator docs --- src/current/_includes/sidebar-data-v25.4.json | 1 - .../_includes/v23.1/sidebar-data/migrate.json | 71 +++++-- .../_includes/v23.2/sidebar-data/migrate.json | 71 +++++-- .../_includes/v24.1/sidebar-data/migrate.json | 71 +++++-- .../_includes/v24.2/sidebar-data/migrate.json | 71 +++++-- .../_includes/v24.3/sidebar-data/migrate.json | 71 +++++-- .../_includes/v25.1/sidebar-data/migrate.json | 71 +++++-- .../_includes/v25.2/sidebar-data/migrate.json | 73 +++++-- .../_includes/v25.3/sidebar-data/migrate.json | 71 +++++-- .../v25.4/sidebar-data/migrate-new.json | 187 ------------------ .../_includes/v25.4/sidebar-data/migrate.json | 73 +++++-- .../_includes/v26.1/sidebar-data/migrate.json | 71 +++++-- .../molt/migration-considerations-rollback.md | 2 +- 13 files changed, 563 insertions(+), 341 deletions(-) delete mode 100644 src/current/_includes/v25.4/sidebar-data/migrate-new.json diff --git a/src/current/_includes/sidebar-data-v25.4.json b/src/current/_includes/sidebar-data-v25.4.json index 2b7178876fe..ab270e056d9 100644 --- a/src/current/_includes/sidebar-data-v25.4.json +++ b/src/current/_includes/sidebar-data-v25.4.json @@ -11,7 +11,6 @@ {% include_cached v25.4/sidebar-data/feature-overview.json %}, {% include_cached v25.4/sidebar-data/resilience.json %}, {% include_cached v25.4/sidebar-data/connect-to-cockroachdb.json %}, - {% include_cached v25.4/sidebar-data/migrate-new.json %}, {% include_cached v25.4/sidebar-data/migrate.json %}, {% include_cached v25.4/sidebar-data/cloud-deployments.json %}, {% include_cached v25.4/sidebar-data/self-hosted-deployments.json %}, diff --git a/src/current/_includes/v23.1/sidebar-data/migrate.json b/src/current/_includes/v23.1/sidebar-data/migrate.json index 81d046ba2d9..f7aace24f2c 100644 --- a/src/current/_includes/v23.1/sidebar-data/migrate.json +++ b/src/current/_includes/v23.1/sidebar-data/migrate.json @@ -9,36 +9,42 @@ ] }, { - "title": "Migration Strategy", - "urls": [ - "/molt/migration-strategy.html" - ] - }, - { - "title": "Migration Flows", + "title": "Migration Considerations", "items": [ { - "title": "Bulk Load", + "title": "Overview", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-considerations.html" ] }, { - "title": "Load and Replicate Separately", + "title": "Migration Granularity", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-considerations-phases.html" ] }, { - "title": "Resume Replication", + "title": "Continuous Replication", "urls": [ - "/molt/migrate-resume-replication.html" + "/molt/migration-considerations-replication.html" ] }, { - "title": "Failback", + "title": "Data Transformation Strategy", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" ] } ] @@ -89,6 +95,41 @@ } ] }, + { + "title": "Common Migration Approaches", + "items": [ + { + "title": "Classic Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Phased Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Delta Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Streaming Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + }, + { + "title": "Active-Active Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, { "title": "Third-Party Migration Tools", "items": [ diff --git a/src/current/_includes/v23.2/sidebar-data/migrate.json b/src/current/_includes/v23.2/sidebar-data/migrate.json index 81d046ba2d9..f7aace24f2c 100644 --- a/src/current/_includes/v23.2/sidebar-data/migrate.json +++ b/src/current/_includes/v23.2/sidebar-data/migrate.json @@ -9,36 +9,42 @@ ] }, { - "title": "Migration Strategy", - "urls": [ - "/molt/migration-strategy.html" - ] - }, - { - "title": "Migration Flows", + "title": "Migration Considerations", "items": [ { - "title": "Bulk Load", + "title": "Overview", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-considerations.html" ] }, { - "title": "Load and Replicate Separately", + "title": "Migration Granularity", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-considerations-phases.html" ] }, { - "title": "Resume Replication", + "title": "Continuous Replication", "urls": [ - "/molt/migrate-resume-replication.html" + "/molt/migration-considerations-replication.html" ] }, { - "title": "Failback", + "title": "Data Transformation Strategy", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" ] } ] @@ -89,6 +95,41 @@ } ] }, + { + "title": "Common Migration Approaches", + "items": [ + { + "title": "Classic Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Phased Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Delta Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Streaming Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + }, + { + "title": "Active-Active Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, { "title": "Third-Party Migration Tools", "items": [ diff --git a/src/current/_includes/v24.1/sidebar-data/migrate.json b/src/current/_includes/v24.1/sidebar-data/migrate.json index 81d046ba2d9..f7aace24f2c 100644 --- a/src/current/_includes/v24.1/sidebar-data/migrate.json +++ b/src/current/_includes/v24.1/sidebar-data/migrate.json @@ -9,36 +9,42 @@ ] }, { - "title": "Migration Strategy", - "urls": [ - "/molt/migration-strategy.html" - ] - }, - { - "title": "Migration Flows", + "title": "Migration Considerations", "items": [ { - "title": "Bulk Load", + "title": "Overview", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-considerations.html" ] }, { - "title": "Load and Replicate Separately", + "title": "Migration Granularity", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-considerations-phases.html" ] }, { - "title": "Resume Replication", + "title": "Continuous Replication", "urls": [ - "/molt/migrate-resume-replication.html" + "/molt/migration-considerations-replication.html" ] }, { - "title": "Failback", + "title": "Data Transformation Strategy", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" ] } ] @@ -89,6 +95,41 @@ } ] }, + { + "title": "Common Migration Approaches", + "items": [ + { + "title": "Classic Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Phased Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Delta Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Streaming Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + }, + { + "title": "Active-Active Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, { "title": "Third-Party Migration Tools", "items": [ diff --git a/src/current/_includes/v24.2/sidebar-data/migrate.json b/src/current/_includes/v24.2/sidebar-data/migrate.json index 81d046ba2d9..f7aace24f2c 100644 --- a/src/current/_includes/v24.2/sidebar-data/migrate.json +++ b/src/current/_includes/v24.2/sidebar-data/migrate.json @@ -9,36 +9,42 @@ ] }, { - "title": "Migration Strategy", - "urls": [ - "/molt/migration-strategy.html" - ] - }, - { - "title": "Migration Flows", + "title": "Migration Considerations", "items": [ { - "title": "Bulk Load", + "title": "Overview", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-considerations.html" ] }, { - "title": "Load and Replicate Separately", + "title": "Migration Granularity", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-considerations-phases.html" ] }, { - "title": "Resume Replication", + "title": "Continuous Replication", "urls": [ - "/molt/migrate-resume-replication.html" + "/molt/migration-considerations-replication.html" ] }, { - "title": "Failback", + "title": "Data Transformation Strategy", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" ] } ] @@ -89,6 +95,41 @@ } ] }, + { + "title": "Common Migration Approaches", + "items": [ + { + "title": "Classic Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Phased Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Delta Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Streaming Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + }, + { + "title": "Active-Active Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, { "title": "Third-Party Migration Tools", "items": [ diff --git a/src/current/_includes/v24.3/sidebar-data/migrate.json b/src/current/_includes/v24.3/sidebar-data/migrate.json index 81d046ba2d9..f7aace24f2c 100644 --- a/src/current/_includes/v24.3/sidebar-data/migrate.json +++ b/src/current/_includes/v24.3/sidebar-data/migrate.json @@ -9,36 +9,42 @@ ] }, { - "title": "Migration Strategy", - "urls": [ - "/molt/migration-strategy.html" - ] - }, - { - "title": "Migration Flows", + "title": "Migration Considerations", "items": [ { - "title": "Bulk Load", + "title": "Overview", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-considerations.html" ] }, { - "title": "Load and Replicate Separately", + "title": "Migration Granularity", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-considerations-phases.html" ] }, { - "title": "Resume Replication", + "title": "Continuous Replication", "urls": [ - "/molt/migrate-resume-replication.html" + "/molt/migration-considerations-replication.html" ] }, { - "title": "Failback", + "title": "Data Transformation Strategy", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" ] } ] @@ -89,6 +95,41 @@ } ] }, + { + "title": "Common Migration Approaches", + "items": [ + { + "title": "Classic Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Phased Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Delta Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Streaming Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + }, + { + "title": "Active-Active Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, { "title": "Third-Party Migration Tools", "items": [ diff --git a/src/current/_includes/v25.1/sidebar-data/migrate.json b/src/current/_includes/v25.1/sidebar-data/migrate.json index e6ba00a899c..f7aace24f2c 100644 --- a/src/current/_includes/v25.1/sidebar-data/migrate.json +++ b/src/current/_includes/v25.1/sidebar-data/migrate.json @@ -9,36 +9,42 @@ ] }, { - "title": "Migration Strategy", - "urls": [ - "/molt/migration-strategy.html" - ] - }, - { - "title": "Migration Flows", + "title": "Migration Considerations", "items": [ { - "title": "Bulk Load", + "title": "Overview", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-considerations.html" ] }, { - "title": "Load and Replicate", + "title": "Migration Granularity", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-considerations-phases.html" ] }, { - "title": "Resume Replication", + "title": "Continuous Replication", "urls": [ - "/molt/migrate-resume-replication.html" + "/molt/migration-considerations-replication.html" ] }, { - "title": "Failback", + "title": "Data Transformation Strategy", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" ] } ] @@ -89,6 +95,41 @@ } ] }, + { + "title": "Common Migration Approaches", + "items": [ + { + "title": "Classic Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Phased Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Delta Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Streaming Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + }, + { + "title": "Active-Active Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, { "title": "Third-Party Migration Tools", "items": [ diff --git a/src/current/_includes/v25.2/sidebar-data/migrate.json b/src/current/_includes/v25.2/sidebar-data/migrate.json index 7693e764268..f7aace24f2c 100644 --- a/src/current/_includes/v25.2/sidebar-data/migrate.json +++ b/src/current/_includes/v25.2/sidebar-data/migrate.json @@ -9,36 +9,42 @@ ] }, { - "title": "Migration Strategy", - "urls": [ - "/molt/migration-strategy.html" - ] - }, - { - "title": "Migration Flows", + "title": "Migration Considerations", "items": [ { - "title": "Bulk Load", + "title": "Overview", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-considerations.html" ] }, { - "title": "Load and Replicate", + "title": "Migration Granularity", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-considerations-phases.html" ] }, { - "title": "Resume Replication", + "title": "Continuous Replication", "urls": [ - "/molt/migrate-resume-replication.html" + "/molt/migration-considerations-replication.html" ] }, { - "title": "Failback", + "title": "Data Transformation Strategy", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" ] } ] @@ -89,6 +95,41 @@ } ] }, + { + "title": "Common Migration Approaches", + "items": [ + { + "title": "Classic Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Phased Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Delta Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Streaming Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + }, + { + "title": "Active-Active Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, { "title": "Third-Party Migration Tools", "items": [ @@ -172,4 +213,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/src/current/_includes/v25.3/sidebar-data/migrate.json b/src/current/_includes/v25.3/sidebar-data/migrate.json index e6ba00a899c..f7aace24f2c 100644 --- a/src/current/_includes/v25.3/sidebar-data/migrate.json +++ b/src/current/_includes/v25.3/sidebar-data/migrate.json @@ -9,36 +9,42 @@ ] }, { - "title": "Migration Strategy", - "urls": [ - "/molt/migration-strategy.html" - ] - }, - { - "title": "Migration Flows", + "title": "Migration Considerations", "items": [ { - "title": "Bulk Load", + "title": "Overview", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-considerations.html" ] }, { - "title": "Load and Replicate", + "title": "Migration Granularity", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-considerations-phases.html" ] }, { - "title": "Resume Replication", + "title": "Continuous Replication", "urls": [ - "/molt/migrate-resume-replication.html" + "/molt/migration-considerations-replication.html" ] }, { - "title": "Failback", + "title": "Data Transformation Strategy", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" ] } ] @@ -89,6 +95,41 @@ } ] }, + { + "title": "Common Migration Approaches", + "items": [ + { + "title": "Classic Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Phased Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Delta Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Streaming Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + }, + { + "title": "Active-Active Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, { "title": "Third-Party Migration Tools", "items": [ diff --git a/src/current/_includes/v25.4/sidebar-data/migrate-new.json b/src/current/_includes/v25.4/sidebar-data/migrate-new.json deleted file mode 100644 index a3149d53066..00000000000 --- a/src/current/_includes/v25.4/sidebar-data/migrate-new.json +++ /dev/null @@ -1,187 +0,0 @@ -{ - "title": "Migrate NEW", - "is_top_level": true, - "items": [ - { - "title": "Overview", - "urls": [ - "/molt/migration-overview.html" - ] - }, - { - "title": "Migration Considerations", - "items": [ - { - "title": "Overview", - "urls": [ - "/molt/migration-considerations.html" - ] - }, - { - "title": "Migration Granularity", - "urls": [ - "/molt/migration-considerations-phases.html" - ] - }, - { - "title": "Continuous Replication", - "urls": [ - "/molt/migration-considerations-replication.html" - ] - }, - { - "title": "Data Transformation Strategy", - "urls": [ - "/molt/migration-considerations-transformation.html" - ] - }, - { - "title": "Validation Strategy", - "urls": [ - "/molt/migration-considerations-validation.html" - ] - }, - { - "title": "Rollback Plan", - "urls": [ - "/molt/migration-considerations-rollback.html" - ] - } - ] - }, - { - "title": "MOLT Tools", - "items": [ - { - "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" - ] - }, - { - "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" - ] - }, - { - "title": "Replicator", - "urls": [ - "/molt/molt-replicator.html" - ] - }, - { - "title": "Verify", - "urls": [ - "/molt/molt-verify.html" - ] - } - ] - }, - { - "title": "Migration Walkthroughs", - "items": [ - { - "title": "Migration with Downtime", - "urls": [ - "/molt/migrate-bulk-load.html" - ] - }, - { - "title": "Near-zero Downtime Migration", - "urls": [ - "/molt/migrate-load-replicate.html" - ] - }, - { - "title": "Near-zero Downtime Migration with Failback", - "urls": [ - "/molt/migrate-failback.html" - ] - } - ] - }, - { - "title": "Third-Party Migration Tools", - "items": [ - { - "title": "AWS DMS", - "urls": [ - "/${VERSION}/aws-dms.html" - ] - }, - { - "title": "Qlik Replicate", - "urls": [ - "/${VERSION}/qlik.html" - ] - }, - { - "title": "Striim", - "urls": [ - "/${VERSION}/striim.html" - ] - }, - { - "title": "Oracle GoldenGate", - "urls": [ - "/${VERSION}/goldengate.html" - ] - }, - { - "title": "Debezium", - "urls": [ - "/${VERSION}/debezium.html" - ] - } - ] - }, - { - "title": "Migrate Data Types", - "items": [ - { - "title": "Migrate from CSV", - "urls": [ - "/${VERSION}/migrate-from-csv.html" - ] - }, - { - "title": "Migrate from Avro", - "urls": [ - "/${VERSION}/migrate-from-avro.html" - ] - }, - { - "title": "Migrate from Shapefiles", - "urls": [ - "/${VERSION}/migrate-from-shapefiles.html" - ] - }, - { - "title": "Migrate from OpenStreetMap", - "urls": [ - "/${VERSION}/migrate-from-openstreetmap.html" - ] - }, - { - "title": "Migrate from GeoJSON", - "urls": [ - "/${VERSION}/migrate-from-geojson.html" - ] - }, - { - "title": "Migrate from GeoPackage", - "urls": [ - "/${VERSION}/migrate-from-geopackage.html" - ] - }, - { - "title": "Import Performance Best Practices", - "urls": [ - "/${VERSION}/import-performance-best-practices.html" - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/src/current/_includes/v25.4/sidebar-data/migrate.json b/src/current/_includes/v25.4/sidebar-data/migrate.json index 4823bb0df99..f7aace24f2c 100644 --- a/src/current/_includes/v25.4/sidebar-data/migrate.json +++ b/src/current/_includes/v25.4/sidebar-data/migrate.json @@ -1,5 +1,5 @@ { - "title": "Migrate OLD", + "title": "Migrate", "is_top_level": true, "items": [ { @@ -9,36 +9,42 @@ ] }, { - "title": "Migration Strategy", - "urls": [ - "/molt/migration-strategy.html" - ] - }, - { - "title": "Migration Flows", + "title": "Migration Considerations", "items": [ { - "title": "Bulk Load", + "title": "Overview", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-considerations.html" ] }, { - "title": "Load and Replicate", + "title": "Migration Granularity", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-considerations-phases.html" ] }, { - "title": "Resume Replication", + "title": "Continuous Replication", "urls": [ - "/molt/migrate-resume-replication.html" + "/molt/migration-considerations-replication.html" ] }, { - "title": "Failback", + "title": "Data Transformation Strategy", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" ] } ] @@ -89,6 +95,41 @@ } ] }, + { + "title": "Common Migration Approaches", + "items": [ + { + "title": "Classic Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Phased Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Delta Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Streaming Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + }, + { + "title": "Active-Active Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, { "title": "Third-Party Migration Tools", "items": [ diff --git a/src/current/_includes/v26.1/sidebar-data/migrate.json b/src/current/_includes/v26.1/sidebar-data/migrate.json index e6ba00a899c..f7aace24f2c 100644 --- a/src/current/_includes/v26.1/sidebar-data/migrate.json +++ b/src/current/_includes/v26.1/sidebar-data/migrate.json @@ -9,36 +9,42 @@ ] }, { - "title": "Migration Strategy", - "urls": [ - "/molt/migration-strategy.html" - ] - }, - { - "title": "Migration Flows", + "title": "Migration Considerations", "items": [ { - "title": "Bulk Load", + "title": "Overview", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-considerations.html" ] }, { - "title": "Load and Replicate", + "title": "Migration Granularity", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-considerations-phases.html" ] }, { - "title": "Resume Replication", + "title": "Continuous Replication", "urls": [ - "/molt/migrate-resume-replication.html" + "/molt/migration-considerations-replication.html" ] }, { - "title": "Failback", + "title": "Data Transformation Strategy", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-considerations-transformation.html" + ] + }, + { + "title": "Validation Strategy", + "urls": [ + "/molt/migration-considerations-validation.html" + ] + }, + { + "title": "Rollback Plan", + "urls": [ + "/molt/migration-considerations-rollback.html" ] } ] @@ -89,6 +95,41 @@ } ] }, + { + "title": "Common Migration Approaches", + "items": [ + { + "title": "Classic Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Phased Bulk Load", + "urls": [ + "/molt/migrate-bulk-load.html" + ] + }, + { + "title": "Delta Migration", + "urls": [ + "/molt/migrate-load-replicate.html" + ] + }, + { + "title": "Streaming Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + }, + { + "title": "Active-Active Migration", + "urls": [ + "/molt/migrate-failback.html" + ] + } + ] + }, { "title": "Third-Party Migration Tools", "items": [ diff --git a/src/current/molt/migration-considerations-rollback.md b/src/current/molt/migration-considerations-rollback.md index 5db81cf11c0..1d45846e8e7 100644 --- a/src/current/molt/migration-considerations-rollback.md +++ b/src/current/molt/migration-considerations-rollback.md @@ -77,7 +77,7 @@ Ensure your source database supports the change data capture requirements for th [MOLT Replicator]({% link molt/molt-replicator.md %}) uses change data to stream changes from one database to another. It's used for both [forward replication]({% link molt/migration-considerations-replication.md %}) and [failback replication](#failback-replication). -To use MOLT Replicator in failback mode, run the [`replicator start`]({% link molt/molt-replicator.md %}#commands) command with its various [flags]({% link molt/molt-replicator.md %}#start-failback-flags). +To use MOLT Replicator in failback mode, run the [`replicator start`]({% link molt/molt-replicator.md %}#commands) command with its various [flags]({% link molt/replicator-flags.md %}). When enabling failback replication, the original source database becomes the replication target, and the original target CockroachDB cluster becomes the replication source. Use the `--sourceConn` flag to indicate the CockroachDB cluster, and use the `--targetConn` flag to indicate the PostgreSQL, MySQL, or Oracle database from which data is being migrated. From 122a74d9d461f7bd8fc610ae959ce4879c5a9442 Mon Sep 17 00:00:00 2001 From: bsanchez-the-roach Date: Tue, 23 Dec 2025 12:51:50 -0500 Subject: [PATCH 12/15] Update pr-reviews.yml to allow deployment of draft --- .github/workflows/pr-reviews.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/pr-reviews.yml b/.github/workflows/pr-reviews.yml index 1736a86a063..0f8e19a7a77 100644 --- a/.github/workflows/pr-reviews.yml +++ b/.github/workflows/pr-reviews.yml @@ -10,7 +10,6 @@ on: jobs: pr-review: - if: github.event.pull_request.draft == false runs-on: ubuntu-latest steps: - name: Checkout From b05a46a908d8ae8946c6ae6eb52655e092190389 Mon Sep 17 00:00:00 2001 From: bsanchez-the-roach Date: Tue, 23 Dec 2025 12:55:33 -0500 Subject: [PATCH 13/15] Update pr-reviews.yml, returning to previous --- .github/workflows/pr-reviews.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-reviews.yml b/.github/workflows/pr-reviews.yml index 0f8e19a7a77..1736a86a063 100644 --- a/.github/workflows/pr-reviews.yml +++ b/.github/workflows/pr-reviews.yml @@ -10,6 +10,7 @@ on: jobs: pr-review: + if: github.event.pull_request.draft == false runs-on: ubuntu-latest steps: - name: Checkout From 97dd7351d6783fcb3f1fc8aec344a71b6e77af3a Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Tue, 23 Dec 2025 16:31:51 -0500 Subject: [PATCH 14/15] separated Replicator to match Fetch, fixed links --- src/current/_includes/molt/molt-setup.md | 2 +- .../_includes/v23.1/sidebar-data/migrate.json | 18 + .../_includes/v23.2/sidebar-data/migrate.json | 18 + .../_includes/v24.1/sidebar-data/migrate.json | 18 + .../_includes/v24.2/sidebar-data/migrate.json | 18 + .../_includes/v24.3/sidebar-data/migrate.json | 18 + .../_includes/v25.1/sidebar-data/migrate.json | 18 + .../_includes/v25.2/sidebar-data/migrate.json | 18 + .../_includes/v25.3/sidebar-data/migrate.json | 18 + .../_includes/v25.4/sidebar-data/migrate.json | 18 + .../_includes/v26.1/sidebar-data/migrate.json | 36 +- .../molt/migration-approach-active-active.md | 8 + .../migration-approach-classic-bulk-load.md | 8 + src/current/molt/migration-approach-delta.md | 8 + .../migration-approach-phased-bulk-load.md | 8 + .../molt/migration-approach-streaming.md | 8 + .../molt/migration-considerations-phases.md | 2 +- .../migration-considerations-replication.md | 2 +- .../molt/migration-considerations-rollback.md | 2 +- src/current/molt/migration-overview.md | 2 +- src/current/molt/molt-fetch.md | 25 +- .../molt/molt-replicator-best-practices.md | 147 +++++++ .../molt/molt-replicator-installation.md | 55 +++ .../molt/molt-replicator-troubleshooting.md | 23 ++ src/current/molt/molt-replicator.md | 369 ++++-------------- src/current/molt/replicator-flags.md | 21 +- src/current/releases/molt.md | 6 +- 27 files changed, 581 insertions(+), 313 deletions(-) create mode 100644 src/current/molt/migration-approach-active-active.md create mode 100644 src/current/molt/migration-approach-classic-bulk-load.md create mode 100644 src/current/molt/migration-approach-delta.md create mode 100644 src/current/molt/migration-approach-phased-bulk-load.md create mode 100644 src/current/molt/migration-approach-streaming.md create mode 100644 src/current/molt/molt-replicator-best-practices.md create mode 100644 src/current/molt/molt-replicator-installation.md create mode 100644 src/current/molt/molt-replicator-troubleshooting.md diff --git a/src/current/_includes/molt/molt-setup.md b/src/current/_includes/molt/molt-setup.md index 4dcb975227d..2ed05806113 100644 --- a/src/current/_includes/molt/molt-setup.md +++ b/src/current/_includes/molt/molt-setup.md @@ -9,7 +9,7 @@ - Create a CockroachDB [{{ site.data.products.cloud }}]({% link cockroachcloud/create-your-cluster.md %}) or [{{ site.data.products.core }}]({% link {{ site.current_cloud_version }}/install-cockroachdb-mac.md %}) cluster. - Install the [MOLT (Migrate Off Legacy Technology)]({% link releases/molt.md %}#installation) tools. -- Review the [Fetch]({% link molt/molt-fetch-best-practices.md %}) and {% if page.name != "migrate-bulk-load.md" %}[Replicator]({% link molt/molt-replicator.md %}#best-practices){% endif %} best practices. +- Review the [Fetch]({% link molt/molt-fetch-best-practices.md %}) and {% if page.name != "migrate-bulk-load.md" %}[Replicator]({% link molt/molt-replicator-best-practices.md %}){% endif %} best practices. - Review [Migration Strategy]({% link molt/migration-strategy.md %}).
diff --git a/src/current/_includes/v23.1/sidebar-data/migrate.json b/src/current/_includes/v23.1/sidebar-data/migrate.json index f7aace24f2c..d517d0c271a 100644 --- a/src/current/_includes/v23.1/sidebar-data/migrate.json +++ b/src/current/_includes/v23.1/sidebar-data/migrate.json @@ -73,6 +73,12 @@ "/molt/molt-replicator.html" ] }, + { + "title": "Installation", + "urls": [ + "/molt/molt-replicator-installation.html" + ] + }, { "title": "Flags", "urls": [ @@ -84,6 +90,18 @@ "urls": [ "/molt/replicator-metrics.html" ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-replicator-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-replicator-troubleshooting.html" + ] } ] }, diff --git a/src/current/_includes/v23.2/sidebar-data/migrate.json b/src/current/_includes/v23.2/sidebar-data/migrate.json index f7aace24f2c..d517d0c271a 100644 --- a/src/current/_includes/v23.2/sidebar-data/migrate.json +++ b/src/current/_includes/v23.2/sidebar-data/migrate.json @@ -73,6 +73,12 @@ "/molt/molt-replicator.html" ] }, + { + "title": "Installation", + "urls": [ + "/molt/molt-replicator-installation.html" + ] + }, { "title": "Flags", "urls": [ @@ -84,6 +90,18 @@ "urls": [ "/molt/replicator-metrics.html" ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-replicator-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-replicator-troubleshooting.html" + ] } ] }, diff --git a/src/current/_includes/v24.1/sidebar-data/migrate.json b/src/current/_includes/v24.1/sidebar-data/migrate.json index f7aace24f2c..d517d0c271a 100644 --- a/src/current/_includes/v24.1/sidebar-data/migrate.json +++ b/src/current/_includes/v24.1/sidebar-data/migrate.json @@ -73,6 +73,12 @@ "/molt/molt-replicator.html" ] }, + { + "title": "Installation", + "urls": [ + "/molt/molt-replicator-installation.html" + ] + }, { "title": "Flags", "urls": [ @@ -84,6 +90,18 @@ "urls": [ "/molt/replicator-metrics.html" ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-replicator-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-replicator-troubleshooting.html" + ] } ] }, diff --git a/src/current/_includes/v24.2/sidebar-data/migrate.json b/src/current/_includes/v24.2/sidebar-data/migrate.json index f7aace24f2c..d517d0c271a 100644 --- a/src/current/_includes/v24.2/sidebar-data/migrate.json +++ b/src/current/_includes/v24.2/sidebar-data/migrate.json @@ -73,6 +73,12 @@ "/molt/molt-replicator.html" ] }, + { + "title": "Installation", + "urls": [ + "/molt/molt-replicator-installation.html" + ] + }, { "title": "Flags", "urls": [ @@ -84,6 +90,18 @@ "urls": [ "/molt/replicator-metrics.html" ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-replicator-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-replicator-troubleshooting.html" + ] } ] }, diff --git a/src/current/_includes/v24.3/sidebar-data/migrate.json b/src/current/_includes/v24.3/sidebar-data/migrate.json index f7aace24f2c..d517d0c271a 100644 --- a/src/current/_includes/v24.3/sidebar-data/migrate.json +++ b/src/current/_includes/v24.3/sidebar-data/migrate.json @@ -73,6 +73,12 @@ "/molt/molt-replicator.html" ] }, + { + "title": "Installation", + "urls": [ + "/molt/molt-replicator-installation.html" + ] + }, { "title": "Flags", "urls": [ @@ -84,6 +90,18 @@ "urls": [ "/molt/replicator-metrics.html" ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-replicator-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-replicator-troubleshooting.html" + ] } ] }, diff --git a/src/current/_includes/v25.1/sidebar-data/migrate.json b/src/current/_includes/v25.1/sidebar-data/migrate.json index f7aace24f2c..d517d0c271a 100644 --- a/src/current/_includes/v25.1/sidebar-data/migrate.json +++ b/src/current/_includes/v25.1/sidebar-data/migrate.json @@ -73,6 +73,12 @@ "/molt/molt-replicator.html" ] }, + { + "title": "Installation", + "urls": [ + "/molt/molt-replicator-installation.html" + ] + }, { "title": "Flags", "urls": [ @@ -84,6 +90,18 @@ "urls": [ "/molt/replicator-metrics.html" ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-replicator-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-replicator-troubleshooting.html" + ] } ] }, diff --git a/src/current/_includes/v25.2/sidebar-data/migrate.json b/src/current/_includes/v25.2/sidebar-data/migrate.json index f7aace24f2c..d517d0c271a 100644 --- a/src/current/_includes/v25.2/sidebar-data/migrate.json +++ b/src/current/_includes/v25.2/sidebar-data/migrate.json @@ -73,6 +73,12 @@ "/molt/molt-replicator.html" ] }, + { + "title": "Installation", + "urls": [ + "/molt/molt-replicator-installation.html" + ] + }, { "title": "Flags", "urls": [ @@ -84,6 +90,18 @@ "urls": [ "/molt/replicator-metrics.html" ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-replicator-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-replicator-troubleshooting.html" + ] } ] }, diff --git a/src/current/_includes/v25.3/sidebar-data/migrate.json b/src/current/_includes/v25.3/sidebar-data/migrate.json index f7aace24f2c..d517d0c271a 100644 --- a/src/current/_includes/v25.3/sidebar-data/migrate.json +++ b/src/current/_includes/v25.3/sidebar-data/migrate.json @@ -73,6 +73,12 @@ "/molt/molt-replicator.html" ] }, + { + "title": "Installation", + "urls": [ + "/molt/molt-replicator-installation.html" + ] + }, { "title": "Flags", "urls": [ @@ -84,6 +90,18 @@ "urls": [ "/molt/replicator-metrics.html" ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-replicator-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-replicator-troubleshooting.html" + ] } ] }, diff --git a/src/current/_includes/v25.4/sidebar-data/migrate.json b/src/current/_includes/v25.4/sidebar-data/migrate.json index f7aace24f2c..d517d0c271a 100644 --- a/src/current/_includes/v25.4/sidebar-data/migrate.json +++ b/src/current/_includes/v25.4/sidebar-data/migrate.json @@ -73,6 +73,12 @@ "/molt/molt-replicator.html" ] }, + { + "title": "Installation", + "urls": [ + "/molt/molt-replicator-installation.html" + ] + }, { "title": "Flags", "urls": [ @@ -84,6 +90,18 @@ "urls": [ "/molt/replicator-metrics.html" ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-replicator-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-replicator-troubleshooting.html" + ] } ] }, diff --git a/src/current/_includes/v26.1/sidebar-data/migrate.json b/src/current/_includes/v26.1/sidebar-data/migrate.json index 4bbcd7510f1..571582248ad 100644 --- a/src/current/_includes/v26.1/sidebar-data/migrate.json +++ b/src/current/_includes/v26.1/sidebar-data/migrate.json @@ -62,7 +62,7 @@ "title": "Fetch", "items": [ { - "title": "Overview", + "title": "Oveview", "urls": [ "/molt/molt-fetch.html" ] @@ -109,7 +109,13 @@ ] }, { - "title": "Flags", + "title": "Installation", + "urls": [ + "/molt/molt-replicator-installation.html" + ] + }, + { + "title": "Commands and Flags", "urls": [ "/molt/replicator-flags.html" ] @@ -119,6 +125,18 @@ "urls": [ "/molt/replicator-metrics.html" ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-replicator-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-replicator-troubleshooting.html" + ] } ] }, @@ -134,33 +152,33 @@ "title": "Common Migration Approaches", "items": [ { - "title": "Classic Bulk Load", + "title": "Classic Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-classic-bulk-load.html" ] }, { - "title": "Phased Bulk Load", + "title": "Phased Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-phased-bulk-load.html" ] }, { "title": "Delta Migration", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-approach-delta.html" ] }, { "title": "Streaming Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-streaming.html" ] }, { "title": "Active-Active Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-active-active.html" ] } ] diff --git a/src/current/molt/migration-approach-active-active.md b/src/current/molt/migration-approach-active-active.md new file mode 100644 index 00000000000..a63fd861a87 --- /dev/null +++ b/src/current/molt/migration-approach-active-active.md @@ -0,0 +1,8 @@ +--- +title: Active-Active Migration +summary: Learn what a Active-Active Migration is, how it relates to the migration considerations, and how to perform it using MOLT tools. +toc: true +docs_area: migrate +--- + +TBD \ No newline at end of file diff --git a/src/current/molt/migration-approach-classic-bulk-load.md b/src/current/molt/migration-approach-classic-bulk-load.md new file mode 100644 index 00000000000..f899e46a2ed --- /dev/null +++ b/src/current/molt/migration-approach-classic-bulk-load.md @@ -0,0 +1,8 @@ +--- +title: Classic Bulk Load Migration +summary: Learn what a Classic Bulk Load Migration is, how it relates to the migration considerations, and how to perform it using MOLT tools. +toc: true +docs_area: migrate +--- + +TBD \ No newline at end of file diff --git a/src/current/molt/migration-approach-delta.md b/src/current/molt/migration-approach-delta.md new file mode 100644 index 00000000000..227e1ee0cc2 --- /dev/null +++ b/src/current/molt/migration-approach-delta.md @@ -0,0 +1,8 @@ +--- +title: Delta Migration +summary: Learn what a Delta Migration is, how it relates to the migration considerations, and how to perform it using MOLT tools. +toc: true +docs_area: migrate +--- + +TBD \ No newline at end of file diff --git a/src/current/molt/migration-approach-phased-bulk-load.md b/src/current/molt/migration-approach-phased-bulk-load.md new file mode 100644 index 00000000000..3c2da438afd --- /dev/null +++ b/src/current/molt/migration-approach-phased-bulk-load.md @@ -0,0 +1,8 @@ +--- +title: Phased Bulk Load Migration +summary: Learn what a Phased Bulk Load Migration is, how it relates to the migration considerations, and how to perform it using MOLT tools. +toc: true +docs_area: migrate +--- + +TBD \ No newline at end of file diff --git a/src/current/molt/migration-approach-streaming.md b/src/current/molt/migration-approach-streaming.md new file mode 100644 index 00000000000..829d7b0fd15 --- /dev/null +++ b/src/current/molt/migration-approach-streaming.md @@ -0,0 +1,8 @@ +--- +title: Streaming Migration +summary: Learn what a Streaming Migration is, how it relates to the migration considerations, and how to perform it using MOLT tools. +toc: true +docs_area: migrate +--- + +TBD \ No newline at end of file diff --git a/src/current/molt/migration-considerations-phases.md b/src/current/molt/migration-considerations-phases.md index 35d451dc0fd..b525b9b80c8 100644 --- a/src/current/molt/migration-considerations-phases.md +++ b/src/current/molt/migration-considerations-phases.md @@ -77,7 +77,7 @@ By default, [MOLT Fetch]({% link molt/molt-fetch.md %}) moves all data from the Similarly, you can use [MOLT Verify]({% link molt/molt-verify.md %})'s `--schema-filter` and `--table-filter` flags to run validation checks on subsets of the data in your source and target databases. In a phased migration, you will likely want to verify data at the end of each migration phase, rather than at the end of the entire migration. -[MOLT Replicator]({% link molt/molt-replicator.md %}) replicates full tables by default. If you choose to combine phased migration with [continuous replication]({% link molt/migration-considerations-replication.md %}), you will either need to select phases that include whole tables, or else use [userscripts]({% link molt/molt-replicator.md %}#flags) to select rows to replicate. +[MOLT Replicator]({% link molt/molt-replicator.md %}) replicates full tables by default. If you choose to combine phased migration with [continuous replication]({% link molt/migration-considerations-replication.md %}), you will either need to select phases that include whole tables, or else use [userscripts]({% link molt/replicator-flags.md %}#userscript) to select rows to replicate. ## Example sequences diff --git a/src/current/molt/migration-considerations-replication.md b/src/current/molt/migration-considerations-replication.md index e9cd08d9cb2..b62e25edfe3 100644 --- a/src/current/molt/migration-considerations-replication.md +++ b/src/current/molt/migration-considerations-replication.md @@ -88,7 +88,7 @@ When you run MOLT Fetch without `--ignore-replication-check`, it emits a checkpo MOLT Fetch supports both `IMPORT INTO` (default, for highest throughput with offline tables) and `COPY FROM` (for online tables) loading methods. Because a hybrid approach will likely aim to have less downtime, you may need to use `COPY FROM` if your tables remain online. In this case, use the `--use-copy` flag. Learn more about Fetch's [data load modes]({% link molt/molt-fetch.md %}#data-load-mode). -MOLT Replicator replicates full tables by default. If you choose to combine continuous replication with a [phased migration]({% link molt/migration-considerations-phases.md %}), you will either need to select phases that include whole tables, or else use [userscripts]({% link molt/molt-replicator.md %}#flags) to select rows to replicate. +MOLT Replicator replicates full tables by default. If you choose to combine continuous replication with a [phased migration]({% link molt/migration-considerations-phases.md %}), you will either need to select phases that include whole tables, or else use [userscripts]({% link molt/replicator-flags.md %}#userscript) to select rows to replicate. MOLT Replicator can be stopped after cutover, or it can remain online to continue streaming changes indefinitely. diff --git a/src/current/molt/migration-considerations-rollback.md b/src/current/molt/migration-considerations-rollback.md index 1d45846e8e7..97379f0a521 100644 --- a/src/current/molt/migration-considerations-rollback.md +++ b/src/current/molt/migration-considerations-rollback.md @@ -77,7 +77,7 @@ Ensure your source database supports the change data capture requirements for th [MOLT Replicator]({% link molt/molt-replicator.md %}) uses change data to stream changes from one database to another. It's used for both [forward replication]({% link molt/migration-considerations-replication.md %}) and [failback replication](#failback-replication). -To use MOLT Replicator in failback mode, run the [`replicator start`]({% link molt/molt-replicator.md %}#commands) command with its various [flags]({% link molt/replicator-flags.md %}). +To use MOLT Replicator in failback mode, run the [`replicator start`]({% link molt/replicator-flags.md %}#commands) command with its various [flags]({% link molt/replicator-flags.md %}). When enabling failback replication, the original source database becomes the replication target, and the original target CockroachDB cluster becomes the replication source. Use the `--sourceConn` flag to indicate the CockroachDB cluster, and use the `--targetConn` flag to indicate the PostgreSQL, MySQL, or Oracle database from which data is being migrated. diff --git a/src/current/molt/migration-overview.md b/src/current/molt/migration-overview.md index 2a552e9eadf..043a21ac524 100644 --- a/src/current/molt/migration-overview.md +++ b/src/current/molt/migration-overview.md @@ -113,7 +113,7 @@ The [MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}) - Continuous replication from source databases to CockroachDB. - [Multiple consistency modes]({% link molt/molt-replicator.md %}#consistency-modes) for balancing throughput and transactional guarantees. - Failback replication from CockroachDB back to source databases. -- [Performance tuning]({% link molt/molt-replicator.md %}#optimize-performance) for high-throughput workloads. +- [Performance tuning]({% link molt/molt-replicator-best-practices.md %}#optimize-performance) for high-throughput workloads. ### Verify diff --git a/src/current/molt/molt-fetch.md b/src/current/molt/molt-fetch.md index 4d7025306f3..138d8c4b8f6 100644 --- a/src/current/molt/molt-fetch.md +++ b/src/current/molt/molt-fetch.md @@ -772,18 +772,18 @@ Use the `cdc_cursor` value as the checkpoint for MySQL or Oracle replication wit You can also use the `cdc_cursor` value with an external change data capture (CDC) tool to continuously replicate subsequent changes from the source database to CockroachDB. -## Common workflows +## Common uses ### Bulk data load +When migrating data to CockroachDB in a bulk load (without utilizing [continuous replication]({% link molt/migration-considerations-replication.md %}) to minimize system downtime), run the `molt fetch` command with the required flags, as shown below: +
-To perform a bulk data load migration from your source database to CockroachDB, run the `molt fetch` command with the required flags. - Specify the source and target database connections. For connection string formats, refer to [Source and target databases](#source-and-target-databases).
@@ -884,9 +884,16 @@ molt fetch \ --ignore-replication-check ~~~ -For detailed steps, refer to [Bulk load migration]({% link molt/migrate-bulk-load.md %}). +For detailed walkthroughs of migrations that use `molt fetch` in this way, refer to the [Classic Bulk Load]({% link molt/migrate-bulk-load.md %}) and [Phased Bulk Load]({% link molt/migrate-bulk-load.md %}) migration approaches. + +For detailed walkthroughs of migrations that use `molt fetch` in this way, refer to these common migration approaches: + +- [Classic Bulk Load Migration]({% link molt/migration-approach-classic-bulk-load.md %}) +- [Phased Bulk Load Migration]({% link molt/migration-approach-phased-bulk-load.md %}) -### Load before replication +### Initial bulk load (before replication) + +In a migration that utilizes [continuous replication]({% link molt/migration-considerations-replication.md %}), perform an initial data load before [setting up ongoing replication with MOLT Replicator]({% link molt/molt-replicator.md %}#forward-replication-after-initial-load). Run the `molt fetch` command without `--ignore-replication-check`, as shown below:
@@ -894,8 +901,6 @@ For detailed steps, refer to [Bulk load migration]({% link molt/migrate-bulk-loa
-To perform an initial data load before setting up ongoing replication with [MOLT Replicator]({% link molt/molt-replicator.md %}), run the `molt fetch` command without `--ignore-replication-check`. This captures replication checkpoints during the data load. - The workflow is the same as [Bulk data load](#bulk-data-load), except: - Exclude `--ignore-replication-check`. MOLT Fetch will query and record replication checkpoints. @@ -949,6 +954,12 @@ The output will include a `cdc_cursor` value at the end of the fetch task: Use this `cdc_cursor` value when starting MOLT Replicator to ensure replication begins from the correct position. For detailed steps, refer to [Load and replicate]({% link molt/migrate-load-replicate.md %}).
+For detailed walkthroughs of migrations that use `molt fetch` in this way, refer to these common migration approaches: + +- [Delta Migration]({% link molt/migration-approach-delta.md %}) +- [Streaming Migration]({% link molt/migration-approach-streaming.md %}) +- [Active-Active Migration]({% link molt/migration-approach-active-active.md %}) + ## See also - [MOLT Fetch Installation]({% link molt/molt-fetch-installation.md %}) diff --git a/src/current/molt/molt-replicator-best-practices.md b/src/current/molt/molt-replicator-best-practices.md new file mode 100644 index 00000000000..138ac3f4916 --- /dev/null +++ b/src/current/molt/molt-replicator-best-practices.md @@ -0,0 +1,147 @@ +--- +title: MOLT Replicator Best Practices +summary: Learn best practices for using MOLT Replicator for continuous replication. +toc: true +docs_area: migrate +--- + +## Test and validate + +To verify that your connections and configuration work properly, run MOLT Replicator in a staging environment before replicating any data in production. Use a test or development environment that closely resembles production. + +## Optimize performance + +{% include molt/optimize-replicator-performance.md %} + +## Security + +Cockroach Labs **strongly** recommends the following: + +### Connection security and credentials + +{% include molt/molt-secure-connection-strings.md %} + +### CockroachDB changefeed security + +For failback scenarios, secure the connection from CockroachDB to MOLT Replicator using TLS certificates. Generate TLS certificates using self-signed certificates, certificate authorities like Let's Encrypt, or your organization's certificate management system. + +#### TLS from CockroachDB to Replicator + +Configure MOLT Replicator with server certificates using the [`--tlsCertificate`]({% link molt/replicator-flags.md %}#tls-certificate) and [`--tlsPrivateKey`]({% link molt/replicator-flags.md %}#tls-private-key) flags to specify the certificate and private key file paths. For example: + +{% include_cached copy-clipboard.html %} +~~~ shell +replicator start \ +--tlsCertificate ./certs/server.crt \ +--tlsPrivateKey ./certs/server.key \ +... +~~~ + +These server certificates must correspond to the client certificates specified in the changefeed webhook URL to ensure proper TLS handshake. + +Encode client certificates for changefeed webhook URLs: + +- Webhook URLs: Use both URL encoding and base64 encoding: `base64 -i ./client.crt | jq -R -r '@uri'` +- Non-webhook contexts: Use base64 encoding only: `base64 -w 0 ca.cert` + +#### JWT authentication + +You can use JSON Web Tokens (JWT) to authorize incoming changefeed connections and restrict writes to a subset of SQL databases or user-defined schemas in the target cluster. + +Replicator supports JWT claims that allow writes to specific databases, schemas, or all of them. JWT tokens must be signed using RSA or EC keys. HMAC and `None` signatures are automatically rejected. + +To configure JWT authentication: + +1. Add PEM-formatted public signing keys to the `_replicator.jwt_public_keys` table in the staging database. + +1. To revoke a specific token, add its `jti` value to the `_replicator.jwt_revoked_ids` table in the staging database. + +The Replicator process re-reads these tables every minute to pick up changes. + +To pass the JWT token from the changefeed to the Replicator webhook sink, use the [`webhook_auth_header` option]({% link {{ site.current_cloud_version }}/create-changefeed.md %}#options): + +{% include_cached copy-clipboard.html %} +~~~ sql +CREATE CHANGEFEED ... WITH webhook_auth_header='Bearer '; +~~~ + +##### Token quickstart + +The following example uses `OpenSSL` to generate keys, but any PEM-encoded RSA or EC keys will work. + +{% include_cached copy-clipboard.html %} +~~~ shell +# Generate an EC private key using OpenSSL. +openssl ecparam -out ec.key -genkey -name prime256v1 + +# Write the public key components to a separate file. +openssl ec -in ec.key -pubout -out ec.pub + +# Upload the public key for all instances of Replicator to find it. +cockroach sql -e "INSERT INTO _replicator.jwt_public_keys (public_key) VALUES ('$(cat ec.pub)')" + +# Reload configuration, or wait one minute. +killall -HUP replicator + +# Generate a token which can write to the ycsb.public schema. +# The key can be decoded using the debugger at https://jwt.io. +# Add the contents of out.jwt to the CREATE CHANGEFEED command: +# WITH webhook_auth_header='Bearer {out.jwt}' +replicator make-jwt -k ec.key -a ycsb.public -o out.jwt +~~~ + +##### External JWT providers + +The `make-jwt` command also supports a [`--claim`]({% link molt/replicator-flags.md %}#claim) flag, which prints a JWT claim that can be signed by your existing JWT provider. The PEM-formatted public key or keys for that provider must be inserted into the `_replicator.jwt_public_keys` table. The `iss` (issuers) and `jti` (token id) fields will likely be specific to your auth provider, but the custom claim must be retained in its entirety. + +{{site.data.alerts.callout_success}} +You can repeat the [`-a`]({% link molt/replicator-flags.md %}#allow) flag to create a claim for multiple schemas. +{{site.data.alerts.end}} + +{% include_cached copy-clipboard.html %} +~~~ shell +replicator make-jwt -a 'database.schema' --claim +~~~ + +~~~json +{ + "iss": "replicator", + "jti": "d5ffa211-8d54-424b-819a-bc19af9202a5", + "https://github.com/cockroachdb/replicator": { + "schemas": [ + [ + "database", + "schema" + ] + ] + } +} +~~~ + +### Production considerations + +- Avoid [`--disableAuthentication`]({% link molt/replicator-flags.md %}#disable-authentication) and [`--tlsSelfSigned`]({% link molt/replicator-flags.md %}#tls-self-signed) flags in production environments. These flags should only be used for testing or development purposes. + +### Supply chain security + +Use the `version` command to verify the integrity of your MOLT Replicator build and identify potential upstream vulnerabilities. + +{% include_cached copy-clipboard.html %} +~~~ shell +replicator version +~~~ + +The output includes: + +- Module name +- go.mod checksum +- Version + +Use this information to determine if your build may be subject to vulnerabilities from upstream packages. Cockroach Labs uses Dependabot to automatically upgrade Go modules, and the team regularly merges Dependabot updates to address security issues. + +## See also + +- [MOLT Replicator]({% link molt/molt-replicator.md %}) +- [MOLT Replicator Installation]({% link molt/molt-replicator-installation.md %}) +- [MOLT Replicator Flags]({% link molt/replicator-flags.md %}) +- [Migration Overview]({% link molt/migration-overview.md %}) diff --git a/src/current/molt/molt-replicator-installation.md b/src/current/molt/molt-replicator-installation.md new file mode 100644 index 00000000000..478ab30c704 --- /dev/null +++ b/src/current/molt/molt-replicator-installation.md @@ -0,0 +1,55 @@ +--- +title: MOLT Replicator Installation +summary: Learn how to install MOLT Replicator and configure prerequisites for continuous replication. +toc: true +docs_area: migrate +--- + +## Prerequisites + +### Supported databases + +MOLT Replicator supports the following source and target databases: + +- PostgreSQL 11-16 +- MySQL 5.7, 8.0 and later +- Oracle Database 19c (Enterprise Edition) and 21c (Express Edition) +- CockroachDB (all currently [supported versions]({% link releases/release-support-policy.md %}#supported-versions)) + +### Database configuration + +The source database must be configured for replication: + +| Database | Configuration Requirements | Details | +|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------| +| PostgreSQL source |
  • Enable logical replication by setting `wal_level = logical`.
| [Configure PostgreSQL for replication]({% link molt/migrate-load-replicate.md %}#configure-source-database-for-replication) | +| MySQL source |
  • 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`.
  • Configure sufficient binlog retention for migration duration.
| [Configure MySQL for replication]({% link molt/migrate-load-replicate.md %}?filters=mysql#configure-source-database-for-replication) | +| Oracle source |
  • Install [Oracle Instant Client]({% link molt/migrate-load-replicate.md %}?filters=oracle#oracle-instant-client).
  • [Enable `ARCHIVELOG` mode]({% link molt/migrate-load-replicate.md %}?filters=oracle#enable-archivelog-and-force-logging), supplemental logging for primary keys, and `FORCE LOGGING`.
  • [Create sentinel table]({% link molt/migrate-load-replicate.md %}#create-source-sentinel-table) (`REPLICATOR_SENTINEL`) in source schema.
  • Grant and verify [LogMiner privileges]({% link molt/migrate-load-replicate.md %}#grant-logminer-privileges).
| [Configure Oracle for replication]({% link molt/migrate-load-replicate.md %}?filters=oracle#configure-source-database-for-replication) | +| CockroachDB source (failback) |
  • [Enable rangefeeds]({% link {{ site.current_cloud_version }}/create-and-configure-changefeeds.md %}#enable-rangefeeds) (`kv.rangefeed.enabled = true`) (CockroachDB {{ site.data.products.core }} clusters only).
| [Configure CockroachDB for replication]({% link molt/migrate-failback.md %}#prepare-the-cockroachdb-cluster) | + +### User permissions + +The SQL user running MOLT Replicator requires specific privileges on both the source and target databases: + +| Database | Required Privileges | Details | +|------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| PostgreSQL source |
  • `SUPERUSER` role (recommended), or the following granular permissions:
  • `CREATE` and `SELECT` on database and tables to replicate.
  • Table ownership for adding tables to publications.
  • `LOGIN` and `REPLICATION` privileges to create replication slots and access replication data.
| [Create PostgreSQL migration user]({% link molt/migrate-load-replicate.md %}#create-migration-user-on-source-database) | +| MySQL source |
  • `SELECT` on tables to replicate.
  • `REPLICATION SLAVE` and `REPLICATION CLIENT` privileges for binlog access.
  • For [`--fetchMetadata`]({% link molt/replicator-flags.md %}#fetch-metadata), either `SELECT` on the source database or `PROCESS` globally.
| [Create MySQL migration user]({% link molt/migrate-load-replicate.md %}?filters=mysql#create-migration-user-on-source-database) | +| Oracle source |
  • `SELECT`, `INSERT`, `UPDATE` on `REPLICATOR_SENTINEL` table.
  • `SELECT` on `V$` views (`V$LOG`, `V$LOGFILE`, `V$LOGMNR_CONTENTS`, `V$ARCHIVED_LOG`, `V$LOG_HISTORY`).
  • `SELECT` on `SYS.V$LOGMNR_*` views (`SYS.V$LOGMNR_DICTIONARY`, `SYS.V$LOGMNR_LOGS`, `SYS.V$LOGMNR_PARAMETERS`, `SYS.V$LOGMNR_SESSION`).
  • `LOGMINING` privilege.
  • `EXECUTE` on `DBMS_LOGMNR`.
  • For Oracle Multitenant, the user must be a common user (prefixed with `C##`) with privileges granted on both CDB and PDB.
| [Create Oracle migration user]({% link molt/migrate-load-replicate.md %}?filters=oracle#create-migration-user-on-source-database)

[Create sentinel table]({% link molt/migrate-load-replicate.md %}?filters=oracle#create-source-sentinel-table)

[Grant LogMiner privileges]({% link molt/migrate-load-replicate.md %}?filters=oracle#grant-logminer-privileges) | +| CockroachDB target (forward replication) |
  • `ALL` on target database.
  • `CREATE` on schema.
  • `SELECT`, `INSERT`, `UPDATE`, `DELETE` on target tables.
  • `CREATEDB` privilege for creating staging schema.
| [Create CockroachDB user]({% link molt/migrate-load-replicate.md %}#create-the-sql-user) | +| PostgreSQL, MySQL, or Oracle target (failback) |
  • `SELECT`, `INSERT`, `UPDATE` on tables to fail back to.
  • For Oracle, `FLASHBACK` is also required.
| [Grant PostgreSQL user permissions]({% link molt/migrate-failback.md %}#grant-target-database-user-permissions)

[Grant MySQL user permissions]({% link molt/migrate-failback.md %}?filter=mysql#grant-target-database-user-permissions)

[Grant Oracle user permissions]({% link molt/migrate-failback.md %}?filter=oracle#grant-target-database-user-permissions) | + +## Installation + +{% include molt/molt-install.md %} + +### Docker usage + +{% include molt/molt-docker.md %} + +## See also + +- [MOLT Replicator]({% link molt/molt-replicator.md %}) +- [MOLT Replicator Flags]({% link molt/replicator-flags.md %}) +- [Load and Replicate]({% link molt/migrate-load-replicate.md %}) +- [Migration Overview]({% link molt/migration-overview.md %}) diff --git a/src/current/molt/molt-replicator-troubleshooting.md b/src/current/molt/molt-replicator-troubleshooting.md new file mode 100644 index 00000000000..e96472fc4dd --- /dev/null +++ b/src/current/molt/molt-replicator-troubleshooting.md @@ -0,0 +1,23 @@ +--- +title: MOLT Replicator Troubleshooting +summary: Troubleshoot common issues with MOLT Replicator during continuous replication. +toc: true +docs_area: migrate +--- + +
+ + + +
+ +{% include molt/molt-troubleshooting-replication.md %} + +{% include molt/molt-troubleshooting-failback.md %} + +## See also + +- [MOLT Replicator]({% link molt/molt-replicator.md %}) +- [MOLT Replicator Installation]({% link molt/molt-replicator-installation.md %}) +- [MOLT Replicator Flags]({% link molt/replicator-flags.md %}) +- [Migration Overview]({% link molt/migration-overview.md %}) diff --git a/src/current/molt/molt-replicator.md b/src/current/molt/molt-replicator.md index aa6d1dbe039..55955a23e89 100644 --- a/src/current/molt/molt-replicator.md +++ b/src/current/molt/molt-replicator.md @@ -13,62 +13,20 @@ MOLT Replicator consumes change data from PostgreSQL [logical replication](https - *Checkpoint*: The position in the source database's transaction log from which replication begins or resumes: LSN (PostgreSQL), GTID (MySQL), or SCN (Oracle). - *Staging database*: A CockroachDB database used by Replicator to store replication metadata, checkpoints, and buffered mutations. Specified with [`--stagingSchema`]({% link molt/replicator-flags.md %}#staging-schema) and automatically created with [`--stagingCreateSchema`]({% link molt/replicator-flags.md %}#staging-create-schema). For details, refer to [Staging database](#staging-database). -- *Forward replication*: Replicate changes from a source database (PostgreSQL, MySQL, or Oracle) to CockroachDB during a migration. For usage details, refer to [Forward replication with initial load](#forward-replication-with-initial-load). -- *Failback*: Replicate changes from CockroachDB back to the source database. Used for migration rollback or to maintain data consistency on the source during migration. For usage details, refer to [Failback to source database](#failback-to-source-database). - -## Prerequisites - -### Supported databases - -MOLT Replicator supports the following source and target databases: - -- PostgreSQL 11-16 -- MySQL 5.7, 8.0 and later -- Oracle Database 19c (Enterprise Edition) and 21c (Express Edition) -- CockroachDB (all currently [supported versions]({% link releases/release-support-policy.md %}#supported-versions)) - -### Database configuration - -The source database must be configured for replication: - -| Database | Configuration Requirements | Details | -|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------| -| PostgreSQL source |
  • Enable logical replication by setting `wal_level = logical`.
| [Configure PostgreSQL for replication]({% link molt/migrate-load-replicate.md %}#configure-source-database-for-replication) | -| MySQL source |
  • 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`.
  • Configure sufficient binlog retention for migration duration.
| [Configure MySQL for replication]({% link molt/migrate-load-replicate.md %}?filters=mysql#configure-source-database-for-replication) | -| Oracle source |
  • Install [Oracle Instant Client]({% link molt/migrate-load-replicate.md %}?filters=oracle#oracle-instant-client).
  • [Enable `ARCHIVELOG` mode]({% link molt/migrate-load-replicate.md %}?filters=oracle#enable-archivelog-and-force-logging), supplemental logging for primary keys, and `FORCE LOGGING`.
  • [Create sentinel table]({% link molt/migrate-load-replicate.md %}#create-source-sentinel-table) (`REPLICATOR_SENTINEL`) in source schema.
  • Grant and verify [LogMiner privileges]({% link molt/migrate-load-replicate.md %}#grant-logminer-privileges).
| [Configure Oracle for replication]({% link molt/migrate-load-replicate.md %}?filters=oracle#configure-source-database-for-replication) | -| CockroachDB source (failback) |
  • [Enable rangefeeds]({% link {{ site.current_cloud_version }}/create-and-configure-changefeeds.md %}#enable-rangefeeds) (`kv.rangefeed.enabled = true`) (CockroachDB {{ site.data.products.core }} clusters only).
| [Configure CockroachDB for replication]({% link molt/migrate-failback.md %}#prepare-the-cockroachdb-cluster) | - -### User permissions - -The SQL user running MOLT Replicator requires specific privileges on both the source and target databases: - -| Database | Required Privileges | Details | -|------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| PostgreSQL source |
  • `SUPERUSER` role (recommended), or the following granular permissions:
  • `CREATE` and `SELECT` on database and tables to replicate.
  • Table ownership for adding tables to publications.
  • `LOGIN` and `REPLICATION` privileges to create replication slots and access replication data.
| [Create PostgreSQL migration user]({% link molt/migrate-load-replicate.md %}#create-migration-user-on-source-database) | -| MySQL source |
  • `SELECT` on tables to replicate.
  • `REPLICATION SLAVE` and `REPLICATION CLIENT` privileges for binlog access.
  • For [`--fetchMetadata`]({% link molt/replicator-flags.md %}#fetch-metadata), either `SELECT` on the source database or `PROCESS` globally.
| [Create MySQL migration user]({% link molt/migrate-load-replicate.md %}?filters=mysql#create-migration-user-on-source-database) | -| Oracle source |
  • `SELECT`, `INSERT`, `UPDATE` on `REPLICATOR_SENTINEL` table.
  • `SELECT` on `V$` views (`V$LOG`, `V$LOGFILE`, `V$LOGMNR_CONTENTS`, `V$ARCHIVED_LOG`, `V$LOG_HISTORY`).
  • `SELECT` on `SYS.V$LOGMNR_*` views (`SYS.V$LOGMNR_DICTIONARY`, `SYS.V$LOGMNR_LOGS`, `SYS.V$LOGMNR_PARAMETERS`, `SYS.V$LOGMNR_SESSION`).
  • `LOGMINING` privilege.
  • `EXECUTE` on `DBMS_LOGMNR`.
  • For Oracle Multitenant, the user must be a common user (prefixed with `C##`) with privileges granted on both CDB and PDB.
| [Create Oracle migration user]({% link molt/migrate-load-replicate.md %}?filters=oracle#create-migration-user-on-source-database)

[Create sentinel table]({% link molt/migrate-load-replicate.md %}?filters=oracle#create-source-sentinel-table)

[Grant LogMiner privileges]({% link molt/migrate-load-replicate.md %}?filters=oracle#grant-logminer-privileges) | -| CockroachDB target (forward replication) |
  • `ALL` on target database.
  • `CREATE` on schema.
  • `SELECT`, `INSERT`, `UPDATE`, `DELETE` on target tables.
  • `CREATEDB` privilege for creating staging schema.
| [Create CockroachDB user]({% link molt/migrate-load-replicate.md %}#create-the-sql-user) | -| PostgreSQL, MySQL, or Oracle target (failback) |
  • `SELECT`, `INSERT`, `UPDATE` on tables to fail back to.
  • For Oracle, `FLASHBACK` is also required.
| [Grant PostgreSQL user permissions]({% link molt/migrate-failback.md %}#grant-target-database-user-permissions)

[Grant MySQL user permissions]({% link molt/migrate-failback.md %}?filter=mysql#grant-target-database-user-permissions)

[Grant Oracle user permissions]({% link molt/migrate-failback.md %}?filter=oracle#grant-target-database-user-permissions) | - -## Installation - -{% include molt/molt-install.md %} - -### Docker usage - -{% include molt/molt-docker.md %} +- *Forward replication*: Replicate changes from a source database (PostgreSQL, MySQL, or Oracle) to CockroachDB during a migration. For usage details, refer to [Forward replication with initial load](#forward-replication-after-initial-load). +- *Failback*: Replicate changes from CockroachDB back to the source database. Used for migration rollback or to maintain data consistency on the source during migration. For usage details, refer to [Failback to source database](#failback-replication). ## How it works MOLT Replicator supports forward replication from PostgreSQL, MySQL, and Oracle, and failback from CockroachDB: -- PostgreSQL source ([`pglogical`](#commands)): MOLT Replicator uses [PostgreSQL logical replication](https://www.postgresql.org/docs/current/logical-replication.html), which is based on publications and replication slots. You create a publication for the target tables, and a slot marks consistent replication points. MOLT Replicator consumes this logical feed directly and applies the data in sorted batches to the target. +- PostgreSQL source ([`pglogical`]({% link molt/replicator-flags.md %}#commands)): MOLT Replicator uses [PostgreSQL logical replication](https://www.postgresql.org/docs/current/logical-replication.html), which is based on publications and replication slots. You create a publication for the target tables, and a slot marks consistent replication points. MOLT Replicator consumes this logical feed directly and applies the data in sorted batches to the target. -- MySQL source ([`mylogical`](#commands)): MOLT Replicator relies on [MySQL GTID-based replication](https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html) to read change data from MySQL binlogs. It works with MySQL versions that support GTID-based replication and applies transactionally consistent feeds to the target. Binlog features that do not use GTIDs are not supported. +- MySQL source ([`mylogical`]({% link molt/replicator-flags.md %}#commands)): MOLT Replicator relies on [MySQL GTID-based replication](https://dev.mysql.com/doc/refman/8.0/en/replication-gtids.html) to read change data from MySQL binlogs. It works with MySQL versions that support GTID-based replication and applies transactionally consistent feeds to the target. Binlog features that do not use GTIDs are not supported. -- Oracle source ([`oraclelogminer`](#commands)): MOLT Replicator uses [Oracle LogMiner](https://docs.oracle.com/en/database/oracle/oracle-database/21/sutil/oracle-logminer-utility.html) to capture change data from Oracle redo logs. Both Oracle Multitenant (CDB/PDB) and single-tenant Oracle architectures are supported. Replicator periodically queries LogMiner-populated views and processes transactional data in ascending SCN windows for reliable throughput while maintaining consistency. +- Oracle source ([`oraclelogminer`]({% link molt/replicator-flags.md %}#commands)): MOLT Replicator uses [Oracle LogMiner](https://docs.oracle.com/en/database/oracle/oracle-database/21/sutil/oracle-logminer-utility.html) to capture change data from Oracle redo logs. Both Oracle Multitenant (CDB/PDB) and single-tenant Oracle architectures are supported. Replicator periodically queries LogMiner-populated views and processes transactional data in ascending SCN windows for reliable throughput while maintaining consistency. -- Failback from CockroachDB ([`start`](#commands)): MOLT Replicator acts as an HTTP webhook sink for a single CockroachDB changefeed. Replicator receives mutations from source cluster nodes, can optionally buffer them in a CockroachDB staging cluster, and then applies time-ordered transactional batches to the target database. Mutations are applied as [`UPSERT`]({% link {{ site.current_cloud_version }}/upsert.md %}) or [`DELETE`]({% link {{ site.current_cloud_version }}/delete.md %}) statements while respecting [foreign-key]({% link {{ site.current_cloud_version }}/foreign-key.md %}) and table dependencies. +- Failback from CockroachDB ([`start`]({% link molt/replicator-flags.md %}#commands)): MOLT Replicator acts as an HTTP webhook sink for a single CockroachDB changefeed. Replicator receives mutations from source cluster nodes, can optionally buffer them in a CockroachDB staging cluster, and then applies time-ordered transactional batches to the target database. Mutations are applied as [`UPSERT`]({% link {{ site.current_cloud_version }}/upsert.md %}) or [`DELETE`]({% link {{ site.current_cloud_version }}/delete.md %}) statements while respecting [foreign-key]({% link {{ site.current_cloud_version }}/foreign-key.md %}) and table dependencies. ### Consistency modes @@ -84,30 +42,11 @@ MOLT Replicator supports three consistency modes for balancing throughput and tr 1. *Immediate* (default for PostgreSQL, MySQL, and Oracle sources): Applies updates as they arrive to Replicator with no buffering or waiting for resolved timestamps. For CockroachDB sources, provides highest throughput but requires no foreign keys on the target schema. -## Commands - -MOLT Replicator provides the following commands: - -| Command | Description | -|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `pglogical` | Replicate from PostgreSQL source to CockroachDB target using logical replication. | -| `mylogical` | Replicate from MySQL source to CockroachDB target using GTID-based replication. | -| `oraclelogminer` | Replicate from Oracle source to CockroachDB target using Oracle LogMiner. | -| `start` | Replicate from CockroachDB source to PostgreSQL, MySQL, or Oracle target ([failback mode](#failback-to-source-database)). Requires a CockroachDB changefeed with rangefeeds enabled. | -| `make-jwt` | Generate JWT tokens for authorizing changefeed connections in failback scenarios. Supports signing tokens with RSA or EC keys, or generating claims for external JWT providers. For details, refer to [JWT authentication](#jwt-authentication). | -| `version` | Display version information and Go module dependencies with checksums. For details, refer to [Supply chain security](#supply-chain-security). | - -For command-specific flags and examples, refer to [Usage](#usage) and [Common workflows](#common-workflows). - -## Flags - -Refer to [Replicator Flags]({% link molt/replicator-flags.md %}). - ## Usage ### Replicator commands -MOLT Replicator provides four commands for different replication scenarios. For detailed workflows, refer to [Common workflows](#common-workflows). +MOLT Replicator provides four commands for different replication scenarios. For example commands, refer to [Common uses](#common-uses). Use `pglogical` to replicate from PostgreSQL to CockroachDB: @@ -140,7 +79,7 @@ replicator start ### Source connection strings {{site.data.alerts.callout_success}} -Follow the security recommendations in [Connection security and credentials](#connection-security-and-credentials). +Follow the security recommendations in [Connection security and credentials]({% link molt/molt-replicator-best-practices.md %}#connection-security-and-credentials). {{site.data.alerts.end}} [`--sourceConn`]({% link molt/replicator-flags.md %}#source-conn) specifies the connection string of the source database for forward replication. @@ -195,7 +134,7 @@ For failback, [`--stagingConn`]({% link molt/replicator-flags.md %}#staging-conn ~~~ {{site.data.alerts.callout_info}} -For failback, [`--targetConn`]({% link molt/replicator-flags.md %}#target-conn) specifies the original source database (PostgreSQL, MySQL, or Oracle). For details, refer to [Failback to source database](#failback-to-source-database). +For failback, [`--targetConn`]({% link molt/replicator-flags.md %}#target-conn) specifies the original source database (PostgreSQL, MySQL, or Oracle). For details, refer to [Failback replication](#failback-replication). {{site.data.alerts.end}} ### Replication checkpoints @@ -241,135 +180,46 @@ The staging database is used to: - Maintain consistency for time-ordered transactional batches while respecting table dependencies. - Provide restart capabilities after failures. -## Security - -Cockroach Labs **strongly** recommends the following: - -### Connection security and credentials - -{% include molt/molt-secure-connection-strings.md %} - -### CockroachDB changefeed security +### Monitoring -For failback scenarios, secure the connection from CockroachDB to MOLT Replicator using TLS certificates. Generate TLS certificates using self-signed certificates, certificate authorities like Let's Encrypt, or your organization's certificate management system. +#### Metrics -#### TLS from CockroachDB to Replicator - -Configure MOLT Replicator with server certificates using the [`--tlsCertificate`]({% link molt/replicator-flags.md %}#tls-certificate) and [`--tlsPrivateKey`]({% link molt/replicator-flags.md %}#tls-private-key) flags to specify the certificate and private key file paths. For example: - -{% include_cached copy-clipboard.html %} -~~~ shell -replicator start \ ---tlsCertificate ./certs/server.crt \ ---tlsPrivateKey ./certs/server.key \ -... -~~~ - -These server certificates must correspond to the client certificates specified in the changefeed webhook URL to ensure proper TLS handshake. - -Encode client certificates for changefeed webhook URLs: - -- Webhook URLs: Use both URL encoding and base64 encoding: `base64 -i ./client.crt | jq -R -r '@uri'` -- Non-webhook contexts: Use base64 encoding only: `base64 -w 0 ca.cert` - -#### JWT authentication - -You can use JSON Web Tokens (JWT) to authorize incoming changefeed connections and restrict writes to a subset of SQL databases or user-defined schemas in the target cluster. - -Replicator supports JWT claims that allow writes to specific databases, schemas, or all of them. JWT tokens must be signed using RSA or EC keys. HMAC and `None` signatures are automatically rejected. - -To configure JWT authentication: - -1. Add PEM-formatted public signing keys to the `_replicator.jwt_public_keys` table in the staging database. - -1. To revoke a specific token, add its `jti` value to the `_replicator.jwt_revoked_ids` table in the staging database. - -The Replicator process re-reads these tables every minute to pick up changes. - -To pass the JWT token from the changefeed to the Replicator webhook sink, use the [`webhook_auth_header` option]({% link {{ site.current_cloud_version }}/create-changefeed.md %}#options): +MOLT Replicator metrics are not enabled by default. Enable Replicator metrics by specifying the [`--metricsAddr`]({% link molt/replicator-flags.md %}#metrics-addr) flag with a port (or `host:port`) when you start Replicator. This exposes Replicator metrics at `http://{host}:{port}/_/varz`. For example, the following flag exposes metrics on port `30005`: -{% include_cached copy-clipboard.html %} -~~~ sql -CREATE CHANGEFEED ... WITH webhook_auth_header='Bearer '; +~~~ +--metricsAddr :30005 ~~~ -##### Token quickstart - -The following example uses `OpenSSL` to generate keys, but any PEM-encoded RSA or EC keys will work. - -{% include_cached copy-clipboard.html %} -~~~ shell -# Generate an EC private key using OpenSSL. -openssl ecparam -out ec.key -genkey -name prime256v1 - -# Write the public key components to a separate file. -openssl ec -in ec.key -pubout -out ec.pub - -# Upload the public key for all instances of Replicator to find it. -cockroach sql -e "INSERT INTO _replicator.jwt_public_keys (public_key) VALUES ('$(cat ec.pub)')" - -# Reload configuration, or wait one minute. -killall -HUP replicator - -# Generate a token which can write to the ycsb.public schema. -# The key can be decoded using the debugger at https://jwt.io. -# Add the contents of out.jwt to the CREATE CHANGEFEED command: -# WITH webhook_auth_header='Bearer {out.jwt}' -replicator make-jwt -k ec.key -a ycsb.public -o out.jwt -~~~ +For guidelines on using and interpreting replication metrics, refer to [Replicator Metrics]({% link molt/replicator-metrics.md %}). -##### External JWT providers +#### Logging -The `make-jwt` command also supports a [`--claim`]({% link molt/replicator-flags.md %}#claim) flag, which prints a JWT claim that can be signed by your existing JWT provider. The PEM-formatted public key or keys for that provider must be inserted into the `_replicator.jwt_public_keys` table. The `iss` (issuers) and `jti` (token id) fields will likely be specific to your auth provider, but the custom claim must be retained in its entirety. +By default, MOLT Replicator writes two streams of logs: operational logs to `stdout` (including `warning`, `info`, `trace`, and some errors) and final errors to `stderr`. -{{site.data.alerts.callout_success}} -You can repeat the [`-a`]({% link molt/replicator-flags.md %}#allow) flag to create a claim for multiple schemas. -{{site.data.alerts.end}} +Redirect both streams to ensure all logs are captured for troubleshooting: {% include_cached copy-clipboard.html %} -~~~ shell -replicator make-jwt -a 'database.schema' --claim -~~~ - -~~~json -{ - "iss": "replicator", - "jti": "d5ffa211-8d54-424b-819a-bc19af9202a5", - "https://github.com/cockroachdb/replicator": { - "schemas": [ - [ - "database", - "schema" - ] - ] - } -} -~~~ - -### Production considerations - -- Avoid [`--disableAuthentication`]({% link molt/replicator-flags.md %}#disable-authentication) and [`--tlsSelfSigned`]({% link molt/replicator-flags.md %}#tls-self-signed) flags in production environments. These flags should only be used for testing or development purposes. +~~~shell +# Merge both streams to console +./replicator ... 2>&1 -### Supply chain security +# Redirect both streams to a file +./replicator ... > output.log 2>&1 -Use the `version` command to verify the integrity of your MOLT Replicator build and identify potential upstream vulnerabilities. +# Merge streams to console while saving to file +./replicator > >(tee replicator.log) 2>&1 -{% include_cached copy-clipboard.html %} -~~~ shell -replicator version +# Use logDestination flag to write all logs to a file +./replicator --logDestination replicator.log ... ~~~ -The output includes: - -- Module name -- go.mod checksum -- Version +Enable debug logging with [`-v`]({% link molt/replicator-flags.md %}#verbose). For more granularity and system insights, enable trace logging with [`-vv`]({% link molt/replicator-flags.md %}#verbose). Pay close attention to warning- and error-level logs, as these indicate when Replicator is misbehaving. -Use this information to determine if your build may be subject to vulnerabilities from upstream packages. Cockroach Labs uses Dependabot to automatically upgrade Go modules, and the team regularly merges Dependabot updates to address security issues. +## Common uses -## Common workflows +### Forward replication (after initial load) -### Forward replication with initial load +In a migration that utilizes [continuous replication]({% link molt/migration-considerations-replication.md %}), run the `replicator` command after [using MOLT Fetch to perform the initial data load]({% link molt/molt-fetch.md %}#initial-bulk-load-before-replication). Run the `replicator` command with the required flags, as shown below:
@@ -438,7 +288,7 @@ Specify the target schema on CockroachDB with [`--targetSchema`]({% link molt/re To replicate from the correct position, specify the appropriate checkpoint value.
-Use [`--slotName`]({% link molt/replicator-flags.md %}#slot-name) to specify the slot [created during the data load]({% link molt/molt-fetch.md %}#load-before-replication), which automatically tracks the LSN (Log Sequence Number) checkpoint: +Use [`--slotName`]({% link molt/replicator-flags.md %}#slot-name) to specify the slot [created during the data load]({% link molt/molt-fetch.md %}#initial-bulk-load-before-replication), which automatically tracks the LSN (Log Sequence Number) checkpoint: {% include_cached copy-clipboard.html %} ~~~ @@ -487,7 +337,6 @@ replicator pglogical \ --stagingCreateSchema ~~~ -For detailed steps, refer to [Load and replicate]({% link molt/migrate-load-replicate.md %}#start-replicator).
@@ -502,7 +351,6 @@ replicator mylogical \ --stagingCreateSchema ~~~ -For detailed steps, refer to [Load and replicate]({% link molt/migrate-load-replicate.md %}?filters=mysql#start-replicator).
@@ -520,63 +368,17 @@ replicator oraclelogminer \ --stagingCreateSchema ~~~ -For detailed steps, refer to [Load and replicate]({% link molt/migrate-load-replicate.md %}?filters=oracle#start-replicator).
-### Resume after interruption - -
- - - -
+For detailed walkthroughs of migrations that use `replicator` in this way, refer to these common migration approaches: -When resuming replication after an interruption, MOLT Replicator automatically uses the stored checkpoint to resume from the correct position. +- [Delta Migration]({% link molt/migration-approach-delta.md %}) +- [Streaming Migration]({% link molt/migration-approach-streaming.md %}) +- [Active-Active Migration]({% link molt/migration-approach-active-active.md %}) -Rerun the same `replicator` command used during [forward replication](#forward-replication-with-initial-load), specifying the same fully-qualified [`--stagingSchema`]({% link molt/replicator-flags.md %}#staging-schema) value as before. Omit [`--stagingCreateSchema`]({% link molt/replicator-flags.md %}#staging-create-schema) and any checkpoint flags. For example: +### Failback replication -
-{% include_cached copy-clipboard.html %} -~~~ shell -replicator pglogical \ ---sourceConn $SOURCE \ ---targetConn $TARGET \ ---slotName molt_slot \ ---stagingSchema defaultdb._replicator -~~~ - -For detailed steps, refer to [Resume replication]({% link molt/migrate-resume-replication.md %}). -
- -
-{% include_cached copy-clipboard.html %} -~~~ shell -replicator mylogical \ ---sourceConn $SOURCE \ ---targetConn $TARGET \ ---stagingSchema defaultdb._replicator -~~~ - -For detailed steps, refer to [Resume replication]({% link molt/migrate-resume-replication.md %}?filters=mysql). -
- -
-{% include_cached copy-clipboard.html %} -~~~ shell -replicator oraclelogminer \ ---sourceConn $SOURCE \ ---sourcePDBConn $SOURCE_PDB \ ---sourceSchema MIGRATION_USER \ ---targetConn $TARGET \ ---stagingSchema defaultdb._replicator -~~~ - -For detailed steps, refer to [Resume replication]({% link molt/migrate-resume-replication.md %}?filters=oracle). -
- -### Failback to source database - -When replicating from CockroachDB back to the source database, MOLT Replicator acts as a webhook sink for a CockroachDB changefeed. +A migration that utilizes [failback replication]({% link molt/migration-considerations-rollback.md %}) replicates data from the CockroachDB cluster back to the source database. In this case, MOLT Replicator acts as a webhook sink for a CockroachDB changefeed. Use the `start` command for failback: @@ -599,7 +401,7 @@ Specify the CockroachDB connection string with [`--stagingConn`]({% link molt/re --stagingConn $STAGING ~~~ -Specify the staging database name with [`--stagingSchema`]({% link molt/replicator-flags.md %}#staging-schema) in fully-qualified `database.schema` format. This should be the same staging database created during [Forward replication with initial load](#forward-replication-with-initial-load): +Specify the staging database name with [`--stagingSchema`]({% link molt/replicator-flags.md %}#staging-schema) in fully-qualified `database.schema` format. This should be the same staging database created during [Forward replication with initial load](#forward-replication-after-initial-load): {% include_cached copy-clipboard.html %} ~~~ @@ -642,52 +444,13 @@ When [creating the CockroachDB changefeed]({% link molt/migrate-failback.md %}#c Explicitly set a default `10s` [`webhook_client_timeout`]({% link {{ site.current_cloud_version }}/create-changefeed.md %}#options) value in the `CREATE CHANGEFEED` statement. This value ensures that the webhook can report failures in inconsistent networking situations and make crash loops more visible. {{site.data.alerts.end}} -## Monitoring - -### Metrics - -MOLT Replicator metrics are not enabled by default. Enable Replicator metrics by specifying the [`--metricsAddr`]({% link molt/replicator-flags.md %}#metrics-addr) flag with a port (or `host:port`) when you start Replicator. This exposes Replicator metrics at `http://{host}:{port}/_/varz`. For example, the following flag exposes metrics on port `30005`: - -~~~ ---metricsAddr :30005 -~~~ - -For guidelines on using and interpreting replication metrics, refer to [Replicator Metrics]({% link molt/replicator-metrics.md %}). - -### Logging - -By default, MOLT Replicator writes two streams of logs: operational logs to `stdout` (including `warning`, `info`, `trace`, and some errors) and final errors to `stderr`. +For a detailed walkthrough of a migration that use `replicator` in this way, refer to this common migration approach: -Redirect both streams to ensure all logs are captured for troubleshooting: +- [Active-Active Migration]({% link molt/migration-approach-active-active.md %}) -{% include_cached copy-clipboard.html %} -~~~shell -# Merge both streams to console -./replicator ... 2>&1 +### Resuming after an interruption -# Redirect both streams to a file -./replicator ... > output.log 2>&1 - -# Merge streams to console while saving to file -./replicator > >(tee replicator.log) 2>&1 - -# Use logDestination flag to write all logs to a file -./replicator --logDestination replicator.log ... -~~~ - -Enable debug logging with [`-v`]({% link molt/replicator-flags.md %}#verbose). For more granularity and system insights, enable trace logging with [`-vv`]({% link molt/replicator-flags.md %}#verbose). Pay close attention to warning- and error-level logs, as these indicate when Replicator is misbehaving. - -## Best practices - -### Test and validate - -To verify that your connections and configuration work properly, run MOLT Replicator in a staging environment before replicating any data in production. Use a test or development environment that closely resembles production. - -### Optimize performance - -{% include molt/optimize-replicator-performance.md %} - -## Troubleshooting +Whether you're using Replicator to perform [forward replication](#forward-replication-after-initial-load) or [failback replication](#failback-replication), an unexpected issue may cause replication to stop. Rerun the `replicator` command as shown below:
@@ -695,20 +458,52 @@ To verify that your connections and configuration work properly, run MOLT Replic
-{% include molt/molt-troubleshooting-replication.md %} +When resuming replication after an interruption, MOLT Replicator automatically uses the stored checkpoint to resume from the correct position. -{% include molt/molt-troubleshooting-failback.md %} +Rerun the same `replicator` command used during forward replication, specifying the same fully-qualified [`--stagingSchema`]({% link molt/replicator-flags.md %}#staging-schema) value as before. Omit [`--stagingCreateSchema`]({% link molt/replicator-flags.md %}#staging-create-schema) and any checkpoint flags. For example: -## Examples +
+{% include_cached copy-clipboard.html %} +~~~ shell +replicator pglogical \ +--sourceConn $SOURCE \ +--targetConn $TARGET \ +--slotName molt_slot \ +--stagingSchema defaultdb._replicator +~~~ -For detailed examples of using MOLT Replicator usage, refer to the migration workflow tutorials: +
-- [Load and Replicate]({% link molt/migrate-load-replicate.md %}): Load data with MOLT Fetch and set up ongoing replication with MOLT Replicator. -- [Resume Replication]({% link molt/migrate-resume-replication.md %}): Resume replication after an interruption. -- [Migration failback]({% link molt/migrate-failback.md %}): Replicate changes from CockroachDB back to the initial source database. +
+{% include_cached copy-clipboard.html %} +~~~ shell +replicator mylogical \ +--sourceConn $SOURCE \ +--targetConn $TARGET \ +--stagingSchema defaultdb._replicator +~~~ + +
+ +
+{% include_cached copy-clipboard.html %} +~~~ shell +replicator oraclelogminer \ +--sourceConn $SOURCE \ +--sourcePDBConn $SOURCE_PDB \ +--sourceSchema MIGRATION_USER \ +--targetConn $TARGET \ +--stagingSchema defaultdb._replicator +~~~ + +
## See also +- [MOLT Replicator Installation]({% link molt/molt-replicator-installation.md %}) +- [MOLT Replicator Flags]({% link molt/replicator-flags.md %}) +- [MOLT Replicator Best Practices]({% link molt/molt-replicator-best-practices.md %}) +- [MOLT Replicator Troubleshooting]({% link molt/molt-replicator-troubleshooting.md %}) - [Migration Overview]({% link molt/migration-overview.md %}) - [Migration Strategy]({% link molt/migration-strategy.md %}) - [MOLT Fetch]({% link molt/molt-fetch.md %}) \ No newline at end of file diff --git a/src/current/molt/replicator-flags.md b/src/current/molt/replicator-flags.md index ad6ec3b8664..8da1d276f7e 100644 --- a/src/current/molt/replicator-flags.md +++ b/src/current/molt/replicator-flags.md @@ -5,7 +5,24 @@ toc: false docs_area: migrate --- -This page lists all available flags for the [MOLT Replicator commands]({% link molt/molt-replicator.md %}#commands): `start`, `pglogical`, `mylogical`, `oraclelogminer`, and `make-jwt`. +## Commands + +MOLT Replicator provides the following commands: + +| Command | Description | +|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `pglogical` | Replicate from PostgreSQL source to CockroachDB target using logical replication. | +| `mylogical` | Replicate from MySQL source to CockroachDB target using GTID-based replication. | +| `oraclelogminer` | Replicate from Oracle source to CockroachDB target using Oracle LogMiner. | +| `start` | Replicate from CockroachDB source to PostgreSQL, MySQL, or Oracle target ([failback mode]({% link molt/molt-replicator.md %}#failback-replication)). Requires a CockroachDB changefeed with rangefeeds enabled. | +| `make-jwt` | Generate JWT tokens for authorizing changefeed connections in failback scenarios. Supports signing tokens with RSA or EC keys, or generating claims for external JWT providers. For details, refer to [JWT authentication]({% link molt/molt-replicator-best-practices.md %}#jwt-authentication). | +| `version` | Display version information and Go module dependencies with checksums. For details, refer to [Supply chain security]({% link molt/molt-replicator-best-practices.md %}#supply-chain-security). | + +For command-specific flags and examples, refer to MOLT Replicator [Usage]({% link molt/molt-replicator.md %}#usage) and [Common uses]({% link molt/molt-replicator.md %}#common-uses). + +## Flags + +This page lists all available flags for the [MOLT Replicator commands](#commands): `start`, `pglogical`, `mylogical`, `oraclelogminer`, and `make-jwt`. | Flag | Commands | Type | Description | |---------------------------------------------------------------------------------------------|-----------------------------------------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -53,7 +70,7 @@ This page lists all available flags for the [MOLT Replicator commands]({% link m | `--schemaRefresh` | `start`, `pglogical`, `mylogical`, `oraclelogminer` | `DURATION` | How often a watcher will refresh its schema. If this value is zero or negative, refresh behavior will be disabled.

**Default:** `1m0s` | | `--scn` | `oraclelogminer` | `INT` | **Required** the first time `replicator` is run. The snapshot System Change Number (SCN) from the initial data load, which provides a replication marker for streaming changes. | | `--scnWindowSize` | `oraclelogminer` | `INT` | The maximum size of SCN bounds per pull iteration from LogMiner. This helps prevent timeout errors when processing large SCN ranges. Set to `0` or a negative value to disable the cap.

**Default:** `3250` | -| `--slotName` | `pglogical` | `STRING` | **Required.** PostgreSQL replication slot name. Must match the slot name specified with `--pglogical-replication-slot-name` in the [MOLT Fetch command]({% link molt/molt-fetch.md %}#load-before-replication).

**Default:** `"replicator"` | +| `--slotName` | `pglogical` | `STRING` | **Required.** PostgreSQL replication slot name. Must match the slot name specified with `--pglogical-replication-slot-name` in the [MOLT Fetch command]({% link molt/molt-fetch.md %}#initial-bulk-load-before-replication).

**Default:** `"replicator"` | | `--sourceConn` | `pglogical`, `mylogical`, `oraclelogminer` | `STRING` | The source database's connection string. When replicating from Oracle, this is the connection string of the Oracle container database (CDB). | | `--sourcePDBConn` | `oraclelogminer` | `STRING` | Connection string for the Oracle pluggable database (PDB). Only required when using an [Oracle multitenant configuration](https://docs.oracle.com/en/database/oracle/oracle-database/21/cncpt/CDBs-and-PDBs.html). [`--sourceConn`](#source-conn) **must** be included. | | `--sourceSchema` | `oraclelogminer` | `STRING` | **Required.** Source schema name on Oracle where tables will be replicated from. | diff --git a/src/current/releases/molt.md b/src/current/releases/molt.md index 2d7f551f884..f139ab7e054 100644 --- a/src/current/releases/molt.md +++ b/src/current/releases/molt.md @@ -101,7 +101,7 @@ Cockroach Labs recommends using the latest available version of each tool. Refer - MOLT Fetch now supports [sharding]({% link molt/molt-fetch.md %}#table-sharding) of primary keys of any data type on PostgreSQL 11+ sources. This can be enabled with the [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag. - Added the [`--ignore-replication-check`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag to allow data loads with planned downtime and no replication setup. The `--pglogical-ignore-wal-check` flag has been removed. -- Added the `--enableParallelApplies` [replication flag]({% link molt/molt-replicator.md %}#flags) to enable parallel application of independent table groups during replication. By default, applies are synchronous. When enabled, this increases throughput at the cost of increased target pool and memory usage. +- Added the `--enableParallelApplies` [replication flag]({% link molt/replicator-flags.md %}) to enable parallel application of independent table groups during replication. By default, applies are synchronous. When enabled, this increases throughput at the cost of increased target pool and memory usage. - Improved cleanup logic for scheduled tasks to ensure progress reporting and prevent indefinite hangs. - Added parallelism gating to ensure the parallelism setting is smaller than the `targetMaxPoolSize`. This helps prevent a potential indefinite hang. - Added new metrics that track start and end times for progress reports (`core_progress_reports_started_count` and `core_progress_reports_ended_count`) and error reports (`core_error_reports_started_count` and `core_error_reports_ended_count`). These provide visibility into the core sequencer progress and help identify hangs in the applier and progress tracking pipeline. @@ -169,7 +169,7 @@ Cockroach Labs recommends using the latest available version of each tool. Refer - MOLT Fetch failback to CockroachDB is now disallowed. - MOLT Verify can now compare tables that are named differently on the source and target schemas. - The `molt` logging date format is now period-delimited for Windows compatibility. -- During replication, an index is now created on all tables by default, improving replication performance. Because index creation can cause the replication process to initialize more slowly, this behavior can be disabled using the `--stageDisableCreateTableReaderIndex` [replication flag]({% link molt/molt-replicator.md %}#flags). +- During replication, an index is now created on all tables by default, improving replication performance. Because index creation can cause the replication process to initialize more slowly, this behavior can be disabled using the `--stageDisableCreateTableReaderIndex` [replication flag]({% link molt/replicator-flags.md %}#stage-disable-create-table-reader-index). - Added a failback metric that tracks the time to write a source commit to the staging schema for a given mutation. - Added a failback metric that tracks the time to write a source commit to the target database for a given mutation. @@ -187,7 +187,7 @@ Cockroach Labs recommends using the latest available version of each tool. Refer - Added an [`--import-region`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag that is used to set the `AWS_REGION` query parameter explicitly in the [`s3` URL]({% link molt/molt-fetch.md %}#bucket-path). - Fixed the [`truncate-if-exists`]({% link molt/molt-fetch.md %}#target-table-handling) schema mode for cases where there are uppercase table or schema names. - Fixed an issue with unsigned `BIGINT` values overflowing in replication. -- Added a `--schemaRefresh` [replication flag]({% link molt/molt-replicator.md %}#flags) that is used to configure the schema watcher refresh delay in the replication phase. Previously, the refresh delay was set to a constant value of 1 minute. Set the flag as follows: `--replicator-flags "--schemaRefresh {value}"`. +- Added a `--schemaRefresh` [replication flag]({% link molt/replicator-flags.md %}#schema-refresh) that is used to configure the schema watcher refresh delay in the replication phase. Previously, the refresh delay was set to a constant value of 1 minute. Set the flag as follows: `--replicator-flags "--schemaRefresh {value}"`. ### December 13, 2024 From 4a520195130d5a385217d1d0240cffc8053b5088 Mon Sep 17 00:00:00 2001 From: Brandon Sanchez Date: Wed, 24 Dec 2025 15:13:40 -0500 Subject: [PATCH 15/15] Made Fetch docs much more compact and clean, improved linking, added draft diagram, improved readability --- .../molt/migration-create-sql-user.md | 2 +- .../molt/migration-schema-design-practices.md | 4 +- .../molt/molt-drop-constraints-indexes.md | 2 +- .../_includes/molt/molt-limitations.md | 2 +- .../v24.2/feature-highlights-migrations.html | 2 +- .../_includes/v23.1/sidebar-data/migrate.json | 70 ++- .../_includes/v23.2/sidebar-data/migrate.json | 70 ++- .../_includes/v24.1/sidebar-data/migrate.json | 70 ++- .../_includes/v24.2/sidebar-data/migrate.json | 70 ++- .../_includes/v24.3/sidebar-data/migrate.json | 70 ++- .../_includes/v25.1/sidebar-data/migrate.json | 70 ++- .../_includes/v25.2/sidebar-data/migrate.json | 70 ++- .../_includes/v25.3/sidebar-data/migrate.json | 70 ++- .../_includes/v25.4/sidebar-data/migrate.json | 70 ++- .../_includes/v26.1/sidebar-data/migrate.json | 19 +- src/current/advisories/a144650.md | 2 +- .../images/molt/molt-fetch-flow-draft.jpg | Bin 0 -> 783773 bytes src/current/molt/migrate-bulk-load.md | 4 +- src/current/molt/migrate-load-replicate.md | 4 +- src/current/molt/migrate-to-cockroachdb.md | 2 +- .../molt/migration-considerations-phases.md | 2 +- .../migration-considerations-replication.md | 8 +- ...migration-considerations-transformation.md | 8 +- src/current/molt/migration-overview.md | 6 +- src/current/molt/migration-strategy.md | 2 +- src/current/molt/molt-fetch-best-practices.md | 12 +- .../molt/molt-fetch-commands-and-flags.md | 96 ++--- src/current/molt/molt-fetch-installation.md | 2 +- src/current/molt/molt-fetch-monitoring.md | 4 +- src/current/molt/molt-fetch.md | 406 ++++++++---------- src/current/molt/molt-replicator.md | 44 +- src/current/molt/molt-type-mapping.md | 69 +++ src/current/molt/replicator-flags.md | 2 +- src/current/releases/molt.md | 24 +- 34 files changed, 904 insertions(+), 454 deletions(-) create mode 100644 src/current/images/molt/molt-fetch-flow-draft.jpg create mode 100644 src/current/molt/molt-type-mapping.md diff --git a/src/current/_includes/molt/migration-create-sql-user.md b/src/current/_includes/molt/migration-create-sql-user.md index dd2e078e3a4..0430f9b4d02 100644 --- a/src/current/_includes/molt/migration-create-sql-user.md +++ b/src/current/_includes/molt/migration-create-sql-user.md @@ -45,7 +45,7 @@ ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO crdb_user; ~~~ -Depending on the MOLT Fetch [data load mode](#data-load-mode) you will use, grant the necessary privileges to run either [`IMPORT INTO`](#import-into-privileges) or [`COPY FROM`](#copy-from-privileges) on the target tables: +Depending on the MOLT Fetch [data load mode]({% link molt/molt-fetch.md %}#import-into-vs-copy-from) you will use, grant the necessary privileges to run either [`IMPORT INTO`](#import-into-privileges) or [`COPY FROM`](#copy-from-privileges) on the target tables: #### `IMPORT INTO` privileges diff --git a/src/current/_includes/molt/migration-schema-design-practices.md b/src/current/_includes/molt/migration-schema-design-practices.md index fc3261e4384..6df1dfa02a7 100644 --- a/src/current/_includes/molt/migration-schema-design-practices.md +++ b/src/current/_includes/molt/migration-schema-design-practices.md @@ -31,7 +31,7 @@ Convert the source table definitions into CockroachDB-compatible equivalents. Co ~~~
- - MOLT Fetch can automatically define matching CockroachDB tables using the {% if page.name != "migration-strategy.md" %}[`drop-on-target-and-recreate`](#table-handling-mode){% else %}[`drop-on-target-and-recreate`]({% link molt/molt-fetch.md %}#target-table-handling){% endif %} option. + - MOLT Fetch can automatically define matching CockroachDB tables using the {% if page.name != "migration-strategy.md" %}[`drop-on-target-and-recreate`](#table-handling-mode){% else %}[`drop-on-target-and-recreate`]({% link molt/molt-fetch.md %}#handle-target-tables){% endif %} option. - If you define the target tables manually, review how MOLT Fetch handles [type mismatches]({% link molt/molt-fetch.md %}#mismatch-handling). You can use the {% if page.name != "migration-strategy.md" %}[MOLT Schema Conversion Tool](#schema-conversion-tool){% else %}[MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}){% endif %} to create matching table definitions. @@ -57,6 +57,6 @@ Convert the source table definitions into CockroachDB-compatible equivalents. Co Avoid using sequential keys. To learn more about the performance issues that can result from their use, refer to the [guidance on indexing with sequential keys]({% link {{site.current_cloud_version}}/sql-faqs.md %}#how-do-i-generate-unique-slowly-increasing-sequential-numbers-in-cockroachdb). If a sequential key is necessary in your CockroachDB table, you must create it manually, after using [MOLT Fetch]({% link molt/molt-fetch.md %}) to load and replicate the data. {{site.data.alerts.end}} -- Review [Transformations]({% link molt/molt-fetch.md %}#transformations) to understand how computed columns and partitioned tables can be mapped to the target, and how target tables can be renamed. +- Review [Transformations]({% link molt/molt-fetch.md %}#define-transformations) to understand how computed columns and partitioned tables can be mapped to the target, and how target tables can be renamed. - By default on CockroachDB, `INT` is an alias for `INT8`, which creates 64-bit signed integers. PostgreSQL and MySQL default to 32-bit integers. Depending on your source database or application requirements, you may need to change the integer size to `4`. For more information, refer to [Considerations for 64-bit signed integers]({% link {{ site.current_cloud_version }}/int.md %}#considerations-for-64-bit-signed-integers). \ No newline at end of file diff --git a/src/current/_includes/molt/molt-drop-constraints-indexes.md b/src/current/_includes/molt/molt-drop-constraints-indexes.md index f52520a8be9..7c98fc6bf54 100644 --- a/src/current/_includes/molt/molt-drop-constraints-indexes.md +++ b/src/current/_includes/molt/molt-drop-constraints-indexes.md @@ -5,7 +5,7 @@ To optimize data load performance, drop all non-`PRIMARY KEY` [constraints]({% l - [Secondary indexes]({% link {{ site.current_cloud_version }}/schema-design-indexes.md %}) - [`CHECK`]({% link {{ site.current_cloud_version }}/check.md %}) - [`DEFAULT`]({% link {{ site.current_cloud_version }}/default-value.md %}) - - [`NOT NULL`]({% link {{ site.current_cloud_version }}/not-null.md %}) (you do not need to drop this constraint when using `drop-on-target-and-recreate` for [table handling]({% link molt/molt-fetch.md %}#target-table-handling)) + - [`NOT NULL`]({% link {{ site.current_cloud_version }}/not-null.md %}) (you do not need to drop this constraint when using `drop-on-target-and-recreate` for [table handling]({% link molt/molt-fetch.md %}#handle-target-tables)) {{site.data.alerts.callout_danger}} Do **not** drop [`PRIMARY KEY`]({% link {{ site.current_cloud_version }}/primary-key.md %}) constraints. diff --git a/src/current/_includes/molt/molt-limitations.md b/src/current/_includes/molt/molt-limitations.md index 0e6a4fd2475..3f52071b137 100644 --- a/src/current/_includes/molt/molt-limitations.md +++ b/src/current/_includes/molt/molt-limitations.md @@ -37,5 +37,5 @@ - Running DDL on the source or target while replication is in progress can cause replication failures. - `TRUNCATE` operations on the source are not captured. Only `INSERT`, `UPDATE`, `UPSERT`, and `DELETE` events are replicated. -- Changes to virtual columns are not replicated automatically. To migrate these columns, you must define them explicitly with [transformation rules]({% link molt/molt-fetch.md %}#transformations). +- Changes to virtual columns are not replicated automatically. To migrate these columns, you must define them explicitly with [transformation rules]({% link molt/molt-fetch.md %}#define-transformations). {% endif %} \ No newline at end of file diff --git a/src/current/_includes/releases/v24.2/feature-highlights-migrations.html b/src/current/_includes/releases/v24.2/feature-highlights-migrations.html index 7df377498f3..fac0c718033 100644 --- a/src/current/_includes/releases/v24.2/feature-highlights-migrations.html +++ b/src/current/_includes/releases/v24.2/feature-highlights-migrations.html @@ -31,7 +31,7 @@ MOLT Fetch transformation rules

- Column exclusion, computed columns, and partitioned tables are now supported in table migrations with MOLT Fetch. They are supported via a new transformations framework that allows the user to specify a JSON file with instructions on how MOLT Fetch should treat certain schemas, tables, or underlying columns. + Column exclusion, computed columns, and partitioned tables are now supported in table migrations with MOLT Fetch. They are supported via a new transformations framework that allows the user to specify a JSON file with instructions on how MOLT Fetch should treat certain schemas, tables, or underlying columns.

All★★ diff --git a/src/current/_includes/v23.1/sidebar-data/migrate.json b/src/current/_includes/v23.1/sidebar-data/migrate.json index d517d0c271a..fde9c2bf230 100644 --- a/src/current/_includes/v23.1/sidebar-data/migrate.json +++ b/src/current/_includes/v23.1/sidebar-data/migrate.json @@ -54,14 +54,60 @@ "items": [ { "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Type Mapping", + "urls": [ + "/molt/molt-type-mapping.html" + ] + } ] }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Metrics", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { @@ -80,7 +126,7 @@ ] }, { - "title": "Flags", + "title": "Commands and Flags", "urls": [ "/molt/replicator-flags.html" ] @@ -117,33 +163,33 @@ "title": "Common Migration Approaches", "items": [ { - "title": "Classic Bulk Load", + "title": "Classic Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-classic-bulk-load.html" ] }, { - "title": "Phased Bulk Load", + "title": "Phased Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-phased-bulk-load.html" ] }, { "title": "Delta Migration", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-approach-delta.html" ] }, { "title": "Streaming Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-streaming.html" ] }, { "title": "Active-Active Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-active-active.html" ] } ] diff --git a/src/current/_includes/v23.2/sidebar-data/migrate.json b/src/current/_includes/v23.2/sidebar-data/migrate.json index d517d0c271a..fde9c2bf230 100644 --- a/src/current/_includes/v23.2/sidebar-data/migrate.json +++ b/src/current/_includes/v23.2/sidebar-data/migrate.json @@ -54,14 +54,60 @@ "items": [ { "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Type Mapping", + "urls": [ + "/molt/molt-type-mapping.html" + ] + } ] }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Metrics", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { @@ -80,7 +126,7 @@ ] }, { - "title": "Flags", + "title": "Commands and Flags", "urls": [ "/molt/replicator-flags.html" ] @@ -117,33 +163,33 @@ "title": "Common Migration Approaches", "items": [ { - "title": "Classic Bulk Load", + "title": "Classic Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-classic-bulk-load.html" ] }, { - "title": "Phased Bulk Load", + "title": "Phased Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-phased-bulk-load.html" ] }, { "title": "Delta Migration", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-approach-delta.html" ] }, { "title": "Streaming Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-streaming.html" ] }, { "title": "Active-Active Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-active-active.html" ] } ] diff --git a/src/current/_includes/v24.1/sidebar-data/migrate.json b/src/current/_includes/v24.1/sidebar-data/migrate.json index d517d0c271a..fde9c2bf230 100644 --- a/src/current/_includes/v24.1/sidebar-data/migrate.json +++ b/src/current/_includes/v24.1/sidebar-data/migrate.json @@ -54,14 +54,60 @@ "items": [ { "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Type Mapping", + "urls": [ + "/molt/molt-type-mapping.html" + ] + } ] }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Metrics", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { @@ -80,7 +126,7 @@ ] }, { - "title": "Flags", + "title": "Commands and Flags", "urls": [ "/molt/replicator-flags.html" ] @@ -117,33 +163,33 @@ "title": "Common Migration Approaches", "items": [ { - "title": "Classic Bulk Load", + "title": "Classic Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-classic-bulk-load.html" ] }, { - "title": "Phased Bulk Load", + "title": "Phased Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-phased-bulk-load.html" ] }, { "title": "Delta Migration", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-approach-delta.html" ] }, { "title": "Streaming Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-streaming.html" ] }, { "title": "Active-Active Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-active-active.html" ] } ] diff --git a/src/current/_includes/v24.2/sidebar-data/migrate.json b/src/current/_includes/v24.2/sidebar-data/migrate.json index d517d0c271a..fde9c2bf230 100644 --- a/src/current/_includes/v24.2/sidebar-data/migrate.json +++ b/src/current/_includes/v24.2/sidebar-data/migrate.json @@ -54,14 +54,60 @@ "items": [ { "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Type Mapping", + "urls": [ + "/molt/molt-type-mapping.html" + ] + } ] }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Metrics", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { @@ -80,7 +126,7 @@ ] }, { - "title": "Flags", + "title": "Commands and Flags", "urls": [ "/molt/replicator-flags.html" ] @@ -117,33 +163,33 @@ "title": "Common Migration Approaches", "items": [ { - "title": "Classic Bulk Load", + "title": "Classic Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-classic-bulk-load.html" ] }, { - "title": "Phased Bulk Load", + "title": "Phased Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-phased-bulk-load.html" ] }, { "title": "Delta Migration", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-approach-delta.html" ] }, { "title": "Streaming Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-streaming.html" ] }, { "title": "Active-Active Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-active-active.html" ] } ] diff --git a/src/current/_includes/v24.3/sidebar-data/migrate.json b/src/current/_includes/v24.3/sidebar-data/migrate.json index d517d0c271a..fde9c2bf230 100644 --- a/src/current/_includes/v24.3/sidebar-data/migrate.json +++ b/src/current/_includes/v24.3/sidebar-data/migrate.json @@ -54,14 +54,60 @@ "items": [ { "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Type Mapping", + "urls": [ + "/molt/molt-type-mapping.html" + ] + } ] }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Metrics", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { @@ -80,7 +126,7 @@ ] }, { - "title": "Flags", + "title": "Commands and Flags", "urls": [ "/molt/replicator-flags.html" ] @@ -117,33 +163,33 @@ "title": "Common Migration Approaches", "items": [ { - "title": "Classic Bulk Load", + "title": "Classic Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-classic-bulk-load.html" ] }, { - "title": "Phased Bulk Load", + "title": "Phased Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-phased-bulk-load.html" ] }, { "title": "Delta Migration", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-approach-delta.html" ] }, { "title": "Streaming Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-streaming.html" ] }, { "title": "Active-Active Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-active-active.html" ] } ] diff --git a/src/current/_includes/v25.1/sidebar-data/migrate.json b/src/current/_includes/v25.1/sidebar-data/migrate.json index d517d0c271a..fde9c2bf230 100644 --- a/src/current/_includes/v25.1/sidebar-data/migrate.json +++ b/src/current/_includes/v25.1/sidebar-data/migrate.json @@ -54,14 +54,60 @@ "items": [ { "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Type Mapping", + "urls": [ + "/molt/molt-type-mapping.html" + ] + } ] }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Metrics", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { @@ -80,7 +126,7 @@ ] }, { - "title": "Flags", + "title": "Commands and Flags", "urls": [ "/molt/replicator-flags.html" ] @@ -117,33 +163,33 @@ "title": "Common Migration Approaches", "items": [ { - "title": "Classic Bulk Load", + "title": "Classic Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-classic-bulk-load.html" ] }, { - "title": "Phased Bulk Load", + "title": "Phased Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-phased-bulk-load.html" ] }, { "title": "Delta Migration", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-approach-delta.html" ] }, { "title": "Streaming Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-streaming.html" ] }, { "title": "Active-Active Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-active-active.html" ] } ] diff --git a/src/current/_includes/v25.2/sidebar-data/migrate.json b/src/current/_includes/v25.2/sidebar-data/migrate.json index d517d0c271a..fde9c2bf230 100644 --- a/src/current/_includes/v25.2/sidebar-data/migrate.json +++ b/src/current/_includes/v25.2/sidebar-data/migrate.json @@ -54,14 +54,60 @@ "items": [ { "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Type Mapping", + "urls": [ + "/molt/molt-type-mapping.html" + ] + } ] }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Metrics", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { @@ -80,7 +126,7 @@ ] }, { - "title": "Flags", + "title": "Commands and Flags", "urls": [ "/molt/replicator-flags.html" ] @@ -117,33 +163,33 @@ "title": "Common Migration Approaches", "items": [ { - "title": "Classic Bulk Load", + "title": "Classic Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-classic-bulk-load.html" ] }, { - "title": "Phased Bulk Load", + "title": "Phased Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-phased-bulk-load.html" ] }, { "title": "Delta Migration", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-approach-delta.html" ] }, { "title": "Streaming Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-streaming.html" ] }, { "title": "Active-Active Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-active-active.html" ] } ] diff --git a/src/current/_includes/v25.3/sidebar-data/migrate.json b/src/current/_includes/v25.3/sidebar-data/migrate.json index d517d0c271a..fde9c2bf230 100644 --- a/src/current/_includes/v25.3/sidebar-data/migrate.json +++ b/src/current/_includes/v25.3/sidebar-data/migrate.json @@ -54,14 +54,60 @@ "items": [ { "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Type Mapping", + "urls": [ + "/molt/molt-type-mapping.html" + ] + } ] }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Metrics", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { @@ -80,7 +126,7 @@ ] }, { - "title": "Flags", + "title": "Commands and Flags", "urls": [ "/molt/replicator-flags.html" ] @@ -117,33 +163,33 @@ "title": "Common Migration Approaches", "items": [ { - "title": "Classic Bulk Load", + "title": "Classic Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-classic-bulk-load.html" ] }, { - "title": "Phased Bulk Load", + "title": "Phased Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-phased-bulk-load.html" ] }, { "title": "Delta Migration", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-approach-delta.html" ] }, { "title": "Streaming Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-streaming.html" ] }, { "title": "Active-Active Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-active-active.html" ] } ] diff --git a/src/current/_includes/v25.4/sidebar-data/migrate.json b/src/current/_includes/v25.4/sidebar-data/migrate.json index d517d0c271a..fde9c2bf230 100644 --- a/src/current/_includes/v25.4/sidebar-data/migrate.json +++ b/src/current/_includes/v25.4/sidebar-data/migrate.json @@ -54,14 +54,60 @@ "items": [ { "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Type Mapping", + "urls": [ + "/molt/molt-type-mapping.html" + ] + } ] }, { "title": "Fetch", - "urls": [ - "/molt/molt-fetch.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/molt/molt-fetch.html" + ] + }, + { + "title": "Installation", + "urls": [ + "/molt/molt-fetch-installation.html" + ] + }, + { + "title": "Commands and Flags", + "urls": [ + "/molt/molt-fetch-commands-and-flags.html" + ] + }, + { + "title": "Metrics", + "urls": [ + "/molt/molt-fetch-monitoring.html" + ] + }, + { + "title": "Best Practices", + "urls": [ + "/molt/molt-fetch-best-practices.html" + ] + }, + { + "title": "Troubleshooting", + "urls": [ + "/molt/molt-fetch-troubleshooting.html" + ] + } ] }, { @@ -80,7 +126,7 @@ ] }, { - "title": "Flags", + "title": "Commands and Flags", "urls": [ "/molt/replicator-flags.html" ] @@ -117,33 +163,33 @@ "title": "Common Migration Approaches", "items": [ { - "title": "Classic Bulk Load", + "title": "Classic Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-classic-bulk-load.html" ] }, { - "title": "Phased Bulk Load", + "title": "Phased Bulk Load Migration", "urls": [ - "/molt/migrate-bulk-load.html" + "/molt/migration-approach-phased-bulk-load.html" ] }, { "title": "Delta Migration", "urls": [ - "/molt/migrate-load-replicate.html" + "/molt/migration-approach-delta.html" ] }, { "title": "Streaming Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-streaming.html" ] }, { "title": "Active-Active Migration", "urls": [ - "/molt/migrate-failback.html" + "/molt/migration-approach-active-active.html" ] } ] diff --git a/src/current/_includes/v26.1/sidebar-data/migrate.json b/src/current/_includes/v26.1/sidebar-data/migrate.json index 571582248ad..fde9c2bf230 100644 --- a/src/current/_includes/v26.1/sidebar-data/migrate.json +++ b/src/current/_includes/v26.1/sidebar-data/migrate.json @@ -54,15 +54,26 @@ "items": [ { "title": "Schema Conversion Tool", - "urls": [ - "/cockroachcloud/migrations-page.html" + "items": [ + { + "title": "Guide", + "urls": [ + "/cockroachcloud/migrations-page.html" + ] + }, + { + "title": "Type Mapping", + "urls": [ + "/molt/molt-type-mapping.html" + ] + } ] }, { "title": "Fetch", "items": [ { - "title": "Oveview", + "title": "Guide", "urls": [ "/molt/molt-fetch.html" ] @@ -80,7 +91,7 @@ ] }, { - "title": "Monitoring", + "title": "Metrics", "urls": [ "/molt/molt-fetch-monitoring.html" ] diff --git a/src/current/advisories/a144650.md b/src/current/advisories/a144650.md index 969f5c24488..e8d4615b0b2 100644 --- a/src/current/advisories/a144650.md +++ b/src/current/advisories/a144650.md @@ -110,7 +110,7 @@ By default, MOLT Fetch uses [`IMPORT INTO`]({% link v25.1/import-into.md %}) to - If you ran MOLT Verify after completing your MOLT Fetch run, and Verify did not find mismatches, then MOLT Fetch was unaffected by this issue. -- If you did not run Verify after Fetch, analyze the exported files that exist in your configured [Fetch data path]({% link molt/molt-fetch.md %}#data-path) to determine the expected number of rows. Then follow steps 1-3 in the [`IMPORT`](#import) section. +- If you did not run Verify after Fetch, analyze the exported files that exist in your configured [Fetch data path]({% link molt/molt-fetch.md %}#define-intermediate-storage) to determine the expected number of rows. Then follow steps 1-3 in the [`IMPORT`](#import) section. #### Physical Cluster Replication diff --git a/src/current/images/molt/molt-fetch-flow-draft.jpg b/src/current/images/molt/molt-fetch-flow-draft.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cc40ccfa73e5639577d10a13ac02546ca00ca8e5 GIT binary patch literal 783773 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

VD=5n}A~8%?uWb!?42p@Zs>>62Z>03WT+ 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 )vD|+^A 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

  • $>9K|*na7qV zMerBlw4MUcCD!#&S6bHLQzUM@+d=o1ERnk>jsE~ZF~xg+^4!wM(oE&uj!)%H34w!N zelHg+MORWmPMwv6`cq_z3%x$?OTCF_wY-g@nkP_I)wm#o?Nj`#O%egnRxqgI`J!!O z;6IAL12xZvSJ3$Hz!!HPV6~LY88hctV;gcoJLAd5dt;wk?EEYHT}Nz?Y2G%|68j9X z&39o9|>-`!#ON^FjY}~`W zkMS~&7}wI%&ZuH(s(AR_uDyO|JgGRlz|Mc#BjDce`3POAvVwDKC&*81;MbyfXT;h^ zi}Zxnv^9`gI}}4G0iSPHz$c3F%b(eI;pXJ>Z}lH9f?)FijDf}p!EWBQ?-n{;mXT=| zoux#O!EYL(A^-*lu&*y091@TFHSTFoo9z~P-=5X;_r_0wP4Por(|kdv>T78=q$>r? za;b938Oj*I<2ffFk=nk48@}ljDcDXchYgCI33JojxkXDxC+>}<_GCK^4`eVbM9nriYqFeZL!`8yq#?)aHedZ^tG495T04OZZ=_Bo^(QZdw5pGs~L=3A90=zezC zUFyHHAI5oNytRAXDeamxIaK>iq}V%|X1=(W_Kx@;9*YjCKCu4)Xq5vC zMTv~cn2*1I9eslnpBY89O+siRjLs~$P<7r?rY zfIc6#pRPmpeM0v3TbUya7^-j(5;8ky8Sh@VBA2Tmj{MSnD{Mw8Rq8sD+;NIZ$c16t zn@=L9U)?SgZKn^EVwA99gIt#wvD`}@KqHZkl-8ByKfKETFf+|Vj8VVdi-ng_-iz9% zDoDqE#-ikbij*+VsP9MwUY_ED6~1BHwJ0m}6o6#sr2rsKcOElRGZx?ul;gCn2;@{D zijSoLKcVDxrxTHZ+|w}6%`^-@UV?xn0CQ~8F??}Ury=cHA9+Uu?R(?i(>2?Ct z-MdbIAx^?M1}TC0 z#RRRz+%iQWlWF8qot~W3U@6YyL1e_PI@Nsh)}6HDts;sH#WEf+3B@#|hdWf7c3Y4M zrs47lVlzMtPIxrpFgT@E!Nn;!IH1r~A1-}q$_79toA2vNfQ*im0OsAu6y4{hDZ~{3 z(tt_gfE)ne^fcFDj(Um!>IvqWRN&*Opoh3DoT$C4LSti+ zsu$%T;A8<_i?LX5Kw&FnsDWZ zZ%k7OIU%_tr2r=5)bKh|ZpYWXE)U)OX?Q%)0}eCAF6Qk<;YU43O3(!oauoHXAh{}O z5p$ZKpa4(=LNYpvmaw<$< z;L28#g~L-SL!o);7mjyLVphQ zqy^!QXaXifw~o}<+an#tN(%JPS~d=fXaS)Z^G-4L%>)thieXnh>RJIv#|E8(25G$x z4_a~phYiRzASuIAoDqc_ibva@mW~v0)X)P)XzF>OoSr*S7y*(oKnM^2gvB z1M#=R=rE;j?wlWCyCT0+ZVY+KKm~3}^rw=k?kO0k9XY1wJY%g$3^`-h0MWD$da(8|{7_k6QJF&#%jC7{;85H&7gW8Y*jGtNp>}VYab5F+B=dDD+vz6;k zUB$57MFDm{Xx&2+PCHYI(7c>?ph7B=4i8FUz&Hk_90SKR(lSOz6j%n5I@B($_k~#6 zJ5x?`wtylEqm$O0Fiuy$6ySumN#dj&at}%XP^u2nJ5nfC$7+5{V;oWxZW|cpfEY(* z{ApJ!_rD5w8RY&n9)G0(AZ|YzLU!;vccj7XKp5cq&;xOtlg%-JJQ|w>`%_pBlmO5% zz^9D&rN-KE8;2AC2RNX+3}TuAq&e$ASZd4jeBQM)yn8Y|YMyY|H7^+aXb)yeB^bs} z(x7RbPwvJKtszoAl?%zYfGbXU2eSh_<1XB_N9LAn$}>?hVt3-1lEdjow2*s0B6cy3 z0O0nfZHS*?o4`w{5Ay?C-C}ONh?fTP42ilRa20GF0BwdEAai}U( z5OOibFlw#VpQT-tm%$zjxZGyZY`%ZJwjjUA z3RUnIfE5ZyqT41w;Z$wN^%c@kfF9LL6HZt={+df#X_iqO& zsX)az;wmkeoEKvs{t>SYxncc}U;`b*eVqWw^Z*Q12z&?NyJ<|e+BK{!z=ztn2R%5h zqL-8JPwUu^=VIiCRAIs4%^uakg56Udn5|)N3XO=Ypn4os#jtu)3t;A^Rq9LPlNzTL zvLuc;qy8N72q%^Vd-bUt$0G-pHIc!{W&oZ)4r(3Qpg(Gkd3PT#k#X2KU}A`?9#xPq z!0pazkJ-@-l0g(u2@fk8g$Eroim)1*P@eTltdeTtesS08MR5NBvk*qpF79wch{8F?B=e4I?XchSCXvVg z056ZHNFabcPHDS#oYbs#oF3%U6daOk<4(c!bfS)wpaK;i#CfK0rw64d+Ce9;YEn3< zU^jL;4z$o&K_-`)MI@3BK}ZEsag*Mh>^oF=Jo-~UrhpZJeoty<(~fGuDpvsVDkk~4 z2c-Z+Qyr=%C3;n$rH5K+jX~+n09H`Pk|-lRIH?#M;*g>aNv46H|JD7VDmkV3hA~Ra zyyBV*V!mwk2bO&ODM2TbOx$`JdgC0>0*(zSeYF{4PAWpV6ac?_nrRs1Qh+gvceMZj z=bBt@;L>s0iU4C0rwdXpJJNs{aZCzS^FR+H+L{I`U;(5f6``1eo|GOa9CV=bKnlQ~ zMMtocQz#&FPXjao2GL7_QiaDRkO7(iKt(M$$4%)#4I^kZ0Df?4c6x}YZj=EaY}5Iu zv$P6&ws@cmR?-EXA3I3sYx4{CtMFc-;qMa1;!AXvYa8Zv3KZrxIQdUr2Vcg&OdqC4 zQO$W5$1O6_`{CvM*S6~*goaU z(EL-=Ad%QT!^v((v;E)5X1`XiPzT%JIj_k-*})#;;@5{^1P5u^$paYJ2tUrhTCNE) z5>9K-<4^b1=sXg%2r-j`P9p<~2+cnj9M{L4qe0^Xnm~ESYIym0+e*A-)_^bo8z57N z+;V6Dlh%_PPX{%a58{+@%^^Heg$Ft9KnO_9E_unIs)0$I3=hVD3T&Ttor@azL4-ZS*VtwnLeCtY5QOTPSeV@IcXqb0MCDK$k)=EkHCL~dbBGP z+6}6|Lh%0Qk58BX0Iys%=j@&Ex?w75ruR>2ILMetqtpOKYo<7yl78!jgO;-DZ1^+w zo%mtma~-Aht)*PZ`*A4@pb#)}N|JNI01`Ty_q%EIjZr-9CsDP!LIL?DOn`krCl&e4 z;@{Z+0LJ!H+>Z)g*lIRNH^4(TbEz8PsT{Zat(Q7Sq3)!lmZAi&V7A&t_g5Vf#^hV3ypw>$dWh1hciUQ;)-s(xbZltNt!YX!drRt*Dc( z^njMY>PYALR6Y~0wa|TXC+W;~vpzNq=Ztstr?#CtD3D+b^SFVE{GF5bp7_0Nq5lBk zA!!MeIYqVMy%e3Jk73rSY9ADSJA6Zs%WrqBOsshpOC`Kx*x(RX%qqnza zV~>1bXWWYUTz<#iJ(lClmt4{WY@;lo1^{*AW=Zttn%T7dj&*mOeXqrK-c~l9mbq=e zm-VTqlI3u}w5xJuh^qP>o~Qd{X%WdG(L5h@GVb{v@%*umqUZCjeoxykRe3q^ovd;F z{f#T`X7(To=q!I^Uk7Q>Np<2c5?$Oy8QgY96iBECecQYGcCG{Bx5HnBejfOJsB4}M zg63{-R(SgVsZ(ul>8I$uf_iW6SXT%H%fv_3oHEp z0H$3&6e4olRNRsR6tw)}eN&liXEm^k6&XCv|l`q$BZ5dE6| z68K+4O&Ro|sazcSmzOMFQ=W&00An3GXPT+5d=&kk{vK#IJ}1>Qj6-Ofo?D3n`H~(L zP%{7v9tR&&URtS>x%)U%yEc-o6?S~FH|>M*TJ}Z@Hj;&-+$0doy+}CYk_kTIxeKq_ zL*pi`Gs@m7YiML8e7GY(K?6Kt0l_}?*l2$c{u|ipO(*;znsv5{ZhCIyf5Hu>qvDyA4byWvYHL>ZMToh2yu>?AfEN#jh+(&@z4rxQu{~cwEjBy*W#Ng zY|gXd9YP5R;@&A42?sxUBR|f(=URtd(;2OGk*EuVRd$N$*q@*K%f~*)kzcC67`$%} z!=D5-&6$C9Jwevi#@!GNg}(Fk93VNyIU>Gx@K1r#-^0`VS@?l)ZVtmeowTGdkg>wa zE`ITBjf>L+AE$O%m|^6-qNJC|#=M=_=V#S>@785wSoxz=_i#w>MvXX zyNUk*Ij^mg_A$}t^8Wy~d`ovcuEQ&6k*bX2ra|dmiTgQtJ`Foh)x2?W8l<|!h8QqT zQZU7xasJa|9fmlsbn!;1HizLoYge=c+*xV!OArScWmEn&;^uk%XNvX|J=L~_Q={&= zNcg71;b*}Q2YBW`2SH_X;v1)tVtH>EI!5c0jK#1wzH)QN*Xo@Q;fKSY3{Nv?{v6Y7 z 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%0AKBkLKF^DXgq4 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

    o0MN< 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 z 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≺!1ypwv=hrigX0?=q0S%SS?i<(}*Ty zw=9-mrjIWkoU!#dq0v0XwsjQPP6<8b0C#9q_z>0anxG!vL`KrHEQeYDZ#r};k8)s9mtVd!kk9ikoSd^6}$Ykhc9KtdGJKDY=1@)!DvfXZ{?%eC_b#>uc|Vbr6ncUBCWn&Ds^-v7Au+vY~UX znbf5l-J{bBMTLF#`VYtw9{Ibp=y);MCVh0$s%4bv3)8?(z0H$ivh#N9@AQT1+hQ&h z&)|;U&ee$Okrm$esHcqjX3AdL-5R(4rFJD~P7XW|%NGW5$wlDbFNvr5q;2U1kJ90K zw&-II2bXnU>V&;Lu^Qf&BE6@m)K*1Cb)S?7Ub3&#_5Xm#&==R}fd;vi26n^$0Kt^`@I>_q%jYA{{8O4eHUmX1ts zHSu_pQH~toS92ny#RP6+H!03t(Ux&!_~GL(rg#}$QyBJVsC-z^wCK&twtm)Nn?oxM zy}pu$6Z34wS6(nUhw%-io!^M+UQV-TrwODRmU0Q-is)`o z88wBi-v1A(h53>o0?U&&G@TlY#iJ+}*+%K%;Kc+2hNip4;Bt8zxc=C&5a5i1X zoH5p0BQ)s2slZ`#*t;yPdULbn$>7}QK@R@3Z51 zuK)6-e)s6ge#e1I*I=k%u<}6Cmu=<@Q8t;#ctf?#xIgTgb_6@7o0Q!f!|Q(t&Yhh* zVUyj#&Ae+hbKB9!DbW?7tF$50$4ru{qgLd^jzyJ<0*%4bvUYD+sc!XrjrZZ|6@_h5Ii68yn|3EFhTTA7wCX$G_C7UcLurTnZJ=)KaJuz7 zxsA;GdU}kB;f}B3xC`5jYq=6saEB73!;ulnf&QUaK0N45Yr*(4^uxm+Yqa&jvmXK}yg`S4tvP$-klPF(Z87u}tyDqLu@3gU@}f?A z)m#6O$Aco8%nFyH-u=--NX@f~Nl0dSd@`O5^oL3Ba>UMc4z9myicmB}Hf+rNj#6M2 z(P65MmgRD76Bu|a46?YegaeYFG;f;JI=H{ATnNE{_yIM*F~(Jr*2wKejUZl7V6jZe z`tua?h@Z|v@|SlV`}Dc-4<5Q_ZdYbsPMiVd&hPxgpKL?^IyEuZ+hjd@h-3Me7Wi)X zkn?EugtMYt^|J4UB!~5MrAXzm>oH+URx5YE2Bh)h1IVGc(DrnX@29#$o_waeD`WRZ zukUh93l2{xoWuk|?Xsh5-eb;SwIQ%8^#^2Lf&aH@uZc_y;TvK^_-Jw2-tG&`+kP8Q z2l4iUPL)1+)L*&*Ax^=(c8*8-0!RvR;47HTb*Z1tYB5T>Kna%&xKc$F`>1I79ES0@ zJg5*YVJQkwPpH`=$@8b%P_DnPW_E!rOBi5#;fpFseTwOTyC`dUX2pf_1evMscq?^4 z9^Rxj(?@OZxiS{(Fcr~w6l5H*ie_WR#0<`FzyjT#YtD}4a)bGCcg^b9`#8ffocv55 zFd?^sW}-*u%C||&+GOdz0Qu%ul+}vhl@swM$?^?K=C2}W`k-DHiXbLYZu6z^sY4PS ztyE*45aNah|;b)TA=7&jp3gPsLCJNJtMB-2qaK8kV57a(uke^omP)5)q!T{s;-1 zaFbXQ?XwkloPsem=_;*@etb9bSD%ac^BloAY`6T5CXyH)j%GtTQKxIrggdBvj=}ef ztnd&LEgV)1G55)i2{h(>%me|4OTxsuspN;4)Y456bYV$~UA-ZkW!j>pg_3Lr9- z3#n-N@w5hpIerq2ZMv?AB@&swxLOHn6%AmChT|_A7V%eQ9SH+*Kj*!WWjLFlak#)aK zi@(uuTF4R+^@!Rh4@v~dW14}c$TmJRaY!R-3uOIJ2BPki4))#il2G$DWI|DS(`wKM zQPPdoxLvIPZ&!fDOyB7aE>AHqV)z{%M~jDaT*TVRnx=%$gZEa)CtuxM9A9#3LN9+BjYfc7anW0N@ci zfBh*mQ_4)P{m2y$T<8WAsj=z$!8JL!Q<~c~E9eVGdD5}`+(k>=-_4ASjdTG(vC277 z_kJT8DFW$*zcbBw1~zhN0(aB>sqN|Q#c-%KVNMWu_F}g;k2(Ryja0J_H1)(BfeXp) zy}Hq5net>&Y$M8puI~x{>MujOc{5!CXrpKi?=vuja4XFfy9f z_0=HK0dEJQ>6Rv4VbW!uBz!z^k3=Wey0A{x;(IJ?wiAbJLqV=y+nmZ9(?pV3hf~38 zAgPt7+;J&NJsrRSf{KF=9w=oZHC-3%lyM~5S@fzAuYWNgCnD<3-w04@UJVTBw5j(e zKkx#tg5A+xv~d`$iTO!Yp-oa;n_Ol4+k!r zURgn3qV1hp)n*Xp`lvitU@Vaicpc#zR@6>fm|YqCpxf{v>~uQA12%qagnnZOSuTD> zTc-`q=*KLM%LmEp@F;OCnlxAjT zSKM5>A#M}&aSLHM+6x?Z3ct)aE141~px3Q|zW^M^gExgdhz1qe-b6E9i{;t-+nqjAmK`VJSO{t~L)!{I7^XCJFJ= zoTb0Nilx*Kx|!R#x&%~w4BZwCtx~!tVpYYnzxyAst}ZmHf_N}m-Dx+Gz=F7tbai&` zKVbaU*h=;lTSVo3j`i!JalhpL-h&=JuI7E4#R@LhaV;PFRu(-vKt*miMh|SLIPeO$ z_n?`w{u)^2kzgvTbu?L=#<<|uZx+uvk94&5P5S?pgV>$Z7vS|`-l&h3cm-4{%` z`x-D;dPUD$Ej$0cK}A+fX$?n1-CLUOYd<86UNTlbRSyWf7_zR8*-{kg;;MLiyEkHm@L5oTCZwdF%zx1 zWUzLFJtJZP$kMz_RGVzkfL5ttN96p=&W>?6Z{hN-8 zFUg>ecYYehm06=S5_LXw&Q-O2rO9!`DZ;lkA^`FBdhGko_w)84HK*IQ88fhyFaYN{ zXYa4)z$L{yCq`P@?zTG24q{IQD>^n0qqolD2V6JoAeaq~=PJqL_>U_Nl+LL(Wn6(? z+E(wVUW@9}t0O(29JljuFpX$^k!%&{{9+ zc1*!+w|lFfjH-KrjtRLO$>p#JLlAg-YTd22e8y5=jp&sn(fuC2*Ub3*mty*n)`3f9 z*ww=mv+XBE;wenr>TQ>pzxH%Ndi$)#mjiwsc#7;QV48lRX1}ZFPYm^TPQT{4cvwH% z9SVju>CGks(L)_)`)?6azU>#LefEo|FPwTEF3g&~mB|TF{#rzL`4hy+zCgffYa&D= zG?n2;^5g8+FlZbLbT$2m;o#dg_wc(bul9aiyJ~b@&u6pTkpPG8F4lhjBw6q_^-HNv zAo1{Z5B>HN*;n=MwI++KhdIr|{Thp*+r_GWjasH3=aTpOawr@#URJPHUW8l^~&tc%rFoSO?+n*mx9ew#EKLOw8+a3Pmslw@E%R5*< zd%I8eUfL3y9-~LvFJwp448RnC8wxKn>CfT0&#!HmYcU@Pi&8Sm!zuK0Ydyfg&C1Lf z{Zd3Ey^Qi6ohlxtW(RA29TXg}$bN5-rX?oU7@Km+|NQ5pn$u4d)o31tABUwBE+dxZ ze~G7<+L^?U|s^ht6w0sh5xc5z0Fo)LuLgc>9NAA&wav(-O))`Fgh6 zv~x0`9%s^0V{THmm(^;ZyQ#Is-jnSH&Gmkj9Ab_={i_;b%g=Lri>5L+4kf83-6F}j zbY{XqS$SXwH!;FXbLm`Tfpe3WQm2gSL3 z)AR5uGZN

    e4-OBSGVW7Hf7+sms{q9s0(KHE4>Kd7tr!Y(L2BQX|n@aLTpz(7KPV zXX`26n=uwAImRUS;8dIajs;&i?zXTUxUiP6*Ierrc=G+_ql_Pzn6$mUyx5G7LBdbp z6nw1S8h^cF%FI=a7H7tqIt$S6cAF@AtGMC4LPYM&nBBRev`3<5)cK^&QJ8`-YhPbM zLwJk%7^dP9q)Za5zft)@-sJnJs_R=SyRPiYg6+YV8-Zr;U10Dw6QZ$~7Iz_)1_EQ; z(My$kM@s;s&$k3_0comUeP47GsgZy~n7snuc^C+nRtz`Ff^H2UT^JD<%r#~7D-Z|YW=qA+NcHoPxJ2H77w%xR+^(7zn1LHvzk(aCr>Ssx zaQ1Mr#j9o`JJ#gLVY}2wXyl4PKo023Yj*Aed2Un_cDQjnZ>9RO(Pp0Qwy9_56`}Y_ zOzg(eb_4rX{aR!}UdlJhb*J46QC%>luuEZ)A^lu+61_|0K%#}{B1;G2&y9_ER$Xk2 zYj>1`&tjeZ1|-%xF~S&f*gww?7O|MJQltj?$0jY zy1Ag8aL$P-pD9|_DkKMvtUH7$7m$n6$6uT<{Va~CA}KkK)pZ^EJ2?c+*s-|zZ>!%N z`E$*&dS|4IT3DWm5EC$0ZxRqYBw46AvS`4ovVt7(cFujZ%j)FqUx!n&XD0d;I7r(v zeO8!19<1iuFYR2~mKu*~Cqmh87vq@Lum&^%9C>{E?3|O}QM3Mbb&mXsKBFPuYZ801GZo> z*E^(4OI24M;oA*prR*2MxR*J&3wsoesWwFW%pDT~&3cT$g% zhTr{|N@UQyjOXr~H!TEr@vvj5rEmy;pl>d<12+;s!>aQuJ{`caF>frUsXKe+j+uMr zFw*|tj{FO~I!rXQDz=jE7Um=|(8G%Po#nduObGoLG@Gz;v|J2U`xR%d19(sn3lp*N zqLIR^L_NXW$Ip4W)^IMSaj;>vtHJqPSvzf-Ru_X$j_R!eZ9|p{mAlZ_T(!~HKp8Od z$4&!JQUTu#kMKNN(`=y^V~W6ooKwf}Ncb90t;;tEW@n=p^?u7xLzbgk*40!8bsxXp zaIq=pDWdQ6;$+d4I=2RUz)EPFe&)}q+&0s^$5)GTAIGpFh(QTq>UK_Hezmsz&sIH^=gQQ>!&S>f?h5MdnU@3Q z=`yBG5fESh;&W~nsm*-vZi=_po?u*-Yt*J$Mye}-~ zrEi-=K^m?TX|G7PyGfB6^616A19Ii|@;4em;J%5W5G+F9tV3E*3KUhZZEJ90x_S11 zT>GHDiCZDd0=|Wl-_TTLAldy_i}P?!tN19Hlco$@Rf$k-kt^WO@scM?aV&cybyS-q z44|t24W8xG(Y74MDyT9h(i8pN01Z<$S|S|M z4O?Kpd=3_(`F!(^g8JzH<&71j1BNhN;}%nUsNu{W31-TZbScUcM*f4(When{J$ajN7GVvyNWfzOD;o@%gKMSW_AjJtYxse9ycZ@;Z04y%^Z) z9dow0YS+Y#ev|z0oda5B`>{E1-^hGPj)%Xm*Q2VV7oBWOIULmUbM<%YpGJG|^`V|I zi1F49I!b**5NK?}l7sDL>S+%P$kx%}TL&3pWg(={vv3LFJ5pIa^$%t>7-jA&>;`2r z3r&?e?7yFl!7EA6FkRBH5V`4L%mVJhoOYD7ZyDTtaohcohdaO1hbZaQ%sT|a2_g!! zX_xYZ{j5X~yQ}<>XYDDUJbcazNqU??h@zlGd0bbk4nHCbo=-p(J$k7k!3_-|?tsFR zf$jPNH_y;#c~1aMS|v^ysgeG=QXJ&_E}vF3CfF)#MZQWijAApN?r*(e#$f zRT%{4aNVeRaI5mP1v3_ZAKU|`GZv?H{bMSnS8lS726E&I>>(yux@ycSr_=$FZ zsg?tpxfk?%ARRFHtL%!+#G3~^c3DBwZDzhqg;e+I`h_NW@K>)|19Od5S)}7Z`WC>5 z`f5-d3nJFqfhG0kJ_^DY>iU3|WEP{L>iguffF-g&wOeS@Jix3mzZ#nT>0iWX0xba% zZp6Vwa4d2l7PYBV*wN-%u3IC^jRXQ?eeUFbx$(NyU;O+oeM#Z(1dI3E0_U}E%`&b@ zXF1H;dv~2GV~A&Ns^Xais?n+dkD;5SB#vA7fFN(Yb#&5{cRy;2#{AkhBa=-0U`?fp zx#0u(-arB$47FySQMky!_hgI~S>m71BEWI-HgZ6Lkm5*k`;x z7vp#NZd4$G-b?PWq5MaRq7i(7KPo!~vTBALW2v=b8qS6Jfz4_G*lvE6P`YQB2!kiW z7%C3P=a+J#D2dvduEh-(x{>^zNDIRY`Fp&&mC$%RVmGE9ExH>I14GXV)sP>rgZh#H~PY_gyF%>{vEE+^!XHj}>&?cUgDz?3~wGAXp7}eJ%f} z*FHnuh(CV4_4#sN6Gv4t!bNH%l8Q9FZncS?{DS!g9&glwtUBjZ-`+N>kQ>BHu{=A$?%Re-jUhgPHs7Mw zw?rz=OGHW~Q-~P>!7L(|8Mc)zJ=PduyU_k84ync;ZhDc93_yGHf>$O`jNSq8obhnI zK1Yl`A~SIKrDNJ1FBgs_x=>@<+~=ELL1=LB*5mH9l!wwu9H0)f@{77 zGmLZZrtkh8*LG!yiP{CPdI!G_&ed-jpJuHv$nO3iOg{ZEmsg{TZ17;QL9t0zI>$Zy~NnEthi@ed!A|6?pNo_u4*>g9-&d zPLnF%SOx1$qtxCw`0u3StDgN}whG+P0QA}d)yut*Z>!C!7>7iPv2+p}gjwKXlG(Xh8SUeM= zsv8%ZwB4UBZ{xs0qBF}wW%Z;>jiCNA0T(q84k}3qXA}ZNk9g|*D+v3{0o~|BEAc7$ zl4e5sH2{eVO#OM>D<#^?NNoXnfc^RQ#Gq4*m&R?)9!2vHWA_2CsZaF&?A>0$BaQU^(P8(OQ=B+3Iucez`_3j3B+!? zCv%uCpxMaDUE~b_124%oW@>Q2=^lp6b?(h3US_%u7qeqG|Np=Mdl_L?r*}%V7Zdh@nT9YjWU(|$D2&Er?sf!U4#S!2Cj=)2sC^v^^1flfJ z*?9s!WRVY{i6lij;NvBMs7CqjDGnuMAI2zp4w#yb#Wrd zFA`(nFP0-NRUkR#dccU6mY=k4h72JMps8mvlXjG0aA0dZ>}vGOjUalvByS|Z33g6i z@+J$yY`}8Wn8d2)Kt^2>utsCc>?+TI1_-8CE=Yj+YG_j3-fTHxzp!Txw}OT_L`C{T z$$I5@R~6ed67_AO`DYya)naXRNIC#fax~4TxgP)UJs!z2)eHiBWMR-eC6Fpz+TH*! z{Oko;#9wUx6bDn;)BM};T-^1mX3bKfPK6dQ-$&gjj@A9sCVh1SbVvA;s71OY#^NwL zRj7S=r7a|(O#mD%zM#bab2Up$_oSPRg)eB16Tl{l7t^hPZWJJg>c@aUkhJ)C-Gb|h zDuXjHeKWK$aQ62CH%#}DB{$M=%@iUISs^2!1k*h@J%DB05}rI2Fs7BK%@KkLEWUuA zN1*V#RUG-BC8 zAbhyGeI^D;+KxB$raLxQtR9aMrV5TD4QAs3@H8fgiRdptlR{h|#hs3(E%NfYrs}Lw zrn%s=gfBb_eASc7FFGouGKRFr^-1FX&Ao4au8i#LQAq-R7)_zt6g6E~@PF0~7gBl3 zfd(xOM7k;2aG*z+_s7X((P#J$3kqj)8+Q^MoYy_4HAC5qycnw_?5|!w_CWpXg@}Y0!ijU;01&%%sI1{ z$H7kyP_=#wB*wT<`8hEHn>xMfCO|_7 zaz=tOjOWnDrY4UYwRe z&c0FukEc45ZECt`eptLFHcGt#08gQEk@ONH6^M)Q{akr$tYH#asEXQ`1X~A~15Nj7 zdaWN(6Q2+@>5h#dc$I^IoQ>^t!}>@$)yEnD5Z(b=6?y{rD@57kDe&$#&V3S%5PY}^ zZykZBbuIBmgHt#zrS%!}2RbUr5;q<|eJ-VCAZ!U&|=$F5XruzYW z;a(Z#H1tFSyQU0fS% zPRV+K4j>FmI@(*ozCU6e%|Ik(A}8qGedpr9Qr&L4%>aBpMA!k%CJNmri6Y{M6O|=} z5zIJ}&4<~M5=mDbvyOF>h#vy~0Zb@7_?VQ}K%Sxpp2x{TwPkr&43lQizbG+DjM1-7 z%gwswx#}ROHRP|koQF|=fb-vjg`*jjzD0j&PQ=n<~6~ z`qE(!eA{MDINRu2t`mg1D3cl1nb;Z4%)cb@Jtt>CyAYhW+41zvc>`F)4y5xqwJ2dQP z;ALE4Z7RN6K{S1esYu23Tv(4fiaq!+vWZ&fe){+q*++7o(eYyy=Sr-@{<@vr#0$0~ z3_$=Ft-W^fah=IoVL8{jUh}bUYx-Bi#o6S3>04;?r(VkbRuQSXw=W;1VgpP1lqs{H zuh4B#noMlu+xur={)HB8E4CIV#)seA)V6LEM7GI}m7hCLL4QSE8+zr{7PV(^iR>53 ze5jY_emr(LQGZ}YGlIi=+#C|oH~+8njn6Y?-1`IkVXVOSq0X}u`QXl)OS#7U7r(T~ z^DD8aB^U&9hC-BV%B0H)zLH6$G|<1#M#r@(D-OeWzA-*6{$zxzQgQJ0@%||B$Ajv} z?YB&D)eA~s$aOR6(~r^D?9;i%56IkkU&V~kZxJpLZiU7$z-Prqh|Gn&UB`a-$&m0w z=cx^8H7-{|6{Km2OpQxeC_IGEcIxCT#r_#{Jb}G+(oVWP<}sk!c{K8e=wpi?A%~Tf zo2eBYHtQ$fKmX00*P^J_Jp0E>A!6OmOF83LOfPR8+4`pIUGhjEmS_E!JZ4p%#AmWb$9>xY;^N;U+bAx+KfkO8f+au zbz^Y7JeKA#Y`s*a#YjAKt4`bto_U^Y<+^=hvJDNE+d9wlOl+`ScdU!zGcS0@airbL z;fY_YUPu|tBba{58&#Uov&N7t1EB?ZNKzPAWCC7&J+sYsD9FO8k zEVL*i;Gpp!ZYyK1vjFt67~0)lJ8`HbA(DLg`om`P-p$<9EYY_bZ#y_ZM$zS?mn@?w<^mok-u&YEo9%?r?QZS(q2tzqZ{_ z8hI`rY&#q(c>C4Vo=9hY!|={^8Os17%`Mndid+X6A#R4FP<^NDA66=to?@(X?3rb? z+0(LuM+7}y+|#Fat=)Kb$Iv$*=9S4{eVGr~*z%|MInh~~&k$K6D%dPX5MYI;-9gTF}U@qpReYMm)=Y_DR>s!dzx%kPd@FrciC8z zibx=iynEI0*HSl6%kda3xiJly5A?~|523xmVRWI8<;JPWZ^B~|KUrpTvn`F(xn;S2+TeZm{ zLtDf=?DkLfpbXmSA zb)z3*Xs3Jhtvt~SVdnoNU8@+`Do3JLt}TKbkQ~oZFXG(AFEULEQy0x8@u2*7?D%t(p`U979 zc5cW29(F3w>b$s^97Bnc$kY&JgxI0{nHt~&RoMlE%n#3DcfiS#R@0t*LG1ftdGkQC zuQX`Z1VvM)w?XFNYGBI1fo&u~VmZjN*Kh@=E&U#xi_eFfmafO)!EC{2-ZUuFK=fKH zOf+K9Ox7XXR8vz2b@6BXsz%(!OA)rI7ofW(9z(zVBqTG<)=i5;j^A> zNPPs)UN!$zZeJo4Rnu$=jn@uYhMcl$;>c19FgSNkEue^*F?Wi+oufJ4Yk{$Uf6f4E!Ojhi9f8kDOiPnk z5s5KLx$98GKoTQ%u-`!-R`>0fi`WsuK+SrOaE~j_HpArygpTiVnjy1+9FJW7*WJYa z&(uvD`4JJ}rXJA5{&$hkDg2G|q*r;e@wyy7Bv?QiNB)mXQEH$Ptc?=|^gZzJ|A2`R zF_>%%jQ(n9Aj*fxg{T)oqx26@@5ATb^08|xU1foC7yZC=i*DmpMa1y>GnoE3Y2c!_ zh|JjFeTd)=t(LCApLugVLFTENf_1VuLefx!7k4^1mDGO(GKK;;)`WY&5R{5A9|gdU zf9>9my^gG7{~I+Ez90kPgJvb|{|zWLvN#Gar9CTnMw_uUjIwM=e27G|+#A_+-X;ff z>LbdM)+gQ&!`8wc4}AV4&JSs|ZfN%gF#r~&A1Rklj4(8^?(4fVF_+QirXDezxIos&(}COr zhw6=jSwrnSkKCvhpyVD_7fsfb>VW&Sx;yE3>iJ8hQypmczk z#hYDSeHb4S{E>sakaIC`O~h!Y^taR4SN_;p`PRUZ#{U3r4*}kbz87>q{48SN{^|5* zH>)_r8Qkvvsj7~!Y(J50+z{9rPLz?#P@xK&5*E$26s*~VwH!=w4HOI5pe!r@hEXqm z=aV1@_o&FU7!CeZD!n+x0xQzRO`2i6ZKesbX3WsN{|%jegvA@Rx_*@SSJZM~ee|slL5ut>rD-6C=yTzN za=@wir;j(X?G)EI=z|&?~>H zdxQes0p^Y~1MT^dM>QlGOSyu5`F!3KVq1(bWC9XzAdn7_z|irhPoA<|KEc1h0Ries z@sxB^xw&+@Hq_cS8IZ+H8pWR3!}7sFKp3l$h+p`$R{@)2sNeZWYU)Z1&+mT^ zK0JIrpL@U7GokE7s)yQJXXD5>S9O4S&puhYQ_5++1e^E4w+3=*qFFv!i~np7_4V@7 zR9sRVUB-bBs66`ya;Sv!TEgPym)hEiY^fpT$P=>__1NbY+FP~hwr5Dw&j`cs38|dW zB`eQNlNaJYk+%bmoV83W-{$tb$jjl#F|=X`RM|k1I*wzS~_Qu zFhSiXlgE9K`@U;2F~yX^_Y7lJ#_w#hil$TV#i^j$sdfn%g@2GgbFjgdUbfjJToMid zal7|^s%tp`bcRXjOG%)zLb;Gt%W?b26s3X#G!g27 zKoVxMO21wdy}K7#}}!d$-NlCmDOfIH;2b}*Yef){wSR3=l=!H5jOv|Iz3 zq9?z>3H42aem(#VZz;Hz-K^$G%H>A_Tj)6)6i%kv)w|mvgcfEB8~`mXn(lTbUjfM8 z1TKN^UD7)Gy0m?W0Ni`k(AsWU<57`h##KO~UHYqkQCmDH>9nv=ElK9b+DP;x_r~Lv zc8dOx=ke8hRB=n$&QwZ1H;bi+b8)AKd8~HTSF+3Q0w8Y1Qp)@G$L<=IgegY@C1b;C z!w&(;`gDAr4S5ErLw;EEyMM1zOU<69+PPB~yKU@g)5g^W=I1G^={e|xuf|UbrKZfL ze|NEG^qhSM(9Q{8It!NsXH=d#uP|>&9Q>A@*CF3g45r&YS3gKTk}hcdGJG&+U^}k= zXC_o>v(!w9e_ea)o72uTnUW#t%eDT6FJER-?Rd-AMni0~z5iL~gQ0Pm{^sBw&r{PQ z5t(5ZSH26MZs@|5?4jKgy7@EBQ;SJGBW9@6ZLZD!BDW+DbwDtyvz%p6KXyC$l;M@_ z@~6VlMvfzM`35MRfZcE2z53*~*>s9z`-|07KivFVL zzX|!*=7`UJaqg18_4Teu#K{D6?O8e{KUV@QKs=o2xNOC#yuEU0LXdlHb;Y9fCPO#; zO-Y^@m0cR@jM0xhtgTmVj+y`E-uc@OD`)$lYY{?(fa`)cKZG_?E>mz<)nxq#7!l+w zTweU;t*j-ha%gk5K%V+M+m4-4ES4SxGo3KZpe6QEu?H?RiU{}HE06vUa4wGvy*<3g zGvm(G%QpDoO1DId#k1iSZ6Ts{PFD-G2z78oso#ugDwkT()4Q*QTG#x6X}|2%$up%k)9-elQdp6YOOhxDOF_u2=44{^7`$g>5XgM&^DDvd7gtW zn$?0Ryv;6Pp@W=CTl^7WGn@{QW>*w@0zNItm8GRn$dDPadXx0mVK07zRBVl zTG-vNA9CHWysUDSR4fRUu~P15*$a@;w4$aXeXKHvvl3qQ@*MCRC%Cq9Y>BITp;4tR z^_{3Pi;ZUj=Vnf4(FQiV!5_Y%K>pFw!hGgvdOB_oUYRa#I0!^--0p1KjQgUWP(D*n zmK4I|X69O0gsi*qP(_atKhaG`{zYwC6@|$Z<=0jc?jvg}kWtK;xzzQCsB&Y0Ux*pL z1tU6*&MT^Y!@f$ld5_+0Tl8J&{N!@CTTxr{cJ%YT<(30WQ;xzmcMkIvaVtjO1Gc_U z)3?}8&%U{o&fwFLwddw~i5yvSLb_|3-t(UxWgFwlf@YLxoolaR#=gFK<^#{3iuPin z?NZ2aj3k>4k!FLL#b5u(jVPe2{`&hk?Z!Iw?7JtZyNedAvf)MS0^a4o`mVEO5AYD%~j48gn*pAAfqK zsz*Yel**GPm@z#^WEgqlJWRMq9st*_F(ju$*<3c8q?n25j`hZ>$aQd*aBH*mNtk+; zMWePhJ*5PLrPl21v}671S-W5CbZm4@L>;GWvO=JL+M5aaTeh(Q)GsYlQm_)8TCY6$ zC>b|Zgyv0TAH7=U+0k#QJldCh_nM1og*|_{Iga;DZL;DW09&Bk1vs*?mb<4+kF-n2 zteotAubW;2VvFic`xgl3nxtT{nJ{JnS*dhKhZ!mN2$uW%U~la$v)(t$tZd`) z8vnGTVa4A+(!vC!U_EGfU{- zz@>aIP5$uu`DwrRF0=(E#QDo&f5~w6&Kwp6=&q$0PXHDga0|GjA_VXw)z0xk%T9=jQK!G`h zPUZ|#6#9IQEw4*HD|N6#Yz)iQI!~9#^v+pSUD?R1z84TJ>gF$#*=uJq`-F+|%c1V# zrSo6KBAV=w*tp11uolokiv)mfSP5!=J5raQk_HQ#X`qBfA9wB)B7UAzi!#7*fXn5E zl8u~CW}lpYA6Ftuq`<~kls%vz&}mvMijrA3M96{3hpPw!F}+pN2ks@Dkw!apS=4b_ z)vA^yS6ZWyO*cy34*ZxJ-cGRqA;LMUXOgAxVtU`FvyO^7;b3#@eo|HdY#M9*xnSM% zZ<%V0_b%K3o_B0aicxK8oi|30i84ydwDJ=uQ&p5VRkkp+yi2gCWE!Xz9WRvpd*@A; zf}liF>!v1A1f6r~XkDXa4mKoDsXtMOWP1rO>JYqLM&_(RbaM!B>7@cKOfs5N($c8S1^&U5G#euSc?~Gc^wi zFMB8Y=TLZgqZw{T_EJsHMtFj&UHvrg{xYg*f_#PD7Lc*S*aSw}UVs+kEuntC?9XAb zk!YZU5paw|gNyfxpoKK0DqxGCr_?hCB(k7d%#=?51Vzmh0!ekeVDUvVMgzHql_`jz zI~};jiUdH|LYy&{wG|2JL&W)lC=jkV!#E<&%|n2V2MMgvi477k;D=ID9yp|yE}x{C zsC!F?VKIdcbU-C{%6E3P#`^@-xDVPzDF7NQ+nZ%vn4v}>9s~Ni)^dS^wKR)_8$4MZ zsZtOs14@04fOY|)aWJ=+4CHZBf_ovxX#hSo_m<~Wj;X^OseqT08W5|>k~5}ta6X0&bx?qXbUIs3Zx4W}KP>9R=w1P4;#p=|=7B0+GQ;PTYY>?P==wXCAA#Dt74f=!@H98OEiMm{KTl0#3_&(m-& zi&66sYzXXds-eo(0^m#GV~GqNPL@|1f{Z=d1}IYM!qr*=V4crBhx5QSdBzqF zRg^c`Qx{l*U7v$N*yLXE#0?&R)ImZ3H$Ec5W0Vq=LmkQ*WSklPR8XSf9pOo%9wTtS z-+MT98(SmQ&a*h1?*5AciPz9f9J@y04Ib*0%@R4S zumwtZ_IE5>%RfZ!ezB;WvA6`9kqxRKF`TE?-I;&upMMt;f+qv9s1BJzM`tj>EKNPr zjPZjLy#yd}e<+*fu^#HMzKb;3dHmZP+KQGFod0-MMxk{GqP}H`0Qf@fTJs^QNEQw~ zjONo+pmdsvMo=V*+1%?Cm%_G)y$#?a(mtGOr!r|4#ZK{I zIhif-2*vx~voQYaTB4!r0Hne<#b{&pJvZg9f&b0$SuEF?MKR5zja&~wfji1noC1(Z zaF<^}P`C)0Lo*NFhSqIax`Oc^uz_*gnu)YV^g#oZwG|5i2lS9gJbWpnSmy z4#H)e7b6O}aYmzXBe!F)9832{d1vrpa;JhE>AJAkU!)z7G6lNOe{o3}EE8dLHt-F~ zINL<5xa_n8mcf31Rp%L`ML}*bX@?rs@=tbvqQcU3eRR;w&68k96yR7+`lROs*|@}u zgW3#dwS`RB5p&B4%0UBK4t z5(5hG=f!?L{5bkMR6eQ6HYeA^Ln zpak?+$r(VkC}8s6vE}zUK|D-q>ySB+w0?63i=tdN3nXyf1g?L0crXVK9zzvV8#=+p z=&$+hu{1M&ZzG~H-hy(l8Q^|W$WbiQ&r$qI-*61;*`0FbUk#SY__f#-F=A}#*XgvC2oP=*KLXD5WAe>Vnp{e;A^o`*wh)-Hq@Q9T*yxN9S z1(#AN>4r8ms(M`xY`v)#;j>X;*Tk5P76zTsA7{9B3NM0>*4<`~V0 zDcOgSUT<){FjehSsLAA;RN$w=7InxiN4icsD&h7#yuk17)doZ5bCd#f{HMFmpbt}M=T;F|SMmq6H!zVmr zO3C|PJ6yYRU50GuCWkv=ox|8voK>eSi8SL?*%a7j{#LUqJLW2fU8C|p>oU29y)qaF z=};3ItJYSH)g;Xd_?G2YK06_*p*oxW9oH{^aJ_k-qbXVZvRP&Wn?v=75az%urWNgJeRz}I`6M%=Y@L`8mHzgeC+V~V*)Xk z^;7ieouF(W*zi0vIABKCVb$`;Bb^8A_i_E1JmkhGFx#B;Y@W%;5$4~fjt6K^Y*kV@t6M)sd4CQ_c39%Zx0OApPbyX=cS z($@Sr8`Cl-`+{?*^XTM9+l>n@kiz^+Wn*kwv(`Y2_jw)*=Wz#$Wu#2Q%Bh?t%~8+U zX|i>!vnTmX>?nP%fwyX81D{ryDE%?`6#SjRa`BmN2<7x9^xp-|?-7mPwhvkF@{X$= z^SU=_u0{mX{o_ep+Aa1IoBi?`mF7Hf5X2oXrg1PZHQsOIA;CfxN6*O|+Z!>@ zsZH&3mn&vIR?#y2=RD(Mx0C&pq$n87wf(&I3;mS2Uc9hxU2PHF#QlcP;7!DQf8fOS zYtqr(fbISc2M+BHGru2t(UV4x|K#q%IXzfnrh!hl*=TZx!=I(LWTXzeln;YJf(~9# zH6wb5gp7yYVnG{bqiLu^n1o*Pyv!*k7nJ`k?x(vN^XlI-tA8h^H3eUj%KrQaah`vJ zw`USpW@CfHIdf^gDsG3Z<<2OmcMw$m&ANo#B}$&%ocJ`c@%^hNmxvmZ%R0ps*G zkVY2mFGtNAQFCVJ3kmvt3OxE!3O#KS); z3I3e8tSXgP8j@Gu8=}jjD-xS(e#UfUQs5sRtX}vpVrmu<{rz@N#<0%PEe-B_73F%} zcK@IN6V|ArPgP96%*Bkww4_GUGWgYVbB(ghJ9Uj#vWPjS`M9mpPol~zOsb&)&SUBz zRMheBE5?tbI;%FfyM&*a?Am2rKmPSx>@bC!Q$~KTwS3_HN_Cw!%(th_31K_EK33@a% z(EE5H5UX4_So*#)`f@4lWs00Qfg;)+GOxhPNNh4^k_+ALccSGK7$39{FemwN+@-UYq$5{W3DL%!_HM{;@^sVQ@Uo&pNOpGBSnNpVmW z#LfBwKwZaZpNc)sF~QmUSv^YzaO{Q2-yJYM^n$FT4aV!imr9mOR&}l~#fee$JP5nH z0Y$h0{?z7#}b z9nCr$p3;lxTEyOr95^U6++5X__cRA0HyxUU4sz>bMy7jbdt;?R@NYtR+9SOX4GtRaIB?|2-A&!SQuoC*J|@+`tR2Sef!FS(?t` za{M>jfAVF}wvi&%PQ~}^75wkfmo9t`u5a&NIiGtXZ?vA#8wfvAK=1<7_JgfmT}9VY z2q~=dX1$rYoiL_AI-SAY@SOoborP(=xkUfn<~7ZcGC)B?elh8Y1M#qEU29weK0sw9 z$<`}3j?BJGT^8d=9ME=M*2W_qW<@=`+aZ{&Dr4;d`f14haUy#q=bWfFL9KiGVLo;? zgViCN69VP|yzaWp+&CbLsCK;es1uBG{ACJAf9nB7m;NIk_cDL?x!BlXi+uEm)UM8F z?YdhA{b{bf5dhU;IT(l@Q)<27-A;%W{tuX8zos!PF7{^l@}u4+fEBCeJ6FKGY(>3X z5v+0K86?|l<5Q@$lBcdvoM;XI2<%tv-4z1e$o&#ikBT#m2vkOM7Y``svlv7rMnU zbc&Wi4-YQvGk%J?ow1*t|NalaB)ke#ZR0T^{548obt+gn#UXd1ktH0wP> zDn)nKWP1JwB$)Ns);l*joM#of3hTHQ@6Q;O^c4qxf`88|C^T|o2w1Biq9aqUvwcd*wN|H82i^;jU_WjKH1NVxd z()|0sqgEr29I8!6co4#F;(*|Eb3rW>xl{f_5Ue*cW_cwJ;`4%4}_8YOD^zCD&vh6xeNy`P&%)%8@M$C|A3 zQyGaFys;VL8t!?WgefY-c0jsuN}}%(e0izOs68*U(dPZg=qY|t~+hmngfLp z{O545Jqq300XfA~`@^ET@PWZ_XmM^L6hT8|g_zv8d0G6KXyjSJY^c1d3r%K}4^Q}+ zmdI$7Tc|~!ISFdn;c?!&4#!^1lD?2ua%2*CB*hQ$dR8$I;)?H9n|NV2a(3fL0h9ZYca3Cv6U0V<*p%-zv z@pW+*<%-Z!SR7aNo!AKEW8q*S_k-2t3eNk9MX`|)s6J297tFK$6>!UATk$o}a0_j% zz=((+e8XCf4VFALcQGB4D4n|D*AN}5^V4_ZOl_rgM9J0t_2mYayL3Ot_^j%WlREc4 zodher&gzOar!PK{Eg2u#I(C^48w17GFEKxqN%O9WdOJ6|R_p4P`e&ZLo=zB3Z&Bpl z8Y(FM)N>~$&yf0i#^c;w^n8K1Z`RQ6jdj)So9OM3gN!N8Zx$b2>=RR48RFES{KL({ z2?A}T4lrKNlT~nA{5RKwi=U<*ty=`SO0hfb^ND=ntB!63l)wVu|h4|voxN+vK1lGc{nj71;=|>;Cq&dNLpPZ`=c`Z;1!i0y* zee`PYO%DNM9KG1G!69U{6ZXsAxL+rwm%AIjZTOQ?nNCcP6&VknE+{i=w73;>1AX;% zaCV%bX&=<=YrmUjR9m~7@cP2-xA$4g`@Y51r925X`|^mgt4h;_^Wlbq8rb375!y5V zLqesEgZ1NxZ>X9-?SI=_b_8~8$+cqgA>GP6gp;qVrfHhKYOH0+O7~rdc|X@aLYeg`*|!3p{L6Lu4T>kWR6l#-|k17<}9Ih6!6;;@)Te-JWz zrHChsEM7a4{XNdw+IWPub+HPd_2*a~ZSBC&cC{eG^#h&Q{u@58$QwgAErYwA5w5VU zn#=Cy9-zQd7>P3u2RQ%%$UJXQ28o4}K0y@_nsXE%z*Qq_2tkKJLNmc!G{^wR^uVlV zMZ8NPvU{?^4JgDqsM-3#eQ9W*-4-}uf1M_swWXw(nCwidkfFg+=qu~f>+({zBSCRR z&K>zX5px==g?YXQQZH6K^+1enkONWH0eiLdwxw`rFnt3#g67iM_E_#miUn8h`pl}D zTS*BrEtG^Wo=vk&Z3jvM`vMEYisD_ZB()F|#VuZVHyBL&c=A#XOT_~5Oi=mojrZc} zMEOfa$z`gDU+($!iCJowla+V~=T?)8w-sr>m&|81qFD~$rVSWULNdxDM8l~M5kG?S zlwsM9eN;VjLcUcz{t>a8gO!~;VmN|lx zXPohUP)b>k(`ZLP-{W^GwjZdp|cM+2;V zs9ZK=^EpB~8Vm;`THp@@IEvfD*L9J=b}tXppFHES$dRm6AhQG%8rF}-uc+CQe=a zgDm_R5G3T*L>^AZKElc2CI%MYkOLK;USgs5*3w&fnG_)a@uw`4_Fq<+Pg>U%(DOty z_42K_t!?X#>RNHr<}sy0*^bp$jp>Er8z-6i4b=5JS$LDiTG^6a-aQ%$Op&*vBrnvL zL|^K$zoBaDeZJ!DLG8t!(B>X9X7O@UUf-rZWQHNaR*8zQY24!c!^O>ItW+BB$xQdn z+tG8+6MS1b7uEB9Nk2VJ?)7lIOw$l4Y-F)UQ8|*0rLulV?$(_lhZ0hj%>8ZGB<^wA zw~p+ww67>tyT|XdE>>67RFmF^HE^5mR)p;0*7AR3bT^uJ++(2%37D^UEtMiVLO&@u z;jh1~ZQs2z_DwN;RzHDpEv4|~rwfw07(*IQMaOXO6E2ps0B)%imqWwY>5|a({@=AR z=Psb&Z(5?RsmT`N>Z^oi|G6mY%}KjNHFrD|z*ifCxI?g4eL3@5yr}DhaJJd_<*2ND zf)&}|)3YfZqe?J{QyP;;oVifwM`yE$OI@zg|l{~OPq zTi7*!@iEDu^2^JKH2(ov>0+N0z6?wDgMYo@BsRWn#kYxyE5Epo;b!02!`9BXBi7bl zKfsH&QSA1`6)}4!hoN0Q)SbV(5YWAm=6@1O#Qia#P4U)BP+knJ7Vz%wN)nAI~&n+)wyS#$8C!jk@w2$X`A`q*9^zX{RIjr9v}o#=qD_a_gCZ zQRS0`kD26e&KYH1U^F-Hjf#IVMrHksqP~dxJpH*FjYyNG7kpneTq#TU#hCkA`}FHO zmx79%rK5c4>>iw6XlJxrhAGEEukI;#qcQo6A(R6Krqbp^xcxc!h) z=Sl2Nhnlmh8O5ikQfFV^`?HK zzI&;YLx_&3j87j&o}^w`*bb&YGIO9vU^W-~e!l-VK9@tYTQP4ZXgJl1R`F&>*27S) zK~wpqyMSHFNSWWz9Zzj!yR@H_`HxnofJhL6=_s6&$v!2@v^kOUlJbcCXUaj?k)3px z@LNUK@uuO4Z$}40V*;HuO6!(pyA>x*a$M3Ye=F0!pFbv`^1fNv((c&3qaVp(ML}0h zkxGB=Py2==lK-lmY9})}re&uPlP|TFf1p2o$hNeqe`>*UwwRa;^RNC7sIvO5$q-6^_2er;Ax{`$7|&GCZnrYzM=yG1!uer1$5v&YXgG|#Y(0}HAV1vAc@ok}eAB>ot(-nyZ*RN4cv(t8J8IQmkI?Wl{ zsr^9$5{!^RWz%ntQz=0$R&hpIh?5&dy>U*~-~jk!5-Fmkm}9w7^isY&@u7VZh#=OG zt6$bPk%teOMfS>Xg%sV|xTQ=SyovJ%-~N~D7sFXPHVTNe@WEaDAK33MFzX=&+hAKv zEaHJR$c(G~pNoo*thvRc4jXvO;e@iv@XdiTF=~}3fpb^ahvb(ChX2SwBU;{Di_N$w z2Mg^nyc#G8C}eN~hiA)?terOPGV5cs`vqIH-LqIe_?7~qK93a&M&Qzxkif^RkZ4NJ zZVoY>K0UB(B?X}b3u(T3P;=w7%=)**2?Xji6JqhmI+0O3V=ZGJa zihJyIE#XO;5i$ylGQkspM$^~&mC;#00{#hrlOfuFkuO-0mqla>1V48p7i6Zv^O<0X z0OUTCs@g9z6$1t;KqS076=l`}jA*>5@0nY-Y^vY=P5@Gb@Qk9#vUKQZe;(M(G6A5S#Zn98 zESB+)0qdNmt6~@Z|X*aau9?cIHp6%iryg_t$7159)$S<)$xX}j>zYxr;I)}Ml z4O$tV0x>i#DO?j072&&kY2!=Hg#lJc8XBYV7<2C9{VS`(aHApXXa^QH}y!TKeY zCq9jf_u9x=0y1KwM&Q%P%Hr@I43vy zKu_I!F|j~g|5)GvJO!<2eRpu6*Tfj_3s*r zp?>ZaLMOxH3@9sQ?FwO0S<3T9ZhgRPIzARO-slf8fm?;V1}$@V@`4bVDbT=)AIg?5 z$U0L`5hJs%3ysg{Mgq8c_`_VBa|8{eW+DwEaBosZVR;-n$zR3~#o0jR4XC1F+slS< zpNn;YJKk9mI=e6s==18>Tk{Q%n;1?R-;6N%0(QwEon_o}@{0t^t26>U?79I5tv)cE;Rb<|Qd#?)xc`4XR8XF#(>r5A zs84cM$Fk9nKJ?CkZFv=z0bxwCySlf6c8x?rQ@wL;;{Ti>^cJQ;M5wL7)vwjF3rDw0 zsh`bX6&KU2;}XvzyD7ccJA7Z+EI@&>(Zue;q&bc|Nl7LK!5<1O!+W`nFq7CJZf{&7 zoP+#M&r|D92Lgz~hpU`I^jKF1@O!_+rrA@ijq4vRooUbL-fVy4D@Dk={h;#8saB#E zF`9>sb?)2nm#d;BH?TNZ2+)!@AxEduHn`;bSwzT-kLLX|4rfz-MRI&y8NA&|xd!^& zFfuzm$=KR&-moUfLtv4SCOpxp!%I+)XpHWZxnt!ypOn)p(r2trl0? z5X72-prlNf+g@~K4j3d4s7ehyjsM;?b3BZnd(*CLuoMMe#`^SXIx2yKu!Q)`rl zylsp;gAv{gMuGwZlx7_N#&_*W+0LQj0`*r|mZ)qKxmRj#aW>6nVr3|IK=fd{2*p9+ z^f`jgF&~iTHKNex%dW#w?BW3TVB_%VQ={j+^CVXu@X4-|(jO?jo0XAsj~_O3?RvL7 z_}IoR+z%uP#@X-Uys$L1xiTQ5@$#C0ab2X|3{XL)Y?E-WzsV0)MyBX7^;x*rp%qC+8(o>5o%ex1Bmo|lL6X%Fr`wW;loRpfGbs(SYNTm3Ib%72>Y zLVvn=fO-g_DTrfEQd8fVQ0SW0C)F_ z6F-$TiNOw5DhokV)8GVP2#UvA4Zfq9CTQ$Wzao#IN=+n-rkX*}{(#rQe!SXwmX_w`KUASTIO(_TzW#Wu^G=+dB;bY2Z%!Fq^@S#r0wI6X3HwB@o$IJ z7N?iqv&dZ0pcN1rPGIRRpEA~IpOMozYm1y!>QsVE#xymNQ@X7mNQ+7S;tlk!53N~c zcU%vd4K5ADM>_^!r4{GsuXC-P{n#n5o1!<38*jRzc`an&1p{j!m-9@`W^^`VlltWZ z;{n%!xS4hJ#OXTY)Q&JXIqbQ$3&uQQLcg+@D>_Rd|AIUwzee+I=C~{XDn%;I-QhNK ze|D;R#zzJm8-qkUq5V`WCnYicOO`|b0c#Cgi~F?IU&zAD*8EJ&BexqGzS(CpsYQ+Y z$E+a2#tcC|NW!Xi3LoKjwWRO^{jkcTw5{<+kQcq7y`Ra*aOQbWv%wA}=Ean?u&u<= z(*J--jPaSvoPx`N!M0cJI+t1H*Ld-tZW7nHen5|h@103FwpFn3RaUzD5TAVmF>hw+ zVCNWNE4Z&d<>7pBqmki&(4N{A#rWNx>#2ml zqsG5?FjM*=aG{doMtm#&WSkFmv%tV&OY-<*;YEKKOPPJLkc+V9VWp#-5`}r)yJ@9% z#_)ncy)*kSmN7ibG03owqgKafvHNd*m6YSYn67{HgM=0yzHYa|57Q?yHvhUCPNbnC zoUKGoCnPM6m1AUF-&GEJgk5&78TtMVXZ~DMp&;Aeb4uug#+iirNi!Ib&iijwdEVTVd@AuIgzt#k_V@0hLH+=JH?P%g-%yzAdaUm-c)<5#3o%$}E@_&Nl5( zk~if4lVqwdNq6N30($1MO9+dxx^dm`oy8xIZ$iT3$7hV%%u$LGkH+3enOBM~FLbSE z|M1~j+2Fbe&H4WYz1M|%PN(;IN1%GurQR2s1BcSId2>9zv}fB^*^D;Zt)A4)G4(8; z2Y=B?tOOK}pWQyHDc3(}R{QBuh}v~L#w#ehFM|}4kL1uHd#=ancAL4g`b>pAcPIS& zS$+DHD7F6sF7e0C+rV!OPh?4JRn75437j zulZDif4gi^&Px8WxMw6&G5!^!=XqqNi#e4)!k>z17Tv#!7oX2^o=bl=@bp~ec$Kq} zx$_C9P>iM>R=tD6-r*u9+vil-UutOd_#uIY_u3Ts9W@eNxo;j&9!F}AE{L6)i7%G))PAd$j-AUKH;kdYe$}zdEcs}V|c~X&x-@u{Q14+w!aS!9@uT=Obt4ZT#XQ=q%!(C zy)MbwBe2mKxKL(x@OlfUww^0I7+lY)+@zrE(E^a?(l{pcqqShOLyW@_zt zg=kW$i95YZaA$JyGBx8_mv)eBFSU%=BOO^c6^roco`KWzYe|_*p&3;v|{1)HP!+}yXRbuda z!e`eRea7V-O85LR0nViIqlZ0`Emm(yjdu)6zy98y?C(&*`F$3sXuPr{+(UKqZTg_F zRrvAlBgR>!xUpZiC8R#g`SaLQYwXQ4%$rRW+vRpH3J3ap2q2;~BCcDhn6a@ub6vAD zFq%RN0wCgO+2AOWo@?f}m8Vv;Ug?qC>CHLaGjX<<_d?gwO})y(ADjMVRzz6piUrXx zU}!GCt?&vh721=y+;ESb+Kw#HX&(P!GW?9EQ15TN!_lh{f>W4Tx@oAl^mi_tmu4!d z9L7B75_biBNSpk-xE5?!_rvm$v&8!g)}_gWv%qhvum{E%z07lrK}P+PmcU5kiz=mg z)sQELiubm@eb2t}Bd*LmEiCNM?PkpUsP#Vh-+-HCsQP|6imS>bA^YI2 z`C1R{Gyj5kjo?7BNh@c|)@1#j?0mzl$!F-BR6z`8s`3}rzV_OeLJNQ02&v?#_*D zhvO00`C}f(6&Tm>H>LK{FNf{obrvillGh)zDAkuI{0g@Uo}3bSm$xF_AI{NST6uMn zQZN~{&z~O}bSB_19Ll47$-9~G*egV{Tj`Cum*Evb8c$6tLbpUKN91}KnpHC%x7jO$GOv+My0HScFC!@VGdBdyPWhnFz z?>&2Eq?mM_98ezW$jcJC43}DprNFr7F za9fW~ZUChikFhemr&X zpOrt!SLq+-f}lz&)_FpxXD`G-A>##1D3BaLLsS#Eyp2}*<~^!2sHA788!$W(OV-8#XP)?(s&3i zZkuR|I$J@IILTgI-1*aUxccg7!ZX-9In#+-Ya#UZDrlO#3RW7CSF3ldt@g+{sfF?k zD(E{epRjLz8*?$g=sZ#ngV|rYm+;49;@P9(=V4hj%L_0QOUqj#izd~Pj%`+zF~pH? zY-?^Jyq8n!-b}0MNvEe^4ELZ)(V=BpEpGrj{#zl`p)MCcpK`J%v@5y2fOfAJ0lx4iYyUrKlwqKR&N*pEu3o{!J7=ex0<2 znjiF4V>9ao@4ykTkDWWJUv(NecE5pUMcOpsz^9e&Aw{VN)57{X!TwE2q>JpwESLoF z=n(MhG*++3c7Shf7*48Lkn)0jq4dJKdr1<y|%}4t!?zZ^81N+ zE8^gnU4tkdg1B<;t(26soO^Kgmsfw_5neaA*#U2RpT&10`O-W!A|b`26gYuAFp=-8 zv8p?Fg!v{3@%+OC!IO)s;Qgew-N*-M0}H z$NXzZjdAUUL>*^pcG=UQ=T|R1Rp>k#Lb33ik~+XNsfm0bIG%ZSTNV2z9nq(yGeoPpXnDHsm8m^qMiiXpc&9f=CfdzpPd-2i- zY2?R>WBk<{Ev-3MNKG_z2XD5DYW@};g|0kKK+g;GpYQ1}Tc&NU^M7h;aS9YRofgp~ zZg8JihsD46ajQdfJh`psny!yxJ)RVBE%5!AY)ZSM)f3Fg^H8_<0q$;1XQZDmWmd^? zbIrk*%7gWf(q>%Idd|~l(LR6DW`Cp6kcY00D#~ziI5|}v!uLLzNi?xJip6&EV?YhiQk2)Yc-uj$O3ZfGuN@3e!GY9X4+F6d9lVC)Zx5f!- zy!TeEL?4|&jxzmZ18Rp4G#lUSCRK!ZP@3r$g!XZYH)K89SJ3MFPG$W8{oy`8+bt8{ z?frHi;q1GSO{;u5pINNFs)g|8HboH z^T+Xx%JjVWo8v^Y&zS70@~BeEOosqTvu8r&cJ}N;!>W@JZM!Y~8QrLo<(!Xkw&-0p ziKEX-eU&GRChBY6Y!^pIA)$OnyHAq7{wewUOCsgK!RZ5C5FjdVW({%qZ!IU@~|u|P;7Ia$~@zd8O9J-9YeGMl*G-)-H@6cBlAHGi8Ub(dqUhsY35$26Yu8$C?hV9FA zf7JZ2T+C0b9d4~n1LHwCt_tXOC)Zqupb@IiK6x99y$Y$|f=pdiWo`W3bpvIX9bIBL zJ97?;kg(NcHwW9>S6rWzv}|Y;t8*n&ilrObaZjMPc;~W*(`~rsNrfCGs;)m=?R=H& zU&8L)*Pj|~{fBt0EVF@VN(mn;n6ggfrFLIyrIa!l!3tpbH+`FU#YJKz9O8F9gy=E_{N^cONa`+`h?(ePZIsmh;b65@RaMtqEjutoy5;?PK5b~~jMP2Dn`RF9Ds|I8MsI351J-P89GHJWl9FnH2B8Ox0K(cIR;2PtA2|fAV-bw+ zi3GRN6N7BCJH&=lUB@Gb-*s^aKo&f{-9wT>b?hV|!c5AA5t`jOR8OHumL<;AI6t`2 zc3l}|72HGAlZ1anzL^0x+T_pHqWG0gt_k!6+Vp@G@)ar!7>QOMH=zjP}$Ni65^u zf+C*2mOIbJK)~`avHmF|a2rm!sVC#5P|T*rBsU1#0m)n{nd;6C9!)Ru{N|_k^8t!%BoQ@G}7c1w<9Uv(#{uD&^PFG0W6|HMMBwL-oRqiVU6^L+nDXMMtmcV_Rho& z;xq}Q5iMr)q^u!cr-Ei4pqbK0@LlYptYO?aYqK{(^lJf6=d(O}sWwm`;kRE4GZ6&t zPiB_I!5@M%nFVPTv~~j|uC$5V%FZ;S$mD1Y9_(gk$mm;#Me!n)l{V<00GaeAw_-C>!32J?1os&0drG1k-F1T7+(g5lxVQxLY)A1T|mX3 zu>)qzq|qlpVY#ttn1#4JZ#-%pX8_T}`{yq;-zI|J%FOm7&cMP=?xCCJO;y3qtQ$^{ zCCZuy0j#iDO~toG5o_?QJzyr<4WlvPM`r|KgU=?~VUWPWikE+(6u74=&V-Q#J&)EA ztW1BP%mlr+VXFIgBGZIj5}N7H03MRh?bCn%J{&7?WbhCUa;l#7YdJ3jlA}FI?^;3R zGJg${FOVDw7(eY7UW{PnA@k z-~Ijl=i<6tJKXR4e%-Iv^Z9sMIeDakp&B1ohGY^qBnklBlBe3h@y(2d%-7u?$vLK7 zip=#@+XyMOlyr9DE{`u@?Y-rRlE*BRiH^&5!|dMZS)%l@T1`0WvoQrE*v%qFS)Oe7 z<(f$WlVDyZW}IgwWV9-oXctAno6O)}z0Y$HgpSZQw&}7XsT0Z7*^2O^%RiYNy;Ud? zvJXGy&_)1^4bIP!=1=`aX`@*%wkzbBvGG91=l52(!Q0W^yw}95IRKJ>GEvjT>fm>2tmbVJgOAFwA-0Sp-c`B2DlXI*Aoj z#BdNAvi2cqhQ5bOw?Fl}`z?CfChEYER=@j@gk^<=)mXb&;Rdzj>JYJSl(6uculjZ_ zZq9@j$d`3UJQW!tss4dQQ#JjEdzYMH=;+B&1q+a-b=G1M+zT`m`a~RoMrGD&Jm&Ym%6>o-ekUO%%Vt7xi zuTIc(cp$b!LQHM4LT8xT<~xf0aDh6A}rV60ojK5vA|b zb8KPntiDa#^}-;a`p%2762f-7>;s{vqVPBh^eWSabTBApR*=-+`rH?+DUorBdgW^xWZ#iWBY#kS8pp;QbnR}wrgb*6|il#Cb!S^XUXDmYW7{=Oxm75@m=4N zd;3yIzHVrr^Wew!5a>ki>R&83^5>nl9)BlKt$7&+#8my>-1fOi|KYAeIrZ1= z4-;Ua`j)&t)EsP#rJ`|R;?A5{YBRi6%%%_3D}~xE^-=%}Ck+j9Wg;)D+U}D=7780w z8b;~b2zt~7o&VX}a(t*ZrsN&3?VMD7R6r;pxZpe6pTYGnavi=0=m>hyk_ zaLH}?VNg)5Cfb{E`hpl86^gVh)5?D4Y*cx9c`v2<&EVagHoSmBJu!;S8UI8lbccp(cnubK$gi*$ z8C31f#4h}t7GtY+2Ea=P0IRe#n=Ypa>#T$>{|DXo0>t>&F`3C0=9@=2Ta8G_@YlC2 z{5c(ePk%o=^8VuV*KwJbPXDlD*#C+u zJJIOl<^83@{R{QP_tW1mtOEw?Ouo*1is4-Y-~2k##cq3mgw)%s?q}=&s%XieZ0C+z zqk45y?4|3d`-CoRyVpYZ!yzIrKpG~IBrf4M4!75sVA0avF&U6Ior=h^oGQs8phDFh zCF(GoF>nJZ}Id8;NswL1qYN_W0P~wsvf+$1ok5C-N;b zas8HM>KbpQU0*i^SAZZN`$|}cL5Cb_{2aNam(X0EB;(&C_GreSFost(9MPX%QQUu% zytjADfrkBWWOGy26J6&JG)L*|w9)HGtmg4niA;kGsVNd1?);mv8*_J(s-b7?b!6fc z1#!?V`2$1YPQ{PR`lFGk8=>T_Q?3D5CQ1>q!el0!VOc!qvTeqSKSrzDNJlVhjAW>V$_2-~E(5vF$>=Unv0!Xfv?4E-;HTg=uSigK0<~K=Yl# z>DNr<#Epg@3yarl7qeSU!Wt-;5K#VYVQyOeG7-a|hRDJ;v(9s;<~tqzMnCS{uyU zKgp*pY2Jnn)!w>w@fYt=WAbSxf5Q?xBTo}wJan)=JkM{RanI*f%i!;cC$jr`{Ynv` zgT*UTPBbR_U(;!|NbA4@>QP5O9iTAE-}%hEC#Z4sCT2jzhg$WaO4pEfU_s*K=Qq?A^zw zGS9S9@!h9w4IQ`hHE4`zT?>kR4U4VUrQz5bT(HsclfEfO7{)))l{T7-M@kfj#(L~( zPOxjnj%8=OM|+Pc>b+jQGY7%if(OR5`=Wr+oB1r8gv^k`^>-3bBOL&zCA)*DET=T@ zgqUmLF`IFh=|qlfQ2PhkK(xx?nCH}g-EFp*Q$*|XiRXrY*|@f*U#UP^apUkz#K0|^ z=HD5oznvJ|aBN-o^5{EJp8t)n*GX4W1AK}StK5IYEDY0*c8iUVCga zmgtC7ywzaDWK*(?8CMO-P&sj@k=>5{hS!u3wT@DptgV$M2{pYEMiB>@>{wR_u-WX# zNXP(V|580w5+_l}a7)tjMXzwi)v(5i?T)C?$1r4kFD-+*Ga}J3##{D(ebwH-_mGU! ziW}O!qP=C@BP05spZOsu9T= z2*~jo#(by7FlsXg00i>r#Zf>}N6U6<0fp3<3_waWMwYc(M;0-^)It^z0e1xp zFU{QdZ!awlBD^}qvDc()`-i9VmQ5N;_Aes6f*wA)?!AoO;&TGrliCgZP%eBJAk z-NFvHy3*J&mJBsb)gOp#Q(CMkJEl*yVR~2|%pkM(>Jdu?|J34-JT>P&=&w@Dc<&h{ zO3*ZK@5z3Qsg-61PIcSO%YPo9s1Uo9HPiq{D zdod++`d7AIl-my2fT(xzA92;2^?Z&zycrfU9=kPt#s@#)d@26kPvxVj!#}EpeHV7` zyW+R?N$^mzgpv3g%y?SX#j^kZHv+i|tI4meZx*+GmdJFeU)=s|kBZ{gkC_*=SYs1U z7su~E`LH*&ap|F^e;_;O;$Ha^RUP=^stlX9 zRoICs8no8yb67m@<6ZaYGy#+TFJb22wyHHB>%4)Z>hey>narM3@TF?u7lUUooi?pP zSM@il`me$}(DyT>W!bXWOO-%XKlyU2ko%|o>!+&6i!LO)`h#75?{}>&2OU*%Rd;QL zb5GkW-W$Deug2de#}051_iRdTuX~eyg8Rt+G=4{fj3=~s&2?{4nT2{=nKS2`LdEq; zBQUnrI2f9qVX!yjz52A;mJ_N7{78^$Ny3GL>o)PnQ#Ax3kxLR7zv0v|&bVLgN)Z^? zHQm)V;-3tIO?F>SUXGF}@%;4jpZr48@0ohR{af}<&9^3pxZ(LHr2eT47jH-x`$RvK zQBM@+TIXTK|3S|ayUv}6hkga=S$}+b=7u<3NkPe4!+{?&fA!L-A@fS!f%mhsEr^-M z{W(#8b;ccZIH8dnt3))A!?Vlw#hVnc2l%E;m^5TSH`Rt}SuaQ(djS z)DGnx9H}rlT=DJV{FWCZ*J$G*Pr|FCHdn9U)+}sC&~m@+8hCBU6JM}e3tb7(*3B=j zJ(-(2H?n?1FJ-A(?X$Ve18aKckBY7Zm(kpgM`kHiN7nbM_X@$x{HEFc(|7Y?3*3Iz z6m9;e%qP_S2VKs0iTnoLGIHUlJU&{qQ1@KyNxPxu-!wTy6LlTpVT={v=Yw;^lnpeb=x4qo!xJ@TW%{gZkJAM1+ZKBTp-oBnG0aphT`)~CNC|3L$X zgnw_CO!?bBT@){PR+1lpD`%HkQ>TipU#N{46M^mp&ts&1OAkHyrL^$G^mOJ-{$_Y{ zOhNBo8x!@TuZwGTyR09yIx4iLW?suDcl{V5Z3^G~QCj^^T;!#_qb71`MVo4OaAPcN zW1UV!>TSw==NhzR@^iMj)%r@Le8teO1pY^|C?Hw;;s%A|hpL#oV-@K0(~x_yGooNXug{88o{v$_e^VL1PxxcD$mdxQAia}4{=sO!J)Mz>Ry#smC72Gv$<2T6 zw|&h|Tk##xj+#2bl{}U9fUd2X;dpn%Wu!L&^~H2t{Z`LNmi2zhuR`FH*>+>|@uO=W zcz@u(+G*GW0#WTDY2K`neDlwispE6E*NuPmQ^%Cs9tQb&Z#i}CK(SUSNwcB4HqUM{ zE7Y9c@oDNGZY6LTe$q2>Xsxg|?H5nJ7MI`g&R6SwkwNg6$LR%4FE0g82aXt-Np6#@ z{|^G6iTm+?w-$_>BPmKjb*x334kIUfb6@FOsR&V+5v`L?b$H?_`>j|lS^W)4%vN#IMV>-l z$}Z+A-nC7{C8vleYnfkI)xgcM%J=*9Qyg_AyK|JO_TF%ai35`=Z*0 z|60FHTw1u)_CMT}0Nemevc7mRsR;ijlQ0)S-hPEHNPKIQWiTo{LQn!doN~wjsHEmu z=Tq)!?vG@*a*;})ZQP7I%Zr+J(XXHG(r!)<=S@@YnbF+hJem)eA$AR+nvMC`9yjM< z8n7|q+flOvXFO~(^mK7B?3BGy=}0tpOv4q(e2v|MGV)+(P6N;cpRlYDYc>_Pj=AHn z@|Y-RC)L+vN!Q($wT%@CjnX%bS*=VA)lJSieGj7|WRV~QCVLjph(m>6Vtp|a!0Ey6 zyGr=PxLU`xjyMZibJDGhK%$ZscQ?w6z+L4a5b|Am8wUDld}#?_F$rWDvruX@=R;?O zP-Ai@@4QNinWnRNomi8eF?`Qg@=*!G=-qDyAx>g|&{U$j!b60j#yZBhcCr%45Xfn4 z0=4*kuh73LR>&ZHVnI@!UFKFb>OW%ph@Bt^3Rl5w_X>vOV)G))f0nEriR(oW&nhXZ zd~HfUSoD$^N|+`}LTh9&FqeEA(fkxgyx|&hQMq4MVlM z`)gcby`x!)Y}c*0{=?mRIAs@HV#Ab+zL{UrGZz$)aYS>izjw6b>Y;H##xa!C%mL#% zR@QP0?zU8jO^=M8#{Rl#7hODRSSEthbdd@(eG;bcmidfvvLjwF*#sHpOJqln7Lubm zvO;A^dz5+uxm_j1V)+SOwZ%2KVKPI=mMNci5$&eJjAHw4*zt81lijp$0ZsB&!dR2W zDYp+SiSCHb($F^$kf^Rr3q8&Zk38$64?1hMXcP)J{Zvg`DSMq8KWRe9f(eRcHUuWh zX0ZckB+OaSd7jMXsPkpbt+ZZ1qbnRkC38*c6cSxdBnYA6kfjLc1hToZ-R@y&R}u~q zNVR=_ucvYGyRS?{;p$d0aO(87xEJczH-|Q1r2^Yg$x1CgRG8zRp=<56xPodv9++Ib zB8UHehYlRpSmx_Bqf5wAC@zg219CDUd_`ys{7*Rw z6L`CRrDSImi~(hbZ3OR=W`jf(Lo^~xLq=~ROAoGF38e`Xx zTVg5OUvWv2`(h2j#jom)1SeCgUBbAQf_P|T^Eey^GlT)^_>7rhQe_~Dy zSES>Nh1kl{X|q0Yu5cGEt0pV}p;p045CO#xDMD0n!T!IGOo2 zdRx&m|5Gm*g-{7z7Yzg{sbJ%>@A|+c$!W{G(ajV92y@zr(1p~XxwzZ}fp5|vjm|-> zW@b}Ztg9#TDX0KSyFVXUjPzhB*D-2Xb!xkbp6jb*w|Z&dQ*wDu0y2nYBOwljb zMS`!9#8c|v$#R6z%%oOER(-o8B;^xg%!d;YQJm#Yjs#YV*`?Lc^M(X%%i4|SNEx?# z$v06cP3B-EBrbt~-OEYQqioK3{{F_cFi!$c7fiqox9^`mm=*4Vo>WAyW%Tt`TF@nI zAu}KymUfMWwO!)sS%}$N{lD*=^yEoAULL#iSiUC$zX6Z>-wH_-R?8eUdwMNsZ#FPnKqN(@J^Y#K7V z1avis5Gs6_2Ql_}#1}6YpW}rOHj36z&od@~3f6LQPNO zI-S2;5_Hs{NtJrla@3rvfvt(d_vmt@mIla&n-r8F#<=^J75ek8>w%MZNRH5DhYo`J zY)*cubi8d(b`j9Ex{VCMi;PxMDvPW-Ruw}1ps`4l>!9E#Sl_!kMhgw(y1Ed_y+X@o zziPA&JG}U7vFbN(z@EjIK(e%_*|!`zruU1HZAR~E%ho_5yO?S6#ugbunO$6=t!2!9 zW;azV;fo2RPR2ICB8ozCpTEltfdY?dMB%o%K*}}rx2EA|+4B%E&C&&| zGrs2QY$s$HFFd*u+IK=rmqF8XAdD7+0Vw^22}C%eW*IzQXy}@T5$ByurHa{|WK`9e z&T8$$#4wCJhx&5~2)RkpufVljg~Iv?x~~7y=v}0R@N#@D8Vynlwp#S1%AqdHJGY=< z+xOtQNuybY^GE4ppcz6X;Gou8NRxo)ojjZ?78hYB7u$>I(1LS!<8gFM7Ii1;Pa7Q~ zO*v~Qhpjzze*$_Vt|A47WV?->J>gDbvpzs~iu_r@zJLi)Y@YF*35_Xk_0<5ulUw zu4gB*s$-o$m5J?7YFsT%ZRQ(Z3(e)wfKliEFN>984Z7+_m#gC7-rA1k%$1~SYWu1Q^eSjSCqtMdI=EN~mi{@B= z>y-HH^;38Ly=PgRu@ORVga z7*^=uV*EcBe@Y7llb`kXa^am(iWW=Q<{LdHUCTPhC)jv&mxfF{*XQO7EZ_WekWBFX zC=58Q8@j2TXC_!Aa`3Z<0{V9M4B_pv!|fqvhw0*sWk%p^Th?>3o?N#ctc5gMf}~CX zX zQzmr^nh9`1S;r_d3qMPg-I4rTFczk^f}D3q`jP@^qIvH;OjP&nGW}Q;bl9+Zr^l8- zWH?m*RqV5##cG9eudTv|%KAw}hO9V)b)9BdX;t$0%oxs7cQUG}g| zd_#6W9Wx-2lLSJXbMPDq)mIa_dOF2}zb3feW59H2XGr#yb94A}gsYv%fc(IN;>(WF8DYVnY)Vej^_1rK43o)y)S-aiOsXOW}9wVwDjIjCj8woR-L|VRlDdtFdtl; zdSurPE79YKwZ{>&CoWL8+-=?epw{N$*)jPFSw;n3J?~;@XdXs<@98R@g7U*vYcgzi6Gz!4@()~_L&okDr{Ieb zGO`z^!lZw*-Xg|ulOS2RWKcqCypORNWCJ<^kkPxp<$z4*UWf5G;47j)5hqOJ#0ncd zDjcR=t87~C5g=DFw|<76F~%NMf#();Azg53SS`)i>t5#%LOIW!c~>J_)BH+Ej|Flf zU)ShqioDZcT(4NF8(#;8=MF+8Xg;JG%}Znis}*4P2QeUuF{xb@E4=K_qDm|eQ+(BG zK8Y@L9Z8qD)!cQ4etpWpyZ!oejbF%S(=Q>5haV%Lth;(g4w}x1?iRGFJ1*UNaat~E zA?NPt_m*|d9_p_Y7_-HBqZL)umVuV{N#EmUO;S(iFSNgs6aUq(V130zFX)V>;TGvP zFG_8un8*EXx3Nj4{vRsC`&)%2Yawr{`8o(GD9*c; zA)2weEXZiUnV3I#sGNVYw%}&$=3u$oKNUZE_9`&8(oC#oXpE|us0|yBf4h9{()u*x z>L0r7t(9pCn=SHiVS>P5XFf;JypV7vRuB+0m-x#)SPDv<_Q;xXpu;SK#Y88aN!$Dk z3^SU7)nBK`3inz$ImKL$Q>jA{{`xrAP<(rQR4MNWBfX9Cd zF3!LT`#Ju}L0|bgbCIL;a06>E;w!gqc%A_knqZToOJ)z=f?kqi`{XQOE*+S&r8Bx& zG-YkdH(~q#hTz&fbK7O>g?Q^Z#gf8yf zEHPYjJu!4|AGThLW#+0m+l(&Fh;ZH+juK>q*K#%|H;?A4t-K$UFeJksx7=^07&`J$ z7{&&`b4P0VvM4qdLYoIMrTN;u2zpvy(lRS8s8TN$ic;e1Y3USq_S9NnfI;71mr(AR zv5M}PC4Xvn>_wWHsB4d=4~(yt`(G`(`9O8)VwqP>itee14X*t)1x9l_EL~h{YgxX^ zdSA14JT1I!A1nB`D{tw^i+jJ~UR~NeJHP!oWAO%Q_RclprKgeAZ*put6*f(O|45YO z)gMAmC$eVvBTbomSjJp8#~;cn6GMYV_3i+Vg<%CJwAFVVG*9i_h?_N$)20c)I2U3z zS+hNSfAUt<9igxe45i#UUE@b-5SY_@7hd)&#v>CQqkiJve;TB#*`sdn6D6~}#S%gy z^5BpwL~4g;yKHQ?3{gCT5fs|lhd@kfTb%HcnNQ7vC81<3ORW8WhTEHG`qurqny0#h zH@L#fN+mesNf-5C+!Xw#5W_5E=g$t!94Q)EL*xc>TX9U{s=iDccvMuD`?8V*XXCf5|~b+5-va*cUbE0C|eV};~sv358z_K-Oh zX450avZ7EC5Ovrvu?sTmv!KA21I}|J(NNU9v$tMbgu9kaJE25BDip;?pa|*g)h>A$ zzn)N1%n|UfI&LLO?B*jzPUEEUr~T;yIH+C}`Y& ze?->-&K#d)3!#TCgFO?I`B21?yTeQj=WPt$s^%?bT-oPH5GZB@boqRix5)3NgHBPK z9!@MWv+}^eG{q3(PFn)fKk@u9u6x_wzM~licbOAI%b+5`dM~;qb|byw9+25W@$M0# z!r6gvXW8gATMdmd+(>r&Nuq?LTYY%&Q7a$pw}U}AcF;Du7PxCt4?&ZvSlC&iXn^Bg zeCryTZ|IT8C#mlc+^T25bDe(o@pWvbiK9v41PLYtpC(N(!z^6k35(4V*+3K(t^J@R za4-g7=TvX#8xLkBw@;Hb#5<;)-IJ5{_IeH2OH1NP3jPWEo&KRX`MPkFLZF^XC%hJ~ zBa-7v4kWPsS*V4uxZW-PG^T?Kh7q#L*>A73T58avI_2>FBG&%QDh?7}yM|zUT&8`u zb=(S$9?>FE)*HwrLtzg9I*)ER?K}+tHCvSk)_Hmw5q*Qq3Gc+7CWAB+$a-GR@wD9S zDe`(_AysvdzG==UI7;>kBXknTC@lc2J!6a&3MhG#8M!lK3<%^t9p~Rx#lA%zD)ZhF z3U10M%xdXl@o&b?Lp3AEbh5Cz6L^kzV7Nh}a;Ri;2yNHYYUy}B0zfE8&@2kF*2l<< zUnm(Df##5=O(xfFJHCfTo^6k{^8uAh{;)9sZ(=BF8}-1>pfUK-QvXtJHJo+1XeXS( z+>w|K@-nciB^}>iEjqTBxjQ$v0m23bzz?cIoMilN(VM=(E~}4N^o?m>n09;8oZ#N2 zrwa(Mmy_GQ6sQ(Uwg&#_x!_jSz4Ao4PlW(i0mBoNesXrhO0{hg0^>8mbL(5H5oEn* z+AUAz5qA0pLRK6y_tmn>JuB5yX%5wSp*M^D>Qx5eHL9PZQIvTB092hS#)wOE2J5k2qtx!@ZFf$f}vpLWd!zee0IQRvcfiFGAQ zxZv7+z()qjea77+Ot4Ue&LpdO9Fzh&2{SF@eQe*=E{n1qQ$)#Di$v$o-w9mM?uca# zJx-gT%X>$C4<-^uGvm*5-&{aJbGA5UVeS>(Cj1TsP=qwJOt6ubdP+#8;soE>tc!Q4VeRnvBHe(`wmfUXPPIllxbQLWY69ackuH)hU0r{=Gwi&8-Osk zh>9DAIWL=2lJsB+Q^Ror)%&rO97pxgT%n&K5qinw?>MWald5a&wU3ClEQ8QKjlvk& zXfzH)fP9*2G3;@2g-4Em&6Ft7QpH{=biwnOeGfR|!`}^JP>IYsZGn9I>)`8YD}2b| zMHcoxtti&OjJE%O7=NWPE@>-Vw-(^_#)B}uV#&!_#w_nx>A=wec$(`$HUMr!MV2F- z)Iv~GEq}f{Jt1(AXZFuJpSiQdSS(V6*c zz3`;R%WO9dU!zwEit>?K!D#NFy)O57?}qvx0FmaPctUZ*7K>^P_b_w-TX{E~{V2&{ zF2t$up5X4G^n{;W>zz`bg%kt6ktj9c1fDr|r-R$r{azVQ2<@HfWQMt1^8(jmfDc0x@boBpDJ5F2nF^`Qf( z2jw@Jg$1`fXiFa!$xJpGl>6E9z=*6nnoEi3GBt%KJF4vBL)Nr$cN>kI;0=jGP59^k zav@PTUL=4QG^P_A?Bh(A>eyDZMD|ZtSS-I~Kl;9J*hVJB^ zhdag(yLE`%(+cvl-5#D9i4DAdx4*SbE+O~KhMr2?9evU?vAfrtvHPl8@vopmaE>EHe0*KMV4DH;4R%s#JJl)6j&k&)PTGHEE2t0!FUc>H(IPO=A98heCCWR1kLKyQ7m`iWri^y zw*Y)E%x8r+%YFuN;o8dSQV3}X7`s2vps(~h9XiraBA zfivCU&+y7yT6i&ho=aptT?;nMtbL2@SOlfCXY zlkBKC)ypT-1ZP|gS(zFbhU=KghOkYA3AvmfxYS}*s;{+px=c!(03fw&9S_66LK#54 z1;s^CV%mFcu^?3G=_6;kIg!nWbgdn)k<}-wPPhNe`t}_5epT_5QAyD29`reY_!@16R^6Ky*64TqMMSGqj_uO5FyKC?{h`Oi!-ZCgkjsCC4i8~lP%pXO(p zYz+A+aZC~}I{%i3Mh-sjl`)rHtB$yKx+u{iG|MjGN z7HAs@{+8Tj?3n2BjR5NK>ygpr&Eiy8u|*&kbp_>$$n8h%;qFZ~6cf4H1yetPGF+`z zKP|$E+lhi^6lM=P4+j$@=xVX+?j)}GQ)M|Wr14|wAf15XoSk;s1tit(-}PknDg#>t z&?}2&PkpGe%KNIm>AB{2HO#|?Ckx}*e;;m(T2`O1T}$vz{1*G6c-kvzYVQ`_y?cHK z&9PrIwbH*g(!Q|PtVdo9Cg|`jSj$D9&5_u|hVW?Xl(<`DWuwq0+Y++Z@+E1j*oCOp z6R7xOAGi^ENAsc_E=2P`Oz3{~&OmZ7(mzyPevte3%)Z+4w2L)-z%(T~^=;vLD%o0k z-TFY^eVnC{>K=zD85^RL9uC}z^1V2rRTbBtR_A)O?Pt{PhqjWRUp@J3WMtt8=kk690@St8q?jz29dGVbU%y{i|vPpqSLXF{>AI=#Bg3ic~} zxz&2Z`5{%u;nv6=?XSnmj*_&jZV~W5tA_u&S0|+eSAUk@M{)1{!R<7EDjg%5>$dec zoONMbSaDD`+GJtN!x`yWW^;+ZATPJt&AGYzG*PW$;~qF8bZoGs+uo8Yrf)b+>V9aq z^a3>JLDY%6PYkk6{Yp;Aa!EuIq~X`$Zo?}& zc9!Lb&=7wJUeo5Bgif+jm{aJ zIkRC78lSAUPKn*rK@$w#%Du-|_k4Fky=9$p+AFukw^yXH;KQsmA+7`$NRFWJ+u5{53y%eTaQYkq>hwb#b_j;U~f^|ip$a_7` zv_Ssfk(0!8ULA{ScYbW#dG+S~str42oACV8cFb}UgcHkgX7NAhYLRNCg<_Re3eQGy z=E>W8VKe-Fbz#N7>c{F#X8S!)oO#4p6;Um|+Aj?xd4?e|7f&zy^L-SAwQ`C_rVd}3 z_1rt#d*dw*nLf3@{dNjo4(`xa-|2QYBcj9A+VRJ7{6=L|`MTxj37q!$5Mu2` zYW;~Vf1DStB*u5tZu^k$>)Uef%2KD2+DYWsu_CXTYDCY;h>cZ~v`AXDptSlufYN@M91f#zu3wX>qh)0oE(b+ylG_^bV@S|6Ew`5&|)T3<5g z$%8Mk5|i}>$a_yQ%Y!2;s!wsX$Cmy%j@5Aytk3TLDG!lYK zkKL!feJdLS`PCU99hsE|ACh%1k}p?sazE-mNs00%JuI7Z4*zGictB15-RCKPeMKJQ!CADC}8cv$K%mY8EW&6;aHwR}%4awd&;92;Kz zxw`Qb=SWVv&O&2Al(qM0U1iX*d!#D&xz3JxevC^>!WR2;+I#aEUuHKaPe}UVZ7(HQ zTjfm;ZOfEGYv?s2AKW+09g)c0kbI67o5l#W-9yg39N4h)4J0+s*VK%jCaT2fWE**1 zH!!|XKz>6K>@nG~)Twx1&eYzb%JS-;X;G&5_Q_XZvFJ>@-q@G_xM`R#F~2iZ8hJO3 z_51XX>x(8|t~|$lI(p>fRt_lBsOT2@E!Khbitr8;3CcQy93@tHNNubvg4$; zRsd2715^u?m&Lnx7zbPt{eIVF&tA3@MXQ#Hk;T;w=iS)CYjqef`Sfe1aRk)q=^UfKrOLiKXcdvMyg$lnIU9Gp+-sXag-ug;DI&jG| zuI+kPULJf~HoN`bf~au7GJ-XjvANRojk9+K^{1tM^~Rw)JY98@z;93Uo-~yVO-F`H z?Fw!C#g;im`xb*)O!nILkiA_A-=VNw8{_^%7~{3yBE+ICtl~xV69_(>198y}=9)P{ zx~KpJM(6Q!&bJ%sN04r4n11)I(Oq(0*8<HJx{)UTHxx3$A#Yir0aI&NZ**S zGI8k?EIV^i%$U_%mg{}|)&brw;_E&;TLg=vW^g31v2QHudSA2k##L269k()X*lAz0 zfVD^P8|~^BVtPVW%KU;$56EndfHC`6e}4ZhZ43$;bwTeR`J`D;xngpPjolvbG{5@c zAk=~hw~dRDkn%G;c#B#~c<4?`$=)+_d*t->d9{!P?Cqb^CC3Oy1J;s<9b1`2XT}tN zPGg=p$7DAD2O%=ye@y%CSB<%qpJ>}X_fbM3U|hGsjqXwz8~i;aV%V$tdj9S=HY4Rr z&9p;&o%gHL&gWc%?JYdh&dYwIk$;qml)WLtVW1N7G8fuhj1|&lS0GU|SA^*^WHOFl z?u9>O#b!E&$QrU@(=LEMpO&IhXc+cLHqZqEwW2)Zf@P*-uGzwhYKV0%!)Y@Tl&za1 z=g7IAT_ji)v{@IGjEG;Z@Mt)ivnd+aSdA`wbkNro-pt=ULn9B`nl(WWQQxQTj5POv*_cogA1I)3IYq7eSQgL8k zwvFZ$+?`Ze0!K3PAL=cJMoEHkL~PbAW%(?RlW~F+bE!G(FO`PUy3b?Tvj>QN<7}oN zyW>;KG%)%2quSjH_33%;)t2JM8fwnla-d?U(A*W`gzDlZ0A^S34>dHl*IX>k3|Box zB8%(TC~AhCx|6ApvxxrZM8J~oP@Lzaw!Zwvh)JdYAMPL@Q|E8o5 zb|?dX55~FCO?|Uj+%o145VX>_LSY2nW@CnPi>In=a6Jgb0n*sA=`VxDL+nWg`{a>z z0Y=FPbnTy+R@vhUh=7l)#I*6t{sL%1e)iDpNuTPkHPm2*QYEM=)0=}Sgfl)?52m&Rj^@a!6}tu&+mgqUfj z;3tPz-oAcx1#Q{fS^m}LDQC69ntrse{g}<^lTjqIP1uSfPslWin4A_Dw+by1`J4an zFP7~i!E5cl*~P8*F~d|ryP{5Yue*&md*v^c5*Br7b&ButV>H=N-p0Kh)weQPYi>>+ zra5<$NgQOGO9Itad*bHSoiWWktQKz@9piDHt6vh)>uwa&Gh%~~jX^>8zvv(*-7cv2 zmx$8-J;tMQ-ei@46t8C;K<0 z9HDI6S=OxYz(Fprl>S^FC}nnA2Dg6z2J;rcZ&uOOs$w(JA`+8oATtaIBeLwWv$NMiErl8Fm4*VBP>Wq=H0@1TdSMt< z##|Yq>|-aA5BqoP@06J+VymUnw`!ZlNyDus2z;{$ja~h@&q-)eFLeAVE6z$JA+`>r zyjqMfY4c>F96YUJ)cni!7YCQ-vM>YbzoaA2E%esRqEMBM*)4z z4fr5S@#ec_?4T`V0cLtK%swTKR;)mz{*t~eAn=T=kSnKT?G^1~Ag9Aj^S1z;eP|@6 zH08`{>DHD(g2}d=k1{l(RC2F$LUR+goSxtTBiQz{aQYlLVm9;F(Qg0ej@9^4$zHgc`Tr#MY32Fdo=swV@9;ak{)aT z-h@Bjg=4e*88B^MX~^X^lO+)+_|xp4Mwx_5(6#U!(|3vFv-P3~dv72Pl8$B3&`PK^ zGmuN^IZ5{>FVqjn4R0;{SA-Lb>o`=F@V%#rNqiFd283P7LDoBkGkWK;FsDVg#2_mJSFi=vunIO(d zgNUP~r9@gfM@UFZNh2lQ@qeH9D<5{S?LPM0_x-!B^Sp6WohTzL-QO6LztDn^03~2G z;+Z(6QE=rKsQk1OvOc zo9+wfz4m|UY5W`#f6=E3jv|#un@Z$wTQi|J3O~x8P*v5Mt5Q`!hxAuf;j}m?f%qO* zQ+N!rltF3@KM)<@uCI2tn;W2r+KYgdNo6LSrUIXilcv`VX)|%&IW9~PJqlB8uTDTl zE($5{1=2J6?2W?7x|gJKqVqw%0&*!o7s@TQ7yW6l5#e@E1N+RG4A>B>2M^ z{}_1*ij)R4*Hs)?e^9)bDV;l{tnhQd832#TZ}f1ddXNZft~K(-d*ViOJS&beNu%}1 zPV%2N`ffhhvcwzQcPInd(0iRE)zoJ>f+|n->6Z?C)|DuQJ5CDKH1gORjOG_Zxdk7F z^#ze={kxR7L{rmHb;%l0<-C#~B8m}?rU`azJsQlFB3>g(BvNSPhfI4OKn%)zP6|yJ zki1_IFS_Z0qZSSse;=m2&|>ibP>+TMV&|iM`+3D@o$k>X`5Ub{4uIXvJ9YW?cAExo zL1=z9^BNmJk&cY507Hzt(ek{zz9|zpJESb&F&5W~9~1i+){}=TJfa^W%cRo~rxwuM zaMvK!T#UUj5sEeh@3V&8lsj3wq1>S5%HRp{uE19ykUeqNN0A@K140HkX+37V3n9>g z)f6N%o2uxR$IQ6_aUDFNQ_0c+ma7oOov#%WIZy3KeYT28w}Md?T6lAYYLFs@E8KCIn=jTK{Kcd2ky^&+8X z_?l3D9#d%@D-jiNx{ z{nIynj1fnU$=lzkatHtA_FQjNOP;=HBn`U1czc=)?k&B?@GVI|JNZk60@;|+rJvIG_fc6s|P zMmh~S-*{vD(bUkhJwImor5j4u0g2y zjZH&I_S#%Qdaq8dgy_2Bf6&%{o?3N$?zwz87SlkgN@g&9V$6>4zja`MbZgB#cvLWCtl8vTJp&8q6_ z*8q{HPN&YWz+XY4ekBT0g}brx=}kq zNPpo+pQP*xY$+9JA6o$Uo4&aP7C5f0L&j9E9yRlrw}L2Dp6tp zTOLl9YB2hthF!syS0FM>M#`4@kmY7z<&=!5Kz*Z-IC!&wOBlzf_kuW{Qonu~L@u~v zpDE0XrAA3hQcdUH0mtr->**d5y$V{0S+M4~c;IX><@@-xZ?peF>^~R@*|pcdn0sB& zY7HZ5pg$0Kq2xQX!OkaZdHW-6Zg?WEYHLbDJEfORsnArn+w};21FlHxmxAYU;O_75 zyQ4o2H{`d~Y)REGzbi?cv78G}+}Q0M6AmQLHOJI7MBq`%)uxoB3iT7OEI)PXqu<3v zb2ukM-Q#q7);Av{45wl6=Vq~9QKZxYOYZVUa0jW~T4vA$S+}V{ji6sFu}WrALs}Vz$_SnjO(^QWk*gd7iGIXA3>HTuJ2HVT`>gPy%RyM; zk;$^j9W!Z8aQjBiPJaZ(C2=mW)I{+eeE5TKT@MTD#-$9Fsm7RhrE5Pf)QFyHaYbIUGv+C%`ZQM%+G(iT z^V%l7Ti+aSdNcoVOK_W~)@SuA`&xYXUIE$uo5!si0KSCb+~nBD*6rNQbr{U_-rRC7 zBs{qFvBQreGMM_*h^eH^CEE|@NcI+~!s{n;I0%^4Jn4$##NKTG4Z3W|r(^h%`H z9u>wCwMeuK@=Z0FF}^Q~N}5(68xA)sk6T31I?hr35^Ydk6zHs~B(J^IWA|HWGhsXR z4A#L>l~=-cuDrm;J8sS*aqyGvaosW`jZl-nVu{+;UD|Ba?_6IHdcoDFrOeY?lD0p; z-F?i~STxf_6?kKJ`(uRd9?km_yC0)f8e^ex$OucKzMduK4G9~w@ZQ}?OJR3Jr;kXq z<|1nbk8TFYm}f^V2#tyyiqWIX(G^y3g4_33Q3;nQMe3lUzXE{S9X)l|+(0A<19d)q zV*LKeFz*e=(s(7mGpl<5X;bBCP>IT-4GeuA^~@!(T2qa@=lu#_!iG?9|2LDw+k7;; z6;2FnXZBu6n8grgU)Po&24jJmuesDc;tH63IEfxapZ33YOQMzmGtEGtSAyjptfS~N z+at60y7mt%-wpmVbw5djglq2fTo%O$w5s1Si+5GgQ8gp`8vy?69nK+9k~5CCKNn{; zsH_ys@VIyRF)!_Zouj(SI1FMZPv6)Htf-#g^&YVvnp4pG z+i_d_op<+NIRFNQDO7Cs`{VHY0Y_zOO%hLEtUpbQN7PxV?r`upp}zaPHCj9{Pq3){ zq-XCt|IQ9a%Cod8973z==&Q1z-agU9;)&Mu=6cWh^QZpk!Z)G0Yt9Xa_HjQi)W9&ss? zr51;lHO(#kb&?(B%CXBmxMoGRV5*RV_PrO!1Eg)1PU6(uP!1~UG%4ye5+Z;rf zQQNAAy{k1y894Ku|3V{gs~*iBeyjw;?6=?WH)`%*tu^y*bDX%DljB%IRTJ-rbG zvaYoip>CiheCN&w?vHtCH2-?M`^TZ04--9b8Sft!Mv(sNV{?;dqzWljSo|BS)$WV( zNzb&aEi+@8pBVdgC7aSYZ9GaR|EJ#6#r37I#Btr2B!MU7L*VBn{iqE3Bk=H{n&bNn zRsMk4h`;3H$#)6FBR?_(6cbJ2KZsFebuxHz;}7esu3v#ptz%A{{bb8pq-9|lZ?zSR z;c8-1Uo_XhpNCz0)Cu%r9(OfwON-Qu(hN6nblA{sRh0xu1u(xU-j2{Xn*=u8^x>w> zxE~#gw|9T0K2NlH@uLo_8fnV;k_^JLR*2lOq4s^!G2$y^X7ylWPWuz|W(T{C&m3{w zc+*?X9=k{H%O{7#DeHG2_<4!t9o9I_3vIS(kbmDmCIT6+8PU}6HC z5~^O6$#cKlee5JlnuT^^fTC`~4>>vK{g?3*!|d=q!kY#!qB&pdzdFU(6`J17S_ew< zZtf<@;f983=zHTvje0hE!L}(j68lYy>dy-oHZ^ktaYeLQ_hib?y*L9NtyD^Uj<`^v zV-J4S7y`9P3t?2`+z3`U{hH1=%yYr>sD^HR$j<{ORjly>!R9`(Zu!Z@#;9THt#1EU z6KvIB)9c0;Y%gYAUNKwT8i8f>R;n89Hod$3exXlSkcdZ{|1vMBJeiZS;@gJjwl;g# zQ{nPyf;+1=C*@Zr4+UpzBl&|@3fKsZMmj$=eKx`8mb4nP{Ss>Jk?`RnwiXN~J!zmu zT2bP3=_>#ElEBg9bmeCYM09E8$;J`fGizC8L8l6fWia25s@TD{{jK^MT+S~YBK^cE zrf}K9XA* z-Hcve!ACsY?f<*(Egpd-@!&QV&0s#tiMtPjQ+sjE0hrXnoyXVkiG@1`|3XOZB{oY8J+}J9B%rvVCy>bE}Ehk>keJ ztI{Jc8Ac!bloGpFW#1guct~3iE!}GeWuHPEn%|w9MeH2C4`G_)p|hrK8H@le;{f>` zWx~?=MD*pu(+HVP6zhhWx4@4!N)=#I?`e!sZ8;qJA23n&wau+YQ7Hb)38Qhc`CI3T zL)d~@N1EJX-dp#g-&3ptBDwo>vy&AO*S8130-hYpVK5Z3X@lqZzV@MXOYx4CuTz%< zms5u9hh+f?i2=Er4?tzF^C3try@})$9U1bzbnaZF{ECp*uXx)&wBFv|EAw3YqNb+m zWA`J!z?#Xg-YexTgD;QEq66<-s5;(nlG3K3MUSA94{AR0Y;%3@@_E%4SQxh9zt}{; z-V)xh3@n_HIe4HJK_Pq1m+KF@9fFBZ`&ujnoto}s=tm9(ue02K;ShKI*T}@4 z5*|+~^ee>vKY&PN@I#rrfr?1e+go3?yAOCm5-HD*marEy_gTq5+UCE@JInAK@Ny8~ zulRQbRe#%V&GCJR;b(?@q!iMi);3!~?)+j5RI!a4+4tmcpM@Qk^*WDxImyOv1V}u3 zSYF^`PMC8c3C!M0SQH=kLY*pIih16f>WurU&l1b~6xYeYgZH3m)>&*SGoy>+haSw5;RT=`;h$@PzqQ)Hz#bHa(@m zwZSD5dJnT9Gg8HhLep9EaV*-ZqF<3KP+}yQb85O>p(D2MMp~(oEnOrT^4x6DESPel ziH6&G@lfZTO!60=sSke#U@-QhE!6F6G3(QN*HpLKQ{9_?nB!`we+w`^CoViGlc@Xu z6uyby*J4M#0o45zTA2_iY^$k#XFR8?fo2rHvNM zdG%{D*GNw&Uw^Xs7rAJGDH!cl=JK?2PGZ&I%oOp z(=>xU@A$e=SWQ8}85HY#H=63s`&uldrDs!}8)t~~T34d#5dnF)o~f30RZ=(eLU|}8 zQf26dPnax>61&9-BzZRKBBp1GA(2iERBa|3xA%iBuuj5T*x@TOL4OjQ=BJEa0|$O-~)3 z3W4(CbHHSw=jn^sXuoaHN#c+$ka@7J1OP`l$Js7^Ao&HnjwH~JT6^m8@kxcAWDeQr zjryNtk2JD37CO76fCGlI=Qs|`gYsn+_BaptixE|g9v>{Ln z#F9EfIw;qwgqGl7u&ZBG##4!WBA3|K$n!9FTZs}9mbVhNim4qkh}JAz0cOKe8G06z zln7FxVN=ltOkaKMN3d}tx$sFaChZF;|EyQbbf%-*4TXc75z%xx1{*p%m;~zR$hRn31`;iCyJpMF!NAok`Wde=M>(krP=}9^TOGgPMfO1tBINShG5n8hL2fAY0 znX5?{yAn|)0~(O)&5K)1HGkbDpe&5Y1op*e4A_9_@l@peajrc{um$k0 ze%{29TJR~}c0`>h>~}cL9Ic>jix+c2*Vx%x3;%DXN1*>jhG#9BN+xqkeK>cJLyZ3C z^1h_f<7i6BZ_(%nL>irD&!$fcYvwP&`cIeg6cqygqNx1U*}Ad7?8siGFo81lX&~H4 zqIJ_S9KM9e6z-`p{vM>Olpjyylqf?_5^>WLXZ%fHnq6-7b91#LodB$a^BDs4`tGPG z27d|v_bxHkNhNZ%C~MFnPOETJ$?7JYIuR4oIG3s+KP)~YF&qxVQ81hA3-VIxvyo7A zxH&>t3LZa}Nz4S!>egL9IEvSN{a8WqWZUvz=2#{*<*Kyg_eNE^xW8c3V{fLz zBIqHvviMf=?89k~ieRBysZR~T%2!(hmi5MP%;z#EOQ^Ez)64{Htjse3af!oxQ3+*Y z2XA+5a7%XCf)+J3m5}XgP#ggnp+9I@UJdn7bP}f-4rTsu2^zV-y)?lAhTyewzz_hM z7_5R{uBOGCrN&ZV1rs@{KSJQc^0?(30fV zbzKkT<6NOQJ*xd}kjCOf(~{~7aAY()p_koTbCu3|{*nOV@akVJ^hYmm$_{1AQ|D!T z6IEAHqLIgqNDzoV*A^1|-Cf>~W5nA96E<~-6Fx3x)Y_4Ld0Gp~PBj4I)||VbrTZ&- zT8$rI;(390pNi$*)@Z?iqZEjlflU?Qr8s&s_%G-&m!yPfr`Vm|=qLV=NquySC_6oo zlB8ud+LoQCr4woH@^uY#K8cc@MQF{C@5*BIty7K*65{$bhbX?mi%s@D1U^(K_~k%C znVIqe>-VCa#d*xEYV$&A40X>Uos^jg;3yZ!&&qv{+r!cWliNmuPfzKAhhJ$s!cp_X8kK3!LOH+lxwQ*tPb^4-pXEnXuP+c#zi-4`L4f@-uWTpA?b`vU~Px zi1Ty0v+ALt@L#nu{)UzAN<^irosxEx{}$7k%DAE*m*a;>UUkS6Fd$tZZ0q$J8;X^$ z05}-VAr1?hANf`is!o(;q#*d5!k;~nT!;?O4y^0J5SEJ{VaRM;G`|3s9^RWi^W2ET z2~E&~_3HTXP**W?ea1|D%cbO}Hk632oH;kHSl8uN@XgHP|APHVF0RjA!m0`P$^!_w z3g+1QZ1GkO3wI-cXGEjVWk7&z(72OPNep>DM6I}EsLlqW?2o?uh3)#f9NNLyB6wv3 zKuv(-4}b&goO861`sH@{N?|ZK!`DQ|n>x!B-jbbS#+a%1nQ%PTbe;~x0vrD*qql<4 zF-wgvVbjz|oo+(Fmjh@lB(N}2Om_i*ecXroMWAMlORtUn|tX=j7dgU1C@zhwo%@NV znCp9h{gmb9H5Vju(?(za-Cwg9(WjayDUZGz{F}NNNQ>)9mQhXeAG=kR?b-LV%&(zD zKPH=-~W^!j7`B*E+)Qy z=G0n$N@y{&?!zEflxfXf`DQGNs;c zHzeMbG$g?V~?V~ov55?0%^Z-bD5^^i+$e<|%Ksf*`A zA8OyJkzES@8ZHs#rt5cod5VzB*8P(%5K_!UbGG~bywPyl66-Y-Fo!(o@FD(8(Mt0)D#tK93meUcjTs&@!4-XYEbf%fC5(=t~N(X2hG z)%zQH#N7K_%}NWW?z`u|DmWr5_oAck7^qK3iwuTdGP-5zW=(nyoe5`-+r>K6s@Sj*`>Y^Gn~EY$G2ZT)$BP4+xA?1{N!aYbItz8h@bedoz7Q} zuP45~|8dfe5p?tJ!(WjKRn~&qO}I7%PmFJdfYCFrIsFy$klh{*>QZI%(z5vk*PFtj zF{iWy3xy`l%i?G)@Y4WaWE@2$D*W?Da)uZB&IZ;)^_Am)KqaA#^^9GvP_**$)#QHL zX)JpVtt4T%A$s#zqbA1R(cGvc!;ybjctQ6Twfh-G z!UgXkiK4X%Jg{M6Ik1^d@vdN`u7jyM>`q%f%>?~s2rh$pyPd2-<*OPuvxx8$W$s!Y zB3Q|dH>^`%IL0UJj*7NqpmK>gxQBwkf53~l;PZ)<$j=wXmv&Y5kwFGlJg*|DXm>XB z4@=whr;Hcj-FtljuWo77opCYSbfm6jkUujX*7)^oF*v5N3HGzq^J)=x@U_`KMbVfN z^&5F@dKQKvps>%aN*dG!LPkiqxCYM;q_8~a1@51Erq2njB3*>BeAJV9VQ0;#H z$SY&pXOBf;hsV2QW&7t-$^9!e!Mknd9fuV{n+7P=M@XL<<|TM^MhRDuZNWb^IWTe( zs7tdQA!kuM@dNOlkzvZ69$ZTO8?sP($KEUm_@2Z=gCIiPmB!URVfjJz%r@xtvp97i z*y}c-EamXe)Mm>LWyZ9u>2`veLg(pDJOYN z8h7f+#_1rO9#m8_U{HMwRb2-Sxc5nUT>0?XAOJyLqs^1A!r8`@> zQn^Dz`u>!vBlG&b9vt~0p+@ALZwklL9P0l7H;2Deq`w>e$}lgkisij|{A{rUqpwZ9 z=9KtqnAp<<-~6fK>nMsaLvJlCF>BP^z6466cB@7H4bzk;T@l?ru&2sT4f)MGTZ3j_ z3$sc4bvHBBt4pL@nMvy=upT`+22gYf>eg|de1|f%{R>$A(?JSWr=+m?OOd$Kd-0y?|j(S=+(p<{6Rrh!Y zZ`|EZ{HJE#z|D7kRv36U>OxY-=1Gj*A^mh;dJ@;vfIsLWznxJP(xD+r(q4jlv*Il! zf(s^Q8GnD=u-9_lcu!;`+D&yiKak8*zTp>2bm{hk&ZDBCdP7P}Jrg&1)IVas4CL=fY~ex{UR=ueX`%!q~FG zpGekoanvU)OOHP;r*-6 z8WlAO=!4Jhf|~Gc7=oj$Q6zsmU=N;op&Rig?=LOv1*V9?9VE%d~ArI zA)WrhtWAcDO*LN!@c}!l97pqh5s_(d(np_*$APL%VN<9IbVUuX#=OHI`&dTt7mGULgu!DhggYrA^B=eG937 z@AgNgx#vj}-Pant>QU$9l}2)}DxaX5!q<$ClM^e)xl7GBA2P*}qD_bRPGVuCwemc5 zWNI_ZwRmTg?H<+Q627oisoayBCWxuO$3`U4N;-E$weiNzgorG<*JZvbNC|i1xa(QbdS5xxnb@V`mcd zTNMPri`g1PX59QLUf)0B+L!=RqG~hA{dUyp|D+g#Lje!=QJ1w>oJ^~!!N-n}MvFui z0oGhVE2Wh_*LSr@7(d$j-Cc=FXlVF$zKlGD^Xp7f2QSW+euOQ>oA|s?k%zQDa3^J9 z%}%;f&cRaOlh1yGv$%VFrtQxW{{f+8Yc>H-mNl5{Ffjv7bf6W^q_mg35Br>{%6#~WU@RV4HJ{Ifz_WXsr(mTPtQbM14hz3A?qYDia1qGQlE ziGA|7CZR&Mlm4E3Y1$j-3_`B3Y{OzhUov4OA~FLNqbMma^Yb9YapR#&%Gydqnue`9 zCuC%<+1#EYw)JHwak%scQ&`^{zzs!l$}#^D!!oi+Hevmg$58vud$+sq&^Ol7Ll>J) ze`t>$j2Y5J%MO`C)Rq_Q4mj2w4ne|z<1<5{wY ziU3o$!rrObM@8SKLD%)HMyCT?c!{0pr1}2No|%a08#*jocYxA@G+NC38vURSPk&J7#bO4=PGD z4}qvy?ovzbW9`4c@2Gnan?ZhnWvMmJ`Cx_M!$3Dk4*)$X>yN?x(A;(Hj8lxcNP2`Z zXuD6;-H{C7mf}udG;3@-Jh>7bG1YjZ>2veveLSX-p{e0TW9i-YPA#UCB2VsA%rGG$ zc%){Lu%J74_AuDFE2_DJz?T#j}Fov5~5YP^n4Y zhvawv1E6)}%zUU1{_0x?`GhZ*yd#u;C}%%VZ0PMxY`2?#ckBC``U)+l1BFmtOB##Q z_T$Q1tw9T$iLS|HrQ9D<0-IlRT%|URl}Vk}%riA{`ttq40op4LZ$#ZCMQxo9-QF06ge!(( NSXx~^XJ;JC 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 E0eWC~JOBUy literal 0 HcmV?d00001 diff --git a/src/current/molt/migrate-bulk-load.md b/src/current/molt/migrate-bulk-load.md index 5b5be1f5852..058bcc5759f 100644 --- a/src/current/molt/migrate-bulk-load.md +++ b/src/current/molt/migrate-bulk-load.md @@ -21,7 +21,7 @@ Perform a one-time bulk load of source data into CockroachDB. Perform the bulk load of the source data. -1. Run the [MOLT Fetch]({% link molt/molt-fetch.md %}) command to move the source data into CockroachDB. This example command passes the source and target connection strings [as environment variables](#secure-connections), writes [intermediate files](#intermediate-file-storage) to S3 storage, and uses the `truncate-if-exists` [table handling mode](#table-handling-mode) to truncate the target tables before loading data. It limits the migration to a single schema and filters for three specific tables. The [data load mode](#data-load-mode) defaults to `IMPORT INTO`. Include the `--ignore-replication-check` flag to skip replication checkpoint queries, which eliminates the need to configure the source database for logical replication. +1. Run the [MOLT Fetch]({% link molt/molt-fetch.md %}) command to move the source data into CockroachDB. This example command passes the source and target connection strings [as environment variables](#secure-connections), writes [intermediate files](#intermediate-file-storage) to S3 storage, and uses the `truncate-if-exists` [table handling mode](#table-handling-mode) to truncate the target tables before loading data. It limits the migration to a single schema and filters for three specific tables. The [data load mode]({% link molt/molt-fetch.md %}#import-into-vs-copy-from) defaults to `IMPORT INTO`. Include the `--ignore-replication-check` flag to skip replication checkpoint queries, which eliminates the need to configure the source database for logical replication.

    {% include_cached copy-clipboard.html %} @@ -51,7 +51,7 @@ Perform the bulk load of the source data.
    - The command assumes an Oracle Multitenant (CDB/PDB) source. `--source-cdb` specifies the container database (CDB) connection string. + The command assumes an Oracle Multitenant (CDB/PDB) source. [`--source-cdb`]({% link molt/molt-fetch-commands-and-flags.md %}#source-cdb) specifies the container database (CDB) connection string. {% include_cached copy-clipboard.html %} ~~~ shell diff --git a/src/current/molt/migrate-load-replicate.md b/src/current/molt/migrate-load-replicate.md index f1de67c8175..679f3f155a9 100644 --- a/src/current/molt/migrate-load-replicate.md +++ b/src/current/molt/migrate-load-replicate.md @@ -15,7 +15,7 @@ Perform an initial bulk load of the source data using [MOLT Fetch]({% link molt/ Perform the initial load of the source data. -1. Issue the [MOLT Fetch]({% link molt/molt-fetch.md %}) command to move the source data to CockroachDB. This example command passes the source and target connection strings [as environment variables](#secure-connections), writes [intermediate files](#intermediate-file-storage) to S3 storage, and uses the `truncate-if-exists` [table handling mode](#table-handling-mode) to truncate the target tables before loading data. It also limits the migration to a single schema and filters three specific tables to migrate. The [data load mode](#data-load-mode) defaults to `IMPORT INTO`. +1. Issue the [MOLT Fetch]({% link molt/molt-fetch.md %}) command to move the source data to CockroachDB. This example command passes the source and target connection strings [as environment variables](#secure-connections), writes [intermediate files](#intermediate-file-storage) to S3 storage, and uses the `truncate-if-exists` [table handling mode](#table-handling-mode) to truncate the target tables before loading data. It also limits the migration to a single schema and filters three specific tables to migrate. The [data load mode]({% link molt/molt-fetch.md %}#import-into-vs-copy-from) defaults to `IMPORT INTO`.
    You **must** include `--pglogical-replication-slot-name` and `--pglogical-publication-and-slot-drop-and-recreate` to automatically create the publication and replication slot during the data load. @@ -47,7 +47,7 @@ Perform the initial load of the source data.
    - The command assumes an Oracle Multitenant (CDB/PDB) source. `--source-cdb` specifies the container database (CDB) connection string. + The command assumes an Oracle Multitenant (CDB/PDB) source. [`--source-cdb`]({% link molt/molt-fetch-commands-and-flags.md %}#source-cdb) specifies the container database (CDB) connection string. {% include_cached copy-clipboard.html %} ~~~ shell diff --git a/src/current/molt/migrate-to-cockroachdb.md b/src/current/molt/migrate-to-cockroachdb.md index 13b28bd1cc3..745de598299 100644 --- a/src/current/molt/migrate-to-cockroachdb.md +++ b/src/current/molt/migrate-to-cockroachdb.md @@ -5,7 +5,7 @@ toc: true docs_area: migrate --- -MOLT Fetch supports various migration flows using [MOLT Fetch modes]({% link molt/molt-fetch.md %}#fetch-mode). +MOLT Fetch supports various migration flows using [MOLT Fetch modes]({% link molt/molt-fetch.md %}#define-fetch-mode). {% include molt/crdb-to-crdb-migration.md %} diff --git a/src/current/molt/migration-considerations-phases.md b/src/current/molt/migration-considerations-phases.md index b525b9b80c8..9df80280da6 100644 --- a/src/current/molt/migration-considerations-phases.md +++ b/src/current/molt/migration-considerations-phases.md @@ -73,7 +73,7 @@ Phased migrations require the ability to route specific tenants, services, or re Phased and unphased migrations are both supported natively by MOLT. -By default, [MOLT Fetch]({% link molt/molt-fetch.md %}) moves all data from the source database to CockroachDB. However, you can use the `--schema-filter`, `--table-filter`, and `--filter-path` flags to selective migrate data from the source to the target. Learn more about [schema and table selection]({% link molt/molt-fetch.md %}#schema-and-table-selection) and [selective data movement]({% link molt/molt-fetch.md %}#selective-data-movement), both of which can enable a phased migration. +By default, [MOLT Fetch]({% link molt/molt-fetch.md %}) moves all data from the source database to CockroachDB. However, you can use the [`--schema-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#schema-filter), [`--table-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#table-filter), and [`--filter-path`]({% link molt/molt-fetch-commands-and-flags.md %}#filter-path) flags to selective migrate data from the source to the target. Learn more about [schema and table selection]({% link molt/molt-fetch.md %}#schema-and-table-selection) and [selective data movement]({% link molt/molt-fetch.md %}#select-data-to-migrate), both of which can enable a phased migration. Similarly, you can use [MOLT Verify]({% link molt/molt-verify.md %})'s `--schema-filter` and `--table-filter` flags to run validation checks on subsets of the data in your source and target databases. In a phased migration, you will likely want to verify data at the end of each migration phase, rather than at the end of the entire migration. diff --git a/src/current/molt/migration-considerations-replication.md b/src/current/molt/migration-considerations-replication.md index b62e25edfe3..ef7dd33d47e 100644 --- a/src/current/molt/migration-considerations-replication.md +++ b/src/current/molt/migration-considerations-replication.md @@ -66,9 +66,9 @@ The MOLT toolkit provides two complementary tools for data migration: [MOLT Fetc Use MOLT Fetch to export and load data to CockroachDB. -For pure bulk migrations, set the `--ignore-replication-check` flag to skip gathering replication checkpoints. This simplifies the workflow when you don't need to track change positions for subsequent replication. +For pure bulk migrations, set the [`--ignore-replication-check`]({% link molt/molt-fetch-commands-and-flags.md %}#ignore-replication-check) flag to skip gathering replication checkpoints. This simplifies the workflow when you don't need to track change positions for subsequent replication. -MOLT Fetch supports both `IMPORT INTO` (default, for highest throughput with offline tables) and `COPY FROM` (for online tables) loading methods. Because a pure bulk load approach will likely involve substantial application downtime, you may benefit from using `IMPORT INTO`. In this case, do not use the `--use-copy` flag. Learn more about Fetch's [data load modes]({% link molt/molt-fetch.md %}#data-load-mode). +MOLT Fetch supports both `IMPORT INTO` (default, for highest throughput with offline tables) and `COPY FROM` (for online tables) loading methods. Because a pure bulk load approach will likely involve substantial application downtime, you may benefit from using `IMPORT INTO`. In this case, do not use the [`--use-copy`]({% link molt/molt-fetch-commands-and-flags.md %}#use-copy) flag. Learn more about Fetch's [data load modes]({% link molt/molt-fetch.md %}#import-into-vs-copy-from). A migration that does not utilize continuous replication would not need to use MOLT Replicator. @@ -84,9 +84,9 @@ molt fetch \ Use MOLT Fetch to export and load the inital dataset to CockroachDB. Then start MOLT Replicator to begin streaming changes from the source database to CockroachDB. -When you run MOLT Fetch without `--ignore-replication-check`, it emits a checkpoint value that marks the point in time when the bulk load snapshot was taken. After MOLT Fetch completes, the checkpoint is stored in the target database. MOLT Replicator then uses this checkpoint to begin streaming changes from exactly that point, ensuring no data is missed between the bulk load and continuous replication. Learn more about [replication checkpoints]({% link molt/molt-replicator.md %}#replication-checkpoints). +When you run MOLT Fetch without [`--ignore-replication-check`]({% link molt/molt-fetch-commands-and-flags.md %}#ignore-replication-check), it emits a checkpoint value that marks the point in time when the bulk load snapshot was taken. After MOLT Fetch completes, the checkpoint is stored in the target database. MOLT Replicator then uses this checkpoint to begin streaming changes from exactly that point, ensuring no data is missed between the bulk load and continuous replication. Learn more about [replication checkpoints]({% link molt/molt-replicator.md %}#replication-checkpoints). -MOLT Fetch supports both `IMPORT INTO` (default, for highest throughput with offline tables) and `COPY FROM` (for online tables) loading methods. Because a hybrid approach will likely aim to have less downtime, you may need to use `COPY FROM` if your tables remain online. In this case, use the `--use-copy` flag. Learn more about Fetch's [data load modes]({% link molt/molt-fetch.md %}#data-load-mode). +MOLT Fetch supports both `IMPORT INTO` (default, for highest throughput with offline tables) and `COPY FROM` (for online tables) loading methods. Because a hybrid approach will likely aim to have less downtime, you may need to use `COPY FROM` if your tables remain online. In this case, use the [`--use-copy`]({% link molt/molt-fetch-commands-and-flags.md %}#use-copy) flag. Learn more about Fetch's [data load modes]({% link molt/molt-fetch.md %}#import-into-vs-copy-from). MOLT Replicator replicates full tables by default. If you choose to combine continuous replication with a [phased migration]({% link molt/migration-considerations-phases.md %}), you will either need to select phases that include whole tables, or else use [userscripts]({% link molt/replicator-flags.md %}#userscript) to select rows to replicate. diff --git a/src/current/molt/migration-considerations-transformation.md b/src/current/molt/migration-considerations-transformation.md index 7d517761dad..a83f2f00d80 100644 --- a/src/current/molt/migration-considerations-transformation.md +++ b/src/current/molt/migration-considerations-transformation.md @@ -64,10 +64,10 @@ While not a part of the transformation process itself, the [MOLT Schema Conversi [MOLT Fetch]({% link molt/molt-fetch.md %}) supports transformations during a bulk data load: -- **Row filtering**: `--filter-path` specifies a JSON file with table-to-SQL-predicate mappings evaluated in the source dialect before export. Ensure filtered columns are indexed for performance. -- **Schema shaping**: `--transformations-file` defines table renames, n→1 merges (consolidate partitioned tables), and column exclusions. For n→1 merges, use `--use-copy` or `--direct-copy` and pre-create the target table. -- **Type alignment**: `--type-map-file` specifies explicit type mappings when auto-creating target tables. -- **Table lifecycle**: `--table-handling` controls whether to truncate, drop-and-recreate, or assume tables exist. +- **Row filtering**: [`--filter-path`]({% link molt/molt-fetch-commands-and-flags.md %}#filter-path) specifies a JSON file with table-to-SQL-predicate mappings evaluated in the source dialect before export. Ensure filtered columns are indexed for performance. +- **Schema shaping**: [`--transformations-file`]({% link molt/molt-fetch-commands-and-flags.md %}#transformations-file) defines table renames, n→1 merges (consolidate partitioned tables), and column exclusions. For n→1 merges, use [`--use-copy`]({% link molt/molt-fetch-commands-and-flags.md %}#use-copy) or [`--direct-copy`]({% link molt/molt-fetch-commands-and-flags.md %}#direct-copy) and pre-create the target table. +- **Type alignment**: [`--type-map-file`]({% link molt/molt-fetch-commands-and-flags.md %}#type-map-file) specifies explicit type mappings when auto-creating target tables. +- **Table lifecycle**: [`--table-handling`]({% link molt/molt-fetch-commands-and-flags.md %}#table-handling) controls whether to truncate, drop-and-recreate, or assume tables exist. ### MOLT Replicator diff --git a/src/current/molt/migration-overview.md b/src/current/molt/migration-overview.md index 043a21ac524..0ad317a1346 100644 --- a/src/current/molt/migration-overview.md +++ b/src/current/molt/migration-overview.md @@ -101,10 +101,10 @@ The [MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}) [MOLT Fetch]({% link molt/molt-fetch.md %}) performs the initial data load to CockroachDB. It supports: - Multiple migration flows via `IMPORT INTO` or `COPY FROM`. -- Data movement via [cloud storage, local file servers, or direct copy]({% link molt/molt-fetch.md %}#data-path). +- Data movement via [cloud storage, local file servers, or direct copy]({% link molt/molt-fetch.md %}#define-intermediate-storage). - [Concurrent data export]({% link molt/molt-fetch-best-practices.md %}) from multiple source tables and shards. -- [Schema transformation rules]({% link molt/molt-fetch.md %}#transformations). -- After exporting data with `IMPORT INTO`, safe [continuation]({% link molt/molt-fetch.md %}#fetch-continuation) to retry failed or interrupted tasks from specific checkpoints. +- [Schema transformation rules]({% link molt/molt-fetch.md %}#define-transformations). +- After exporting data with `IMPORT INTO`, safe [continuation]({% link molt/molt-fetch.md %}#continue-molt-fetch-after-interruption) to retry failed or interrupted tasks from specific checkpoints. ### Replicator diff --git a/src/current/molt/migration-strategy.md b/src/current/molt/migration-strategy.md index b6e76d0c14f..29fb8ecb51f 100644 --- a/src/current/molt/migration-strategy.md +++ b/src/current/molt/migration-strategy.md @@ -97,7 +97,7 @@ Based on the error budget you [defined in your migration plan](#develop-a-migrat It's useful to load test data into CockroachDB so that you can [test your application queries](#validate-queries). -MOLT Fetch [supports both `IMPORT INTO` and `COPY FROM`]({% link molt/molt-fetch.md %}#data-load-mode) for loading data into CockroachDB: +MOLT Fetch [supports both `IMPORT INTO` and `COPY FROM`]({% link molt/molt-fetch.md %}#import-into-vs-copy-from) for loading data into CockroachDB: - Use `IMPORT INTO` for maximum throughput when the target tables can be offline. For a bulk data migration, most users should use `IMPORT INTO` because the tables will be offline anyway, and `IMPORT INTO` can [perform the data import much faster]({% link {{ site.current_cloud_version }}/import-performance-best-practices.md %}) than `COPY FROM`. - Use `COPY FROM` (or `--direct-copy`) when the target must remain queryable during load. diff --git a/src/current/molt/molt-fetch-best-practices.md b/src/current/molt/molt-fetch-best-practices.md index 6cd23af114b..8c14342a3c2 100644 --- a/src/current/molt/molt-fetch-best-practices.md +++ b/src/current/molt/molt-fetch-best-practices.md @@ -16,12 +16,12 @@ To verify that your connections and configuration work properly, run MOLT Fetch - **Maximum allowed number of connections.** MOLT Fetch can export data across multiple connections. The number of connections it will create is the number of shards ([`--export-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags)) multiplied by the number of tables ([`--table-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags)) being exported concurrently. {{site.data.alerts.callout_info}} - With the default numerical range sharding, only tables with [primary key]({% link {{ site.current_cloud_version }}/primary-key.md %}) types of [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) can be sharded. PostgreSQL users can enable [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) to use statistics-based sharding for tables with primary keys of any data type. For details, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding). + With the default numerical range sharding, only tables with [primary key]({% link {{ site.current_cloud_version }}/primary-key.md %}) types of [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) can be sharded. PostgreSQL users can enable [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) to use statistics-based sharding for tables with primary keys of any data type. For details, refer to [Table sharding]({% link molt/molt-fetch.md %}#shard-tables-for-concurrent-export). {{site.data.alerts.end}} - **Maximum lifetime of a connection.** -- If a PostgreSQL database is set as a [source]({% link molt/molt-fetch.md %}#source-and-target-databases), ensure that [`idle_in_transaction_session_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT) on PostgreSQL is either disabled or set to a value longer than the duration of the [data export phase]({% link molt/molt-fetch.md %}#data-export-phase). Otherwise, the connection will be prematurely terminated. To estimate the time needed to export the PostgreSQL tables, you can perform a dry run and sum the value of [`molt_fetch_table_export_duration_ms`]({% link molt/molt-fetch-monitoring.md %}#metrics) for all exported tables. +- If a PostgreSQL database is set as a [source]({% link molt/molt-fetch.md %}#specify-source-and-target-databases), ensure that [`idle_in_transaction_session_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT) on PostgreSQL is either disabled or set to a value longer than the duration of the [data export phase]({% link molt/molt-fetch.md %}#data-export-phase). Otherwise, the connection will be prematurely terminated. To estimate the time needed to export the PostgreSQL tables, you can perform a dry run and sum the value of [`molt_fetch_table_export_duration_ms`]({% link molt/molt-fetch-monitoring.md %}#metrics) for all exported tables. ## Optimize performance @@ -35,15 +35,15 @@ To verify that your connections and configuration work properly, run MOLT Fetch --row-batch-size * --export-concurrency * average size of the table rows ~~~ - If you are exporting more than one table at a time (i.e., [`--table-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) is set higher than `1`), add the estimated memory usage for the tables with the largest row sizes. Ensure that you have sufficient memory to run `molt fetch`, and adjust `--row-batch-size` accordingly. For details on how concurrency and sharding interact, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding). + If you are exporting more than one table at a time (i.e., [`--table-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) is set higher than `1`), add the estimated memory usage for the tables with the largest row sizes. Ensure that you have sufficient memory to run `molt fetch`, and adjust [`--row-batch-size`]({% link molt/molt-fetch-commands-and-flags.md %}#row-batch-size) accordingly. For details on how concurrency and sharding interact, refer to [Table sharding]({% link molt/molt-fetch.md %}#shard-tables-for-concurrent-export). - If a table in the source database is much larger than the other tables, [filter and export the largest table]({% link molt/molt-fetch.md %}#schema-and-table-selection) in its own `molt fetch` task. Repeat this for each of the largest tables. Then export the remaining tables in another task. -- Ensure that the machine running MOLT Fetch is large enough to handle the amount of data being migrated. Fetch performance can sometimes be limited by available resources, but should always be making progress. To identify possible resource constraints, observe the `molt_fetch_rows_exported` [metric]({% link molt/molt-fetch-monitoring.md %}#metrics) for decreases in the number of rows being processed. You can use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view metrics. For details on optimizing export performance through sharding, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding). +- Ensure that the machine running MOLT Fetch is large enough to handle the amount of data being migrated. Fetch performance can sometimes be limited by available resources, but should always be making progress. To identify possible resource constraints, observe the `molt_fetch_rows_exported` [metric]({% link molt/molt-fetch-monitoring.md %}#metrics) for decreases in the number of rows being processed. You can use the [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) to view metrics. For details on optimizing export performance through sharding, refer to [Table sharding]({% link molt/molt-fetch.md %}#shard-tables-for-concurrent-export). ## Import and continuation handling -- When using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#data-load-mode) during the [data import phase]({% link molt/molt-fetch.md %}#data-import-phase) to load tables into CockroachDB, if the fetch task terminates before the import job completes, the hanging import job on the target database will keep the table offline. To make this table accessible again, [manually resume or cancel the job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs). Then resume `molt fetch` using [continuation]({% link molt/molt-fetch.md %}#fetch-continuation), or restart the task from the beginning. +- When using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#import-into-vs-copy-from) during the [data import phase]({% link molt/molt-fetch.md %}#data-import-phase) to load tables into CockroachDB, if the fetch task terminates before the import job completes, the hanging import job on the target database will keep the table offline. To make this table accessible again, [manually resume or cancel the job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs). Then resume `molt fetch` using [continuation]({% link molt/molt-fetch.md %}#continue-molt-fetch-after-interruption), or restart the task from the beginning. ## Security @@ -54,7 +54,7 @@ Cockroach Labs strongly recommends the following security practices. {% include molt/molt-secure-connection-strings.md %} {{site.data.alerts.callout_info}} -By default, insecure connections (i.e., `sslmode=disable` on PostgreSQL; `sslmode` not set on MySQL) are disallowed. When using an insecure connection, `molt fetch` returns an error. To override this check, you can enable the `--allow-tls-mode-disable` flag. Do this **only** when testing, or if a secure SSL/TLS connection to the source or target database is not possible. +By default, insecure connections (i.e., `sslmode=disable` on PostgreSQL; `sslmode` not set on MySQL) are disallowed. When using an insecure connection, `molt fetch` returns an error. To override this check, you can enable the [`--allow-tls-mode-disable`]({% link molt/molt-fetch-commands-and-flags.md %}#allow-tls-mode-disable) flag. Do this **only** when testing, or if a secure SSL/TLS connection to the source or target database is not possible. {{site.data.alerts.end}} ### Cloud storage security diff --git a/src/current/molt/molt-fetch-commands-and-flags.md b/src/current/molt/molt-fetch-commands-and-flags.md index f01967293a6..1c3a61c2103 100644 --- a/src/current/molt/molt-fetch-commands-and-flags.md +++ b/src/current/molt/molt-fetch-commands-and-flags.md @@ -23,60 +23,60 @@ docs_area: migrate | Flag | Description | |---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `--source` | (Required) Connection string used to connect to the Oracle PDB (in a CDB/PDB architecture) or to a standalone database (non‑CDB). For details, refer to [Source and target databases]({% link molt/molt-fetch.md %}#source-and-target-databases). | -| `--source-cdb` | Connection string for the Oracle container database (CDB) when using a multitenant (CDB/PDB) architecture. Omit this flag on a non‑multitenant Oracle database. For details, refer to [Source and target databases]({% link molt/molt-fetch.md %}#source-and-target-databases). | -| `--target` | (Required) Connection string for the target database. For details, refer to [Source and target databases]({% link molt/molt-fetch.md %}#source-and-target-databases). | -| `--allow-tls-mode-disable` | Allow insecure connections to databases. Secure SSL/TLS connections should be used by default. This should be enabled **only** if secure SSL/TLS connections to the source or target database are not possible. | -| `--assume-role` | Service account to use for assume role authentication. `--use-implicit-auth` must be included. For example, `--assume-role='user-test@cluster-ephemeral.iam.gserviceaccount.com' --use-implicit-auth`. For details, refer to [Cloud Storage Authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}). | -| `--bucket-path` | The path within the [cloud storage]({% link molt/molt-fetch.md %}#bucket-path) bucket where intermediate files are written (e.g., `'s3://bucket/path'` or `'gs://bucket/path'`). Only the URL path is used; query parameters (e.g., credentials) are ignored. To pass in query parameters, use the appropriate flags: `--assume-role`, `--import-region`, `--use-implicit-auth`. | -| `--case-sensitive` | Toggle case sensitivity when comparing table and column names on the source and target. To disable case sensitivity, set `--case-sensitive=false`. If `=` is **not** included (e.g., `--case-sensitive false`), the flag is interpreted as `--case-sensitive` (i.e., `--case-sensitive=true`).

    **Default:** `false` | -| `--cleanup` | Whether to delete intermediate files after moving data using [cloud or local storage]({% link molt/molt-fetch.md %}#data-path). **Note:** Cleanup does not occur on [continuation]({% link molt/molt-fetch.md %}#fetch-continuation). | -| `--compression` | Compression method for data when using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#data-load-mode) (`gzip`/`none`).

    **Default:** `gzip` | -| `--continuation-file-name` | Restart fetch at the specified filename if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation]({% link molt/molt-fetch.md %}#fetch-continuation). | -| `--continuation-token` | Restart fetch at a specific table, using the specified continuation token, if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation]({% link molt/molt-fetch.md %}#fetch-continuation). | -| `--crdb-pts-duration` | The duration for which each timestamp used in data export from a CockroachDB source is protected from garbage collection. This ensures that the data snapshot remains consistent. For example, if set to `24h`, each timestamp is protected for 24 hours from the initiation of the export job. This duration is extended at regular intervals specified in `--crdb-pts-refresh-interval`.

    **Default:** `24h0m0s` | -| `--crdb-pts-refresh-interval` | The frequency at which the protected timestamp's validity is extended. This interval maintains protection of the data snapshot until data export from a CockroachDB source is completed. For example, if set to `10m`, the protected timestamp's expiration will be extended by the duration specified in `--crdb-pts-duration` (e.g., `24h`) every 10 minutes while export is not complete.

    **Default:** `10m0s` | -| `--direct-copy` | Enables [direct copy]({% link molt/molt-fetch.md %}#direct-copy), which copies data directly from source to target without using an intermediate store. | -| `--export-concurrency` | Number of shards to export at a time per table, each on a dedicated thread. This controls how many shards are created for each individual table during the [data export phase]({% link molt/molt-fetch.md %}#data-export-phase) and is distinct from `--table-concurrency`, which controls how many tables are processed simultaneously. The total number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`. Tables can be sharded with a range-based or stats-based mechanism. For details, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding).

    **Default:** `4` | -| `--export-retry-max-attempts` | Maximum number of retry attempts for source export queries when connection failures occur. Only supported for PostgreSQL and CockroachDB sources.

    **Default:** `3` | -| `--export-retry-max-duration` | Maximum total duration for retrying source export queries. If `0`, no time limit is enforced. Only supported for PostgreSQL and CockroachDB sources.

    **Default:** `5m0s` | -| `--filter-path` | Path to a JSON file defining row-level filters for the [data import phase]({% link molt/molt-fetch.md %}#data-import-phase). Refer to [Selective data movement]({% link molt/molt-fetch.md %}#selective-data-movement). | -| `--fetch-id` | Restart fetch task corresponding to the specified ID. If `--continuation-file-name` or `--continuation-token` are not specified, fetch restarts for all failed tables. | -| `--flush-rows` | Number of rows before the source data is flushed to intermediate files. **Note:** If `--flush-size` is also specified, the fetch behavior is based on the flag whose criterion is met first. | -| `--flush-size` | Size (in bytes) before the source data is flushed to intermediate files. **Note:** If `--flush-rows` is also specified, the fetch behavior is based on the flag whose criterion is met first. | -| `--ignore-replication-check` | Skip querying for replication checkpoints such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle. This option is intended for use during bulk load migrations or when doing a one-time data export from a read replica. | -| `--import-batch-size` | The number of files to be imported at a time to the target database during the [data import phase]({% link molt/molt-fetch.md %}#data-import-phase). This applies only when using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#data-load-mode) for data movement. **Note:** Increasing this value can improve the performance of full-scan queries on the target database shortly after fetch completes, but very high values are not recommended. If any individual file in the import batch fails, you must [retry]({% link molt/molt-fetch.md %}#fetch-continuation) the entire batch.

    **Default:** `1000` | -| `--import-region` | The region of the [cloud storage]({% link molt/molt-fetch.md %}#bucket-path) bucket. This applies only to [Amazon S3 buckets]({% link molt/molt-fetch.md %}#bucket-path). Set this flag only if you need to specify an `AWS_REGION` explicitly when using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#data-load-mode) for data movement. For example, `--import-region=ap-south-1`. | -| `--local-path` | The path within the [local file server]({% link molt/molt-fetch.md %}#local-path) where intermediate files are written (e.g., `data/migration/cockroach`). `--local-path-listen-addr` must be specified. | -| `--local-path-crdb-access-addr` | Address of a [local file server]({% link molt/molt-fetch.md %}#local-path) that is **publicly accessible**. This flag is only necessary if CockroachDB cannot reach the local address specified with `--local-path-listen-addr` (e.g., when moving data to a CockroachDB {{ site.data.products.cloud }} deployment). `--local-path` and `--local-path-listen-addr` must be specified.

    **Default:** Value of `--local-path-listen-addr`. | -| `--local-path-listen-addr` | Write intermediate files to a [local file server]({% link molt/molt-fetch.md %}#local-path) at the specified address (e.g., `'localhost:3000'`). `--local-path` must be specified. | -| `--log-file` | Write messages to the specified log filename. If no filename is provided, messages write to `fetch-{datetime}.log`. If `"stdout"` is provided, messages write to `stdout`. | -| `--logging` | Level at which to log messages (`trace`/`debug`/`info`/`warn`/`error`/`fatal`/`panic`).

    **Default:** `info` | -| `--metrics-listen-addr` | Address of the Prometheus metrics endpoint, which has the path `{address}/metrics`. For details on important metrics to monitor, refer to [Monitoring]({% link molt/molt-fetch-monitoring.md %}).

    **Default:** `'127.0.0.1:3030'` | -| `--mode` | Configure the MOLT Fetch behavior: `data-load`, `export-only`, or `import-only`. For details, refer to [Fetch mode]({% link molt/molt-fetch.md %}#fetch-mode).

    **Default:** `data-load` | -| `--non-interactive` | Run the fetch task without interactive prompts. This is recommended **only** when running `molt fetch` in an automated process (i.e., a job or continuous integration). | -| `--pprof-listen-addr` | Address of the pprof endpoint.

    **Default:** `'127.0.0.1:3031'` | -| `--row-batch-size` | Number of rows per shard to export at a time. For details on sharding, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding). See also [Best practices]({% link molt/molt-fetch-best-practices.md %}).

    **Default:** `100000` | -| `--schema-filter` | Move schemas that match a specified [regular expression](https://wikipedia.org/wiki/Regular_expression).

    **Default:** `'.*'` | -| `--skip-pk-check` | Skip primary-key matching to allow data load when source or target tables have missing or mismatched primary keys. Disables sharding and bypasses `--export-concurrency` and `--row-batch-size` settings. Refer to [Skip primary key matching]({% link molt/molt-fetch.md %}#skip-primary-key-matching).

    **Default:** `false` | -| `--table-concurrency` | Number of tables to export at a time. The number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`.

    **Default:** `4` | -| `--table-exclusion-filter` | Exclude tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

    This value **cannot** be set to `'.*'`, which would cause every table to be excluded.

    **Default:** Empty string | -| `--table-filter` | Move tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

    **Default:** `'.*'` | -| `--table-handling` | How tables are initialized on the target database (`none`/`drop-on-target-and-recreate`/`truncate-if-exists`). For details, see [Target table handling]({% link molt/molt-fetch.md %}#target-table-handling).

    **Default:** `none` | -| `--transformations-file` | Path to a JSON file that defines transformations to be performed on the target schema during the fetch task. Refer to [Transformations]({% link molt/molt-fetch.md %}#transformations). | -| `--type-map-file` | Path to a JSON file that contains explicit type mappings for automatic schema creation, when enabled with `--table-handling drop-on-target-and-recreate`. For details on the JSON format and valid type mappings, see [type mapping]({% link molt/molt-fetch.md %}#type-mapping). | -| `--use-console-writer` | Use the console writer, which has cleaner log output but introduces more latency.

    **Default:** `false` (log as structured JSON) | -| `--use-copy` | Use [`COPY FROM`]({% link molt/molt-fetch.md %}#data-load-mode) to move data. This makes tables queryable during data load, but is slower than using `IMPORT INTO`. For details, refer to [Data movement]({% link molt/molt-fetch.md %}#data-load-mode). | -| `--use-implicit-auth` | Use [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}) for [cloud storage]({% link molt/molt-fetch.md %}#bucket-path) URIs. | -| `--use-stats-based-sharding` | Enable statistics-based sharding for PostgreSQL sources. This allows sharding of tables with primary keys of any data type and can create more evenly distributed shards compared to the default numerical range sharding. Requires PostgreSQL 11+ and access to `pg_stats`. For details, refer to [Table sharding]({% link molt/molt-fetch.md %}#table-sharding). | +|
    `--source` | (Required) Connection string used to connect to the Oracle PDB (in a CDB/PDB architecture) or to a standalone database (non‑CDB). For details, refer to [Source and target databases]({% link molt/molt-fetch.md %}#specify-source-and-target-databases). | +| `--source-cdb` | Connection string for the Oracle container database (CDB) when using a multitenant (CDB/PDB) architecture. Omit this flag on a non‑multitenant Oracle database. For details, refer to [Source and target databases]({% link molt/molt-fetch.md %}#specify-source-and-target-databases). | +| `--target` | (Required) Connection string for the target database. For details, refer to [Source and target databases]({% link molt/molt-fetch.md %}#specify-source-and-target-databases). | +| `--allow-tls-mode-disable` | Allow insecure connections to databases. Secure SSL/TLS connections should be used by default. This should be enabled **only** if secure SSL/TLS connections to the source or target database are not possible. | +| `--assume-role` | Service account to use for assume role authentication. `--use-implicit-auth` must be included. For example, `--assume-role='user-test@cluster-ephemeral.iam.gserviceaccount.com' --use-implicit-auth`. For details, refer to [Cloud Storage Authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}). | +| `--bucket-path` | The path within the [cloud storage]({% link molt/molt-fetch.md %}#bucket-path) bucket where intermediate files are written (e.g., `'s3://bucket/path'` or `'gs://bucket/path'`). Only the URL path is used; query parameters (e.g., credentials) are ignored. To pass in query parameters, use the appropriate flags: `--assume-role`, `--import-region`, `--use-implicit-auth`. | +| `--case-sensitive` | Toggle case sensitivity when comparing table and column names on the source and target. To disable case sensitivity, set `--case-sensitive=false`. If `=` is **not** included (e.g., `--case-sensitive false`), the flag is interpreted as `--case-sensitive` (i.e., `--case-sensitive=true`).

    **Default:** `false` | +| `--cleanup` | Whether to delete intermediate files after moving data using [cloud or local storage]({% link molt/molt-fetch.md %}#define-intermediate-storage). **Note:** Cleanup does not occur on [continuation]({% link molt/molt-fetch.md %}#continue-molt-fetch-after-interruption). | +| `--compression` | Compression method for data when using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#import-into-vs-copy-from) (`gzip`/`none`).

    **Default:** `gzip` | +| `--continuation-file-name` | Restart fetch at the specified filename if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation]({% link molt/molt-fetch.md %}#continue-molt-fetch-after-interruption). | +| `--continuation-token` | Restart fetch at a specific table, using the specified continuation token, if the task encounters an error. `--fetch-id` must be specified. For details, see [Fetch continuation]({% link molt/molt-fetch.md %}#continue-molt-fetch-after-interruption). | +| `--crdb-pts-duration` | The duration for which each timestamp used in data export from a CockroachDB source is protected from garbage collection. This ensures that the data snapshot remains consistent. For example, if set to `24h`, each timestamp is protected for 24 hours from the initiation of the export job. This duration is extended at regular intervals specified in `--crdb-pts-refresh-interval`.

    **Default:** `24h0m0s` | +| `--crdb-pts-refresh-interval` | The frequency at which the protected timestamp's validity is extended. This interval maintains protection of the data snapshot until data export from a CockroachDB source is completed. For example, if set to `10m`, the protected timestamp's expiration will be extended by the duration specified in `--crdb-pts-duration` (e.g., `24h`) every 10 minutes while export is not complete.

    **Default:** `10m0s` | +| `--direct-copy` | Enables [direct copy]({% link molt/molt-fetch.md %}#direct-copy), which copies data directly from source to target without using an intermediate store. | +| `--export-concurrency` | Number of shards to export at a time per table, each on a dedicated thread. This controls how many shards are created for each individual table during the [data export phase]({% link molt/molt-fetch.md %}#data-export-phase) and is distinct from `--table-concurrency`, which controls how many tables are processed simultaneously. The total number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`. Tables can be sharded with a range-based or stats-based mechanism. For details, refer to [Table sharding]({% link molt/molt-fetch.md %}#shard-tables-for-concurrent-export).

    **Default:** `4` | +| `--export-retry-max-attempts` | Maximum number of retry attempts for source export queries when connection failures occur. Only supported for PostgreSQL and CockroachDB sources.

    **Default:** `3` | +| `--export-retry-max-duration` | Maximum total duration for retrying source export queries. If `0`, no time limit is enforced. Only supported for PostgreSQL and CockroachDB sources.

    **Default:** `5m0s` | +| `--filter-path` | Path to a JSON file defining row-level filters for the [data import phase]({% link molt/molt-fetch.md %}#data-import-phase). Refer to [Selective data movement]({% link molt/molt-fetch.md %}#select-data-to-migrate). | +| `--fetch-id` | Restart fetch task corresponding to the specified ID. If `--continuation-file-name` or `--continuation-token` are not specified, fetch restarts for all failed tables. | +| `--flush-rows` | Number of rows before the source data is flushed to intermediate files. **Note:** If `--flush-size` is also specified, the fetch behavior is based on the flag whose criterion is met first. | +| `--flush-size` | Size (in bytes) before the source data is flushed to intermediate files. **Note:** If `--flush-rows` is also specified, the fetch behavior is based on the flag whose criterion is met first. | +| `--ignore-replication-check` | Skip querying for replication checkpoints such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle. This option is intended for use during bulk load migrations or when doing a one-time data export from a read replica. | +| `--import-batch-size` | The number of files to be imported at a time to the target database during the [data import phase]({% link molt/molt-fetch.md %}#data-import-phase). This applies only when using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#import-into-vs-copy-from) for data movement. **Note:** Increasing this value can improve the performance of full-scan queries on the target database shortly after fetch completes, but very high values are not recommended. If any individual file in the import batch fails, you must [retry]({% link molt/molt-fetch.md %}#continue-molt-fetch-after-interruption) the entire batch.

    **Default:** `1000` | +| `--import-region` | The region of the [cloud storage]({% link molt/molt-fetch.md %}#bucket-path) bucket. This applies only to [Amazon S3 buckets]({% link molt/molt-fetch.md %}#bucket-path). Set this flag only if you need to specify an `AWS_REGION` explicitly when using [`IMPORT INTO`]({% link molt/molt-fetch.md %}#import-into-vs-copy-from) for data movement. For example, `--import-region=ap-south-1`. | +| `--local-path` | The path within the [local file server]({% link molt/molt-fetch.md %}#local-path) where intermediate files are written (e.g., `data/migration/cockroach`). `--local-path-listen-addr` must be specified. | +| `--local-path-crdb-access-addr` | Address of a [local file server]({% link molt/molt-fetch.md %}#local-path) that is **publicly accessible**. This flag is only necessary if CockroachDB cannot reach the local address specified with `--local-path-listen-addr` (e.g., when moving data to a CockroachDB {{ site.data.products.cloud }} deployment). `--local-path` and `--local-path-listen-addr` must be specified.

    **Default:** Value of `--local-path-listen-addr`. | +| `--local-path-listen-addr` | Write intermediate files to a [local file server]({% link molt/molt-fetch.md %}#local-path) at the specified address (e.g., `'localhost:3000'`). `--local-path` must be specified. | +| `--log-file` | Write messages to the specified log filename. If no filename is provided, messages write to `fetch-{datetime}.log`. If `"stdout"` is provided, messages write to `stdout`. | +| `--logging` | Level at which to log messages (`trace`/`debug`/`info`/`warn`/`error`/`fatal`/`panic`).

    **Default:** `info` | +| `--metrics-listen-addr` | Address of the Prometheus metrics endpoint, which has the path `{address}/metrics`. For details on important metrics to monitor, refer to [Monitoring]({% link molt/molt-fetch-monitoring.md %}).

    **Default:** `'127.0.0.1:3030'` | +| `--mode` | Configure the MOLT Fetch behavior: `data-load`, `export-only`, or `import-only`. For details, refer to [Fetch mode]({% link molt/molt-fetch.md %}#define-fetch-mode).

    **Default:** `data-load` | +| `--non-interactive` | Run the fetch task without interactive prompts. This is recommended **only** when running `molt fetch` in an automated process (i.e., a job or continuous integration). | +| `--pprof-listen-addr` | Address of the pprof endpoint.

    **Default:** `'127.0.0.1:3031'` | +| `--row-batch-size` | Number of rows per shard to export at a time. For details on sharding, refer to [Table sharding]({% link molt/molt-fetch.md %}#shard-tables-for-concurrent-export). See also [Best practices]({% link molt/molt-fetch-best-practices.md %}).

    **Default:** `100000` | +| `--schema-filter` | Move schemas that match a specified [regular expression](https://wikipedia.org/wiki/Regular_expression).

    **Default:** `'.*'` | +| `--skip-pk-check` | Skip primary-key matching to allow data load when source or target tables have missing or mismatched primary keys. Disables sharding and bypasses `--export-concurrency` and `--row-batch-size` settings. Refer to [Skip primary key matching]({% link molt/molt-fetch.md %}#skip-primary-key-matching).

    **Default:** `false` | +| `--table-concurrency` | Number of tables to export at a time. The number of concurrent threads is the product of `--export-concurrency` and `--table-concurrency`.

    **Default:** `4` | +| `--table-exclusion-filter` | Exclude tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

    This value **cannot** be set to `'.*'`, which would cause every table to be excluded.

    **Default:** Empty string | +| `--table-filter` | Move tables that match a specified [POSIX regular expression](https://wikipedia.org/wiki/Regular_expression).

    **Default:** `'.*'` | +| `--table-handling` | How tables are initialized on the target database (`none`/`drop-on-target-and-recreate`/`truncate-if-exists`). For details, see [Target table handling]({% link molt/molt-fetch.md %}#handle-target-tables).

    **Default:** `none` | +| `--transformations-file` | Path to a JSON file that defines transformations to be performed on the target schema during the fetch task. Refer to [Transformations]({% link molt/molt-fetch.md %}#define-transformations). | +| `--type-map-file` | Path to a JSON file that contains explicit type mappings for automatic schema creation, when enabled with `--table-handling drop-on-target-and-recreate`. For details on the JSON format and valid type mappings, see [type mapping]({% link molt/molt-fetch.md %}#type-mapping). | +| `--use-console-writer` | Use the console writer, which has cleaner log output but introduces more latency.

    **Default:** `false` (log as structured JSON) | +| `--use-copy` | Use [`COPY FROM`]({% link molt/molt-fetch.md %}#import-into-vs-copy-from) to move data. This makes tables queryable during data load, but is slower than using `IMPORT INTO`. For details, refer to [Data movement]({% link molt/molt-fetch.md %}#import-into-vs-copy-from). | +| `--use-implicit-auth` | Use [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}) for [cloud storage]({% link molt/molt-fetch.md %}#bucket-path) URIs. | +| `--use-stats-based-sharding` | Enable statistics-based sharding for PostgreSQL sources. This allows sharding of tables with primary keys of any data type and can create more evenly distributed shards compared to the default numerical range sharding. Requires PostgreSQL 11+ and access to `pg_stats`. For details, refer to [Table sharding]({% link molt/molt-fetch.md %}#shard-tables-for-concurrent-export). | ### `tokens list` flags | Flag | Description | |-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------| -| `--conn-string` | (Required) Connection string for the target database. For details, see [List active continuation tokens]({% link molt/molt-fetch.md %}#list-active-continuation-tokens). | -| `-n`, `--num-results` | Number of results to return. | +| `--conn-string` | (Required) Connection string for the target database. For details, see [List active continuation tokens]({% link molt/molt-fetch.md %}#list-active-continuation-tokens). | +| `-n`, `--num-results` | Number of results to return. | ## See also diff --git a/src/current/molt/molt-fetch-installation.md b/src/current/molt/molt-fetch-installation.md index d8d416f70b5..fee592f94a5 100644 --- a/src/current/molt/molt-fetch-installation.md +++ b/src/current/molt/molt-fetch-installation.md @@ -17,7 +17,7 @@ The following source databases are supported: ### Database configuration -Ensure that the source and target schemas are identical, unless you enable automatic schema creation with the [`drop-on-target-and-recreate`]({% link molt/molt-fetch.md %}#target-table-handling) option. If you are creating the target schema manually, review the behaviors in [Mismatch handling]({% link molt/molt-fetch.md %}#mismatch-handling). +Ensure that the source and target schemas are identical, unless you enable automatic schema creation with the [`drop-on-target-and-recreate`]({% link molt/molt-fetch.md %}#handle-target-tables) option. If you are creating the target schema manually, review the behaviors in [Mismatch handling]({% link molt/molt-fetch.md %}#mismatch-handling). {{site.data.alerts.callout_info}} MOLT Fetch does not support migrating sequences. If your source database contains sequences, refer to the [guidance on indexing with sequential keys]({% link {{site.current_cloud_version}}/sql-faqs.md %}#how-do-i-generate-unique-slowly-increasing-sequential-numbers-in-cockroachdb). If a sequential key is necessary in your CockroachDB table, you must create it manually. After using MOLT Fetch to load the data onto the target, but before cutover, make sure to update each sequence's current value using [`setval()`]({% link {{site.current_cloud_version}}/functions-and-operators.md %}#sequence-functions) so that new inserts continue from the correct point. diff --git a/src/current/molt/molt-fetch-monitoring.md b/src/current/molt/molt-fetch-monitoring.md index 8adde477856..ab498e412b3 100644 --- a/src/current/molt/molt-fetch-monitoring.md +++ b/src/current/molt/molt-fetch-monitoring.md @@ -1,5 +1,5 @@ --- -title: MOLT Fetch Monitoring +title: MOLT Fetch Metrics summary: Learn how to monitor MOLT Fetch during data migration using Prometheus metrics. toc: true docs_area: migrate @@ -7,7 +7,7 @@ docs_area: migrate ## Metrics -By default, MOLT Fetch exports [Prometheus](https://prometheus.io/) metrics at `127.0.0.1:3030/metrics`. You can configure this endpoint with the `--metrics-listen-addr` [flag]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags). +By default, MOLT Fetch exports [Prometheus](https://prometheus.io/) metrics at `127.0.0.1:3030/metrics`. You can configure this endpoint with the [`--metrics-listen-addr`]({% link molt/molt-fetch-commands-and-flags.md %}#metrics-listen-addr) flag. Cockroach Labs recommends monitoring the following metrics: diff --git a/src/current/molt/molt-fetch.md b/src/current/molt/molt-fetch.md index 138d8c4b8f6..ed7c3497f15 100644 --- a/src/current/molt/molt-fetch.md +++ b/src/current/molt/molt-fetch.md @@ -7,43 +7,55 @@ docs_area: migrate MOLT Fetch moves data from a source database into CockroachDB as part of a [database migration]({% link molt/migration-overview.md %}). -MOLT Fetch uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to move the source data to cloud storage (Google Cloud Storage, Amazon S3, or Azure Blob Storage), a local file server, or local memory. Once the data is exported, MOLT Fetch loads the data into a target CockroachDB database. For details, refer to [Migration phases](#migration-phases). +MOLT Fetch uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to move the source data to cloud storage (Google Cloud Storage, Amazon S3, or Azure Blob Storage), a local file server, or local memory. Once the data is exported, MOLT Fetch loads the data into a target CockroachDB database. +- *Shard*: A portion of a table's data exported concurrently during the data export phase. Tables are divided into shards to enable parallel processing. For details, refer to [Table sharding](#shard-tables-for-concurrent-export). +- *Continuation token*: An identifier that marks the progress of a fetch task. Used to resume data loading from the point of interruption if a fetch task fails. For details, refer to [Fetch continuation](#continue-molt-fetch-after-interruption). +- *Intermediate files*: Temporary data files written to cloud storage or a local file server during the data export phase. These files are used to stage exported data before importing it into CockroachDB during the data import phase. For details, refer to [Data path](#define-intermediate-storage). --> -## Migration phases +## How it works -MOLT Fetch operates in distinct phases to move data from source databases to CockroachDB. For details on available modes, refer to [Fetch mode](#fetch-mode). +MOLT Fetch operates in two distinct phases to move data from the source databases to CockroachDB. The [data export phase](#data-export-phase) moves data to intermediate storage (either cloud storage or a local file server). The [data import phase](#data-import-phase) moves data from that intermediate storage to the CockroachDB cluster. For details on available modes, refer to [Define fetch mode](#define-fetch-mode). + +
    +MOLT Fetch flow draft +
    ### Data export phase -MOLT Fetch connects to the source database and exports table data to intermediate storage. Data is written to [cloud storage](#bucket-path) (Amazon S3, Google Cloud Storage, Azure Blob Storage), a [local file server](#local-path), or [directly to CockroachDB memory](#direct-copy). Multiple tables and table shards can be exported simultaneously using [`--table-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) and [`--export-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), with large tables divided into shards for parallel processing. For details, refer to: +In this first phase, MOLT Fetch connects to the source database and exports table data to intermediate storage. + +- [**Selective data movement**](#select-data-to-migrate): By default, MOLT Fetch moves all data from the --source database to CockroachDB. If instead you want to move a subset of the available data, use the [`--schema-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#schema-filter), [`--table-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#table-filter), and [`--filter-path`]({% link molt/molt-fetch-commands-and-flags.md %}#schema-filter) flags. -- [Fetch mode](#fetch-mode) -- [Table sharding](#table-sharding) +- [**Table sharding for concurrent export**](#shard-tables-for-concurrent-export): Multiple tables and **table shards** can be exported simultaneously using [`--table-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#table-concurrency) and [`--export-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#export-concurrency), with large tables divided into shards for parallel processing. + +- [**Load into intermediate storage**](#define-intermediate-storage): Define whether data is written to cloud storage (Amazon S3, Google Cloud Storage, Azure Blob Storage), a local file server, or directly to CockroachDB memory. Intermediate storage enables [continuation after a MOLT Fetch failure](#continue-molt-fetch-after-interruption) by storing **continuation tokens**. ### Data import phase -MOLT Fetch loads the exported data into the target CockroachDB database. The process uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) (faster, tables offline during import) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) (slower, tables remain queryable) to move data. Data files are imported in configurable batches using [`--import-batch-size`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), and target tables can be automatically created, truncated, or left unchanged based on [`--table-handling`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) settings. For details, refer to: +MOLT Fetch loads the exported data from intermediate storage to the target CockroachDB database. + +- [**`IMPORT INTO` vs. `COPY FROM`**](#import-into-vs-copy-from): This phase uses [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) (faster, tables offline during import) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) (slower, tables remain queryable) to move data. + +- [**Target table handling**](#handle-target-tables): Target tables can be automatically created, truncated, or left unchanged based on [`--table-handling`]({% link molt/molt-fetch-commands-and-flags.md %}#table-handling) settings. -- [Data movement](#data-load-mode) -- [Target table handling](#target-table-handling) +- [**Schema/table transformations**](#define-transformations): Use JSON to map computed columns from source to target, map partitioned tables to a single target table, rename tables on the target database, or rename database schemas. -## Usage +Refer to [the MOLT Fetch flags]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) to learn how to use any flag for the `molt fetch` command. -The following sections describe how to use the `molt fetch` [flags]({% link molt/molt-fetch-commands-and-flags.md %}). +## Run MOLT Fetch -### Source and target databases +The following section describes how to use the [`molt fetch`]({% link molt/molt-fetch-commands-and-flags.md %}#commands) command and how to set its main [flags]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags). + +### Specify source and target databases {{site.data.alerts.callout_success}} Follow the recommendations in [Connection security]({% link molt/molt-fetch-best-practices.md %}#connection-security). {{site.data.alerts.end}} -`--source` specifies the connection string of the source database. +[`--source`]({% link molt/molt-fetch-commands-and-flags.md %}#source) specifies the connection string of the source database. PostgreSQL or CockroachDB connection string: @@ -66,7 +78,7 @@ Oracle connection string: --source 'oracle://{username}:{password}@{host}:{port}/{service_name}' ~~~ -For Oracle Multitenant databases, `--source-cdb` specifies the container database (CDB) connection. `--source` specifies the pluggable database (PDB): +For Oracle Multitenant databases, [`--source-cdb`]({% link molt/molt-fetch-commands-and-flags.md %}#source-cdb) specifies the container database (CDB) connection. [`--source`]({% link molt/molt-fetch-commands-and-flags.md %}#source) specifies the pluggable database (PDB): {% include_cached copy-clipboard.html %} ~~~ @@ -74,16 +86,16 @@ For Oracle Multitenant databases, `--source-cdb` specifies the container databas --source-cdb 'oracle://{username}:{password}@{host}:{port}/{cdb_service_name}' ~~~ -`--target` specifies the [CockroachDB connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url): +[`--target`]({% link molt/molt-fetch-commands-and-flags.md %}#target) specifies the [CockroachDB connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url): {% include_cached copy-clipboard.html %} ~~~ --target 'postgresql://{username}:{password}@{host}:{port}/{database}' ~~~ -### Fetch mode +### Define fetch mode -`--mode` specifies the MOLT Fetch behavior. +[`--mode`]({% link molt/molt-fetch-commands-and-flags.md %}#mode) specifies the MOLT Fetch behavior. `data-load` (default) instructs MOLT Fetch to load the source data into CockroachDB: @@ -106,29 +118,108 @@ For Oracle Multitenant databases, `--source-cdb` specifies the container databas --mode import-only ~~~ -### Data load mode +### Select data to migrate -MOLT Fetch can use either [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to load data into CockroachDB. +By default, MOLT Fetch moves all data from the [`--source`]({% link molt/molt-fetch-commands-and-flags.md %}#source) database to CockroachDB. Use the following flags to move a subset of data. -By default, MOLT Fetch uses `IMPORT INTO`: +#### Schema and table selection -- `IMPORT INTO` achieves the highest throughput, but [requires taking the CockroachDB tables **offline**]({% link {{site.current_cloud_version}}/import-into.md %}#considerations) to achieve its import speed. Tables are taken back online once an [import job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs) completes successfully. See [Best practices]({% link molt/molt-fetch-best-practices.md %}). -- `IMPORT INTO` supports compression using the `--compression` flag, which reduces the amount of storage used. +[`--schema-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#schema-filter) specifies a range of schema objects to move to CockroachDB, formatted as a POSIX regex string. For example, to move every table in the source database's `migration_schema` schema: + +{% include_cached copy-clipboard.html %} +~~~ +--schema-filter 'migration_schema' +~~~ -`--use-copy` configures MOLT Fetch to use `COPY FROM`: +{{site.data.alerts.callout_info}} +[`--schema-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#schema-filter) does not apply to MySQL sources because MySQL tables belong directly to the database specified in the connection string, not to a separate schema. +{{site.data.alerts.end}} -- `COPY FROM` enables your tables to remain online and accessible. However, it is slower than using [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}). -- `COPY FROM` does not support compression. +[`--table-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#table-filter) and [`--table-exclusion-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#table-exclusion-filter) specify tables to include and exclude from the migration, respectively, formatted as POSIX regex strings. For example, to move every source table that has "user" in the table name and exclude every source table that has "temp" in the table name: + +{% include_cached copy-clipboard.html %} +~~~ +--table-filter '.*user.*' --table-exclusion-filter '.*temp.*' +~~~ + +#### Row-level filtering + +Use [`--filter-path`]({% link molt/molt-fetch-commands-and-flags.md %}#filter-path) to specify the path to a JSON file that defines row-level filtering for data load. This enables you to move a subset of data in a table, rather than all data in the table. To apply row-level filters during replication, use [MOLT Replicator]({% link molt/molt-replicator.md %}) with userscripts. + +{% include_cached copy-clipboard.html %} +~~~ +--filter-path 'data-filter.json' +~~~ + +The JSON file should contain one or more entries in `filters`, each with a `resource_specifier` (`schema` and `table`) and a SQL expression `expr`. For example, the following example exports only rows from `migration_schema.t1` where `v > 100`: + +~~~ json +{ + "filters": [ + { + "resource_specifier": { + "schema": "migration_schema", + "table": "t1" + }, + "expr": "v > 100" + } + ] +} +~~~ + +`expr` is case-sensitive and must be valid in your source dialect. For example, when using Oracle as the source, quote all identifiers and escape embedded quotes: + +~~~ json +{ + "filters": [ + { + "resource_specifier": { + "schema": "C##FETCHORACLEFILTERTEST", + "table": "FILTERTBL" + }, + "expr": "ABS(\"X\") > 10 AND CEIL(\"X\") < 100 AND FLOOR(\"X\") > 0 AND ROUND(\"X\", 2) < 100.00 AND TRUNC(\"X\", 0) > 0 AND MOD(\"X\", 2) = 0 AND FLOOR(\"X\" / 3) > 1" + } + ] +} +~~~ {{site.data.alerts.callout_info}} -`COPY FROM` is also used for [direct copy](#direct-copy). +If the expression references columns that are not indexed, MOLT Fetch will emit a warning like: `filter expression 'v > 100' contains column 'v' which is not indexed. This may lead to performance issues.` {{site.data.alerts.end}} -### Table sharding +{% comment %} +#### `--filter-path` userscript for replication + +To use `--filter-path` with replication, create and save a TypeScript userscript (e.g., `filter-script.ts`). The following script ensures that only rows where `v > 100` are replicated to `defaultdb.migration_schema.t1`: + +{% include_cached copy-clipboard.html %} +~~~ ts +import * as api from "replicator@v1"; +function disp(doc, meta) { + if (Number(doc.v) > 100) { + return { "defaultdb.migration_schema.t1" : [ doc ] }; + } +} +// Always put target schema. +api.configureSource("defaultdb.migration_schema", { + deletesTo: disp, + dispatch: disp, +}); +~~~ + +Apply the userscript with the `--userscript` replication flag: + +{% include_cached copy-clipboard.html %} +~~~ +--userscript 'filter-script.ts' +~~~ +{% endcomment %} + +### Shard tables for concurrent export During the [data export phase](#data-export-phase), MOLT Fetch can divide large tables into multiple shards for concurrent export. -To control the number of shards created per table, use the `--export-concurrency` flag. For example: +To control the number of shards created per table, use the [`--export-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#export-concurrency) flag. For example: {% include_cached copy-clipboard.html %} ~~~ @@ -143,7 +234,7 @@ Two sharding mechanisms are available: - **Range-based sharding (default):** Tables are divided based on numerical ranges found in primary key values. Only tables with [`INT`]({% link {{ site.current_cloud_version }}/int.md %}), [`FLOAT`]({% link {{ site.current_cloud_version }}/float.md %}), or [`UUID`]({% link {{ site.current_cloud_version }}/uuid.md %}) primary keys can use range-based sharding. Tables with other primary key data types export as a single shard. -- **Stats-based sharding (PostgreSQL only):** Enable with [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) for PostgreSQL 11+ sources. Tables are divided by analyzing the [`pg_stats`](https://www.postgresql.org/docs/current/view-pg-stats.htm) view to create more evenly distributed shards, up to a maximum of 200 shards. Primary keys of any data type are supported. +- **Stats-based sharding (PostgreSQL only):** Enable with [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#use-stats-based-sharding) for PostgreSQL 11+ sources. Tables are divided by analyzing the [`pg_stats`](https://www.postgresql.org/docs/current/view-pg-stats.htm) view to create more evenly distributed shards, up to a maximum of 200 shards. Primary keys of any data type are supported. Stats-based sharding requires that the user has `SELECT` permissions on source tables and on each table's `pg_stats` view. The latter permission is automatically granted to users that can read the table. @@ -165,7 +256,7 @@ Large tables may take time to analyze, but `ANALYZE` can run in the background. Migration without running `ANALYZE` will still work, but shard distribution may be less even. {{site.data.alerts.end}} -When using `--use-stats-based-sharding`, monitor the log output for each table you want to migrate. +When using [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#use-stats-based-sharding), monitor the log output for each table you want to migrate. If stats-based sharding is successful on a table, MOLT logs the following `INFO` message: @@ -179,25 +270,25 @@ If stats-based sharding fails on a table, MOLT logs the following `WARNING` mess Warning: failed to shard table {table_name} using stats based sharding: {reason_for_failure}, falling back to non stats based sharding ~~~ -The number of shards is dependent on the number of distinct values in the first primary key column of the table to be migrated. If this is different from the number of shards requested with `--export-concurrency`, MOLT logs the following `WARNING` and continues with the migration: +The number of shards is dependent on the number of distinct values in the first primary key column of the table to be migrated. If this is different from the number of shards requested with [`--export-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#export-concurrency), MOLT logs the following `WARNING` and continues with the migration: ~~~ number of shards formed: {num_shards_formed} is not equal to number of shards requested: {num_shards_requested} for table {table_name} ~~~ -Because stats-based sharding analyzes the entire table, running `--use-stats-based-sharding` with [`--filter-path`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) (refer to [Selective data movement](#selective-data-movement)) will cause imbalanced shards to form. +Because stats-based sharding analyzes the entire table, running [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#use-stats-based-sharding) with [`--filter-path`]({% link molt/molt-fetch-commands-and-flags.md %}#filter-path) (refer to [Selective data movement](#select-data-to-migrate)) will cause imbalanced shards to form. -### Data path +### Define intermediate storage MOLT Fetch can move the source data to CockroachDB via [cloud storage](#bucket-path), a [local file server](#local-path), or [directly](#direct-copy) without an intermediate store. #### Bucket path {{site.data.alerts.callout_success}} -Only the path specified in `--bucket-path` is used. Query parameters, such as credentials, are ignored. To authenticate cloud storage, follow the steps in [Secure cloud storage]({% link molt/molt-fetch-best-practices.md %}#cloud-storage-security). +Only the path specified in [`--bucket-path`]({% link molt/molt-fetch-commands-and-flags.md %}#bucket-path) is used. Query parameters, such as credentials, are ignored. To authenticate cloud storage, follow the steps in [Secure cloud storage]({% link molt/molt-fetch-best-practices.md %}#cloud-storage-security). {{site.data.alerts.end}} -`--bucket-path` instructs MOLT Fetch to write intermediate files to a path within [Google Cloud Storage](https://cloud.google.com/storage/docs/buckets), [Amazon S3](https://aws.amazon.com/s3/), or [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) to which you have the necessary permissions. Use additional [flags]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), shown in the following examples, to specify authentication or region parameters as required for bucket access. +[`--bucket-path`]({% link molt/molt-fetch-commands-and-flags.md %}#bucket-path) instructs MOLT Fetch to write intermediate files to a path within [Google Cloud Storage](https://cloud.google.com/storage/docs/buckets), [Amazon S3](https://aws.amazon.com/s3/), or [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs) to which you have the necessary permissions. Use additional [flags]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), shown in the following examples, to specify authentication or region parameters as required for bucket access. Connect to a Google Cloud Storage bucket with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#google-cloud-storage-implicit) and [assume role]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}#set-up-google-cloud-storage-assume-role): @@ -217,7 +308,7 @@ Connect to an Amazon S3 bucket and explicitly specify the `ap_south-1` region: ~~~ {{site.data.alerts.callout_info}} -When `--import-region` is set, `IMPORT INTO` must be used for [data movement](#data-load-mode). +When [`--import-region`]({% link molt/molt-fetch-commands-and-flags.md %}#import-region) is set, `IMPORT INTO` must be used for [data movement](#import-into-vs-copy-from). {{site.data.alerts.end}} Connect to an Azure Blob Storage container with [implicit authentication]({% link {{ site.current_cloud_version }}/cloud-storage-authentication.md %}?filters=azure#azure-blob-storage-implicit-authentication): @@ -230,7 +321,7 @@ Connect to an Azure Blob Storage container with [implicit authentication]({% lin #### Local path -`--local-path` instructs MOLT Fetch to write intermediate files to a path within a [local file server]({% link {{site.current_cloud_version}}/use-a-local-file-server.md %}). `local-path-listen-addr` specifies the address of the local file server. For example: +[`--local-path`]({% link molt/molt-fetch-commands-and-flags.md %}#local-path) instructs MOLT Fetch to write intermediate files to a path within a [local file server]({% link {{site.current_cloud_version}}/use-a-local-file-server.md %}). [`--local-path-listen-addr`]({% link molt/molt-fetch-commands-and-flags.md %}#local-path-listen-addr) specifies the address of the local file server. For example: {% include_cached copy-clipboard.html %} ~~~ @@ -238,9 +329,9 @@ Connect to an Azure Blob Storage container with [implicit authentication]({% lin --local-path-listen-addr 'localhost:3000' ~~~ -In some cases, CockroachDB will not be able to use the local address specified by `--local-path-listen-addr`. This will depend on where CockroachDB is deployed, the runtime OS, and the source dialect. +In some cases, CockroachDB will not be able to use the local address specified by [`--local-path-listen-addr`]({% link molt/molt-fetch-commands-and-flags.md %}#local-path-listen-addr). This will depend on where CockroachDB is deployed, the runtime OS, and the source dialect. -For example, if you are migrating to CockroachDB {{ site.data.products.cloud }}, such that the {{ site.data.products.cloud }} cluster is in a different physical location than the machine running `molt fetch`, then CockroachDB cannot reach an address such as `localhost:3000`. In these situations, use `--local-path-crdb-access-addr` to specify an address for the local file server that is **publicly accessible**. For example: +For example, if you are migrating to CockroachDB {{ site.data.products.cloud }}, such that the {{ site.data.products.cloud }} cluster is in a different physical location than the machine running `molt fetch`, then CockroachDB cannot reach an address such as `localhost:3000`. In these situations, use [`--local-path-crdb-access-addr`]({% link molt/molt-fetch-commands-and-flags.md %}#local-path-crdb-access-addr) to specify an address for the local file server that is **publicly accessible**. For example: {% include_cached copy-clipboard.html %} ~~~ @@ -255,115 +346,38 @@ For example, if you are migrating to CockroachDB {{ site.data.products.cloud }}, #### Direct copy -`--direct-copy` specifies that MOLT Fetch should use `COPY FROM` to move the source data directly to CockroachDB without an intermediate store: +[`--direct-copy`]({% link molt/molt-fetch-commands-and-flags.md %}#direct-copy) specifies that MOLT Fetch should use `COPY FROM` to move the source data directly to CockroachDB without an intermediate store: -- Because the data is held in memory, the machine must have sufficient RAM for the data currently in flight: +- Because the data is held in memory, the machine must have sufficient RAM for the data currently in flight: ~~~ average size of each row * --row-batch-size * --export-concurrency * --table-concurrency ~~~ -- Direct copy does not support compression or [continuation](#fetch-continuation). -- The [`--use-copy`](#data-load-mode) flag is redundant with `--direct-copy`. - -### Schema and table selection - -By default, MOLT Fetch moves all data from the [`--source`](#source-and-target-databases) database to CockroachDB. Use the following flags to move a subset of data. - -`--schema-filter` specifies a range of schema objects to move to CockroachDB, formatted as a POSIX regex string. For example, to move every table in the source database's `migration_schema` schema: - -{% include_cached copy-clipboard.html %} -~~~ ---schema-filter 'migration_schema' -~~~ - -{{site.data.alerts.callout_info}} -`--schema-filter` does not apply to MySQL sources because MySQL tables belong directly to the database specified in the connection string, not to a separate schema. -{{site.data.alerts.end}} - -`--table-filter` and `--table-exclusion-filter` specify tables to include and exclude from the migration, respectively, formatted as POSIX regex strings. For example, to move every source table that has "user" in the table name and exclude every source table that has "temp" in the table name: - -{% include_cached copy-clipboard.html %} -~~~ ---table-filter '.*user.*' --table-exclusion-filter '.*temp.*' -~~~ - -### Selective data movement +- Direct copy does not support compression or [continuation](#continue-molt-fetch-after-interruption). +- The [`--use-copy`](#import-into-vs-copy-from) flag is redundant with [`--direct-copy`]({% link molt/molt-fetch-commands-and-flags.md %}#direct-copy). -Use `--filter-path` to specify the path to a JSON file that defines row-level filtering for data load. This enables you to move a subset of data in a table, rather than all data in the table. To apply row-level filters during replication, use [MOLT Replicator]({% link molt/molt-replicator.md %}) with userscripts. +### `IMPORT INTO` vs. `COPY FROM` -{% include_cached copy-clipboard.html %} -~~~ ---filter-path 'data-filter.json' -~~~ +MOLT Fetch can use either [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}) or [`COPY FROM`]({% link {{site.current_cloud_version}}/copy.md %}) to load data into CockroachDB. -The JSON file should contain one or more entries in `filters`, each with a `resource_specifier` (`schema` and `table`) and a SQL expression `expr`. For example, the following example exports only rows from `migration_schema.t1` where `v > 100`: +By default, MOLT Fetch uses `IMPORT INTO`: -~~~ json -{ - "filters": [ - { - "resource_specifier": { - "schema": "migration_schema", - "table": "t1" - }, - "expr": "v > 100" - } - ] -} -~~~ +- `IMPORT INTO` achieves the highest throughput, but [requires taking the CockroachDB tables **offline**]({% link {{site.current_cloud_version}}/import-into.md %}#considerations) to achieve its import speed. Tables are taken back online once an [import job]({% link {{site.current_cloud_version}}/import-into.md %}#view-and-control-import-jobs) completes successfully. See [Best practices]({% link molt/molt-fetch-best-practices.md %}). +- `IMPORT INTO` supports compression using the [`--compression`]({% link molt/molt-fetch-commands-and-flags.md %}#compression) flag, which reduces the amount of storage used. -`expr` is case-sensitive and must be valid in your source dialect. For example, when using Oracle as the source, quote all identifiers and escape embedded quotes: +[`--use-copy`]({% link molt/molt-fetch-commands-and-flags.md %}#use-copy) configures MOLT Fetch to use `COPY FROM`: -~~~ json -{ - "filters": [ - { - "resource_specifier": { - "schema": "C##FETCHORACLEFILTERTEST", - "table": "FILTERTBL" - }, - "expr": "ABS(\"X\") > 10 AND CEIL(\"X\") < 100 AND FLOOR(\"X\") > 0 AND ROUND(\"X\", 2) < 100.00 AND TRUNC(\"X\", 0) > 0 AND MOD(\"X\", 2) = 0 AND FLOOR(\"X\" / 3) > 1" - } - ] -} -~~~ +- `COPY FROM` enables your tables to remain online and accessible. However, it is slower than using [`IMPORT INTO`]({% link {{site.current_cloud_version}}/import-into.md %}). +- `COPY FROM` does not support compression. {{site.data.alerts.callout_info}} -If the expression references columns that are not indexed, MOLT Fetch will emit a warning like: `filter expression ‘v > 100' contains column ‘v' which is not indexed. This may lead to performance issues.` +`COPY FROM` is also used for [direct copy](#direct-copy). {{site.data.alerts.end}} -{% comment %} -#### `--filter-path` userscript for replication - -To use `--filter-path` with replication, create and save a TypeScript userscript (e.g., `filter-script.ts`). The following script ensures that only rows where `v > 100` are replicated to `defaultdb.migration_schema.t1`: - -{% include_cached copy-clipboard.html %} -~~~ ts -import * as api from "replicator@v1"; -function disp(doc, meta) { - if (Number(doc.v) > 100) { - return { "defaultdb.migration_schema.t1" : [ doc ] }; - } -} -// Always put target schema. -api.configureSource("defaultdb.migration_schema", { - deletesTo: disp, - dispatch: disp, -}); -~~~ - -Apply the userscript with the `--userscript` replication flag: +### Handle target tables -{% include_cached copy-clipboard.html %} -~~~ ---userscript 'filter-script.ts' -~~~ -{% endcomment %} - -### Target table handling - -`--table-handling` defines how MOLT Fetch loads data on the CockroachDB tables that [match the selection](#schema-and-table-selection). +[`--table-handling`]({% link molt/molt-fetch-commands-and-flags.md %}#table-handling) defines how MOLT Fetch loads data on the CockroachDB tables that [match the selection](#schema-and-table-selection). To load the data without changing the existing data in the tables, use `none`: @@ -390,21 +404,21 @@ When using the `drop-on-target-and-recreate` option, MOLT Fetch creates a new Co #### Mismatch handling -If either [`none`](#target-table-handling) or [`truncate-if-exists`](#target-table-handling) is set, `molt fetch` loads data into the existing tables on the target CockroachDB database. If the target schema mismatches the source schema, `molt fetch` will exit early in certain cases, and will need to be re-run from the beginning. For details, refer to [Fetch exits early due to mismatches]({% link molt/molt-fetch-troubleshooting.md %}#fetch-exits-early-due-to-mismatches). +If either [`none`](#handle-target-tables) or [`truncate-if-exists`](#handle-target-tables) is set, `molt fetch` loads data into the existing tables on the target CockroachDB database. If the target schema mismatches the source schema, `molt fetch` will exit early in certain cases, and will need to be re-run from the beginning. For details, refer to [Fetch exits early due to mismatches]({% link molt/molt-fetch-troubleshooting.md %}#fetch-exits-early-due-to-mismatches). {{site.data.alerts.callout_info}} -This does not apply when [`drop-on-target-and-recreate`](#target-table-handling) is specified, since this option automatically creates a compatible CockroachDB schema. +This does not apply when [`drop-on-target-and-recreate`](#handle-target-tables) is specified, since this option automatically creates a compatible CockroachDB schema. {{site.data.alerts.end}} #### Skip primary key matching -`--skip-pk-check` removes the [requirement that source and target tables share matching primary keys]({% link molt/molt-fetch-troubleshooting.md %}#fetch-exits-early-due-to-mismatches) for data load. When this flag is set: +[`--skip-pk-check`]({% link molt/molt-fetch-commands-and-flags.md %}#skip-pk-check) removes the [requirement that source and target tables share matching primary keys]({% link molt/molt-fetch-troubleshooting.md %}#fetch-exits-early-due-to-mismatches) for data load. When this flag is set: - The data load proceeds even if the source or target table lacks a primary key, or if their primary key columns do not match. -- [Table sharding](#table-sharding) is disabled. Each table is exported in a single batch within one shard, bypassing `--export-concurrency` and `--row-batch-size`. As a result, memory usage and execution time may increase due to full table scans. +- [Table sharding](#shard-tables-for-concurrent-export) is disabled. Each table is exported in a single batch within one shard, bypassing [`--export-concurrency`]({% link molt/molt-fetch-commands-and-flags.md %}#export-concurrency) and [`--row-batch-size`]({% link molt/molt-fetch-commands-and-flags.md %}#row-batch-size). As a result, memory usage and execution time may increase due to full table scans. - If the source table contains duplicate rows but the target has [`PRIMARY KEY`]({% link {{ site.current_cloud_version }}/primary-key.md %}) or [`UNIQUE`]({% link {{ site.current_cloud_version }}/unique.md %}) constraints, duplicate rows are deduplicated during import. -When `--skip-pk-check` is set, all tables are treated as if they lack a primary key, and are thus exported in a single unsharded batch. To avoid performance issues, use this flag with `--table-filter` to target only tables **without** a primary key. +When [`--skip-pk-check`]({% link molt/molt-fetch-commands-and-flags.md %}#skip-pk-check) is set, all tables are treated as if they lack a primary key, and are thus exported in a single unsharded batch. To avoid performance issues, use this flag with [`--table-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#table-filter) to target only tables **without** a primary key. For example: @@ -416,7 +430,7 @@ molt fetch \ --skip-pk-check ~~~ -Example log output when `--skip-pk-check` is enabled: +Example log output when [`--skip-pk-check`]({% link molt/molt-fetch-commands-and-flags.md %}#skip-pk-check) is enabled: ~~~json {"level":"info","message":"sharding is skipped for table public.nopktbl - flag skip-pk-check is specified and thus no PK for source table is specified"} @@ -424,65 +438,9 @@ Example log output when `--skip-pk-check` is enabled: #### Type mapping -If [`drop-on-target-and-recreate`](#target-table-handling) is set, MOLT Fetch automatically creates a CockroachDB schema that is compatible with the source data. The column types are determined as follows: - -- PostgreSQL types are mapped to existing CockroachDB [types]({% link {{site.current_cloud_version}}/data-types.md %}) that have the same [`OID`]({% link {{site.current_cloud_version}}/oid.md %}). -- The following MySQL types are mapped to corresponding CockroachDB types: - - | MySQL type | CockroachDB type | Notes | - |-----------------------------------------------------|-------------------------------------------------------------------------------------------|--------------------------------------------------------------| - | `CHAR`, `CHARACTER`, `VARCHAR`, `NCHAR`, `NVARCHAR` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | - | `TINYTEXT`, `TEXT`, `MEDIUMTEXT`, `LONGTEXT` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | - | `GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | - | `LINESTRING` | [`LINESTRING`]({% link {{site.current_cloud_version}}/linestring.md %}) | Spatial type (PostGIS-style) | - | `POINT` | [`POINT`]({% link {{site.current_cloud_version}}/point.md %}) | Spatial type (PostGIS-style) | - | `POLYGON` | [`POLYGON`]({% link {{site.current_cloud_version}}/polygon.md %}) | Spatial type (PostGIS-style) | - | `MULTIPOINT` | [`MULTIPOINT`]({% link {{site.current_cloud_version}}/multipoint.md %}) | Spatial type (PostGIS-style) | - | `MULTILINESTRING` | [`MULTILINESTRING`]({% link {{site.current_cloud_version}}/multilinestring.md %}) | Spatial type (PostGIS-style) | - | `MULTIPOLYGON` | [`MULTIPOLYGON`]({% link {{site.current_cloud_version}}/multipolygon.md %}) | Spatial type (PostGIS-style) | - | `GEOMETRYCOLLECTION`, `GEOMCOLLECTION` | [`GEOMETRYCOLLECTION`]({% link {{site.current_cloud_version}}/geometrycollection.md %}) | Spatial type (PostGIS-style) | - | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | - | `TINYINT`, `INT1` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | - | `BLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `SMALLINT`, `INT2` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | - | `MEDIUMINT`, `INT`, `INTEGER`, `INT4` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | - | `BIGINT`, `INT8` | [`INT`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | - | `FLOAT` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | - | `DOUBLE` | [`FLOAT`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | - | `DECIMAL`, `NUMERIC`, `REAL` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | - | `BINARY`, `VARBINARY` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `DATETIME` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time (no time zone) | - | `TIMESTAMP` | [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time with time zone | - | `TIME` | [`TIME`]({% link {{site.current_cloud_version}}/time.md %}) | Time of day (no date) | - | `BIT` | [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) | Variable-length bit array | - | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | - | `TINYBLOB`, `MEDIUMBLOB`, `LONGBLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `BOOL`, `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | - -- The following Oracle types are mapped to CockroachDB types: - - | Oracle type(s) | CockroachDB type | Notes | - |---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| - | `NCHAR`, `CHAR`, `CHARACTER` | [`CHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`CHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Fixed-length character; falls back to unbounded if length not specified | - | `VARCHAR`, `VARCHAR2`, `NVARCHAR2` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | - | `STRING` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | - | `SMALLINT` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | - | `INTEGER`, `INT`, `SIMPLE_INTEGER` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | - | `LONG` | [`INT8`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | - | `FLOAT`, `BINARY_FLOAT`, `REAL` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | - | `DOUBLE`, `BINARY_DOUBLE` | [`FLOAT8`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | - | `DEC`, `NUMBER`, `DECIMAL`, `NUMERIC` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %})(p, s) or [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | - | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | - | `BLOB`, `RAW`, `LONG RAW` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | - | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | - | `CLOB`, `NCLOB` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as large text | - | `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | - | `TIMESTAMP` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) or [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | If `WITH TIME ZONE` → `TIMESTAMPTZ`, else `TIMESTAMP` | - | `ROWID`, `UROWID` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as opaque identifier | - | `SDO_GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | - | `XMLTYPE` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Stored as text | - -- To override the default mappings for automatic schema creation, you can map source to target CockroachDB types explicitly. These are defined in the JSON file indicated by the `--type-map-file` flag. The allowable custom mappings are valid CockroachDB aliases, casts, and the following mappings specific to MOLT Fetch and [Verify]({% link molt/molt-verify.md %}): +If [`drop-on-target-and-recreate`](#handle-target-tables) is set, MOLT Fetch automatically creates a CockroachDB schema that is compatible with the source data. The column types are determined by [MOLT's default type mappings]({% link molt/molt-type-mapping.md %}). + +- To override the default mappings for automatic schema creation, you can map source to target CockroachDB types explicitly. These are defined in the JSON file indicated by the [`--type-map-file`]({% link molt/molt-fetch-commands-and-flags.md %}#type-map-file) flag. The allowable custom mappings are valid CockroachDB aliases, casts, and the following mappings specific to MOLT Fetch and [Verify]({% link molt/molt-verify.md %}): - [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) <> [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) - [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) <> [`UUID`]({% link {{site.current_cloud_version}}/uuid.md %}) @@ -492,7 +450,7 @@ If [`drop-on-target-and-recreate`](#target-table-handling) is set, MOLT Fetch au - [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) - [`INET`]({% link {{site.current_cloud_version}}/inet.md %}) <> [`TEXT`]({% link {{site.current_cloud_version}}/string.md %}) -`--type-map-file` specifies the path to the JSON file containing the explicit type mappings. For example: +[`--type-map-file`]({% link molt/molt-fetch-commands-and-flags.md %}#type-map-file) specifies the path to the JSON file containing the explicit type mappings. For example: {% include_cached copy-clipboard.html %} ~~~ @@ -526,7 +484,7 @@ The following JSON example defines two type mappings: - `source_type` specifies the source type to be mapped. - `crdb_type` specifies the target CockroachDB [type]({% link {{ site.current_cloud_version }}/data-types.md %}) to be mapped. -### Transformations +### Define transformations You can define transformation rules to be performed on the target database during the fetch task. These can be used to: @@ -535,7 +493,7 @@ You can define transformation rules to be performed on the target database durin - Rename tables on the target database. - Rename database schemas. -Transformation rules are defined in the JSON file indicated by the `--transformations-file` flag. For example: +Transformation rules are defined in the JSON file indicated by the [`--transformations-file`]({% link molt/molt-fetch-commands-and-flags.md %}#transformations-file) flag. For example: {% include_cached copy-clipboard.html %} ~~~ @@ -621,8 +579,8 @@ The following JSON example defines three transformation rules: rule `1` [maps co For n-to-1 mappings: - - Use [`--use-copy`](#data-load-mode) or [`--direct-copy`](#direct-copy) for data movement. - - Manually create the target table. Do not use [`--table-handling drop-on-target-and-recreate`](#target-table-handling). + - Use [`--use-copy`](#import-into-vs-copy-from) or [`--direct-copy`](#direct-copy) for data movement. + - Manually create the target table. Do not use [`--table-handling drop-on-target-and-recreate`](#handle-target-tables). [Example rule `2`](#transformation-rules-example) maps all table names with prefix `charges_part` to a single `charges` table on CockroachDB (an n-to-1 mapping). This assumes that all matching `charges_part.*` tables have the same table definition: @@ -667,7 +625,7 @@ Each rule is applied in the order it is defined. If two rules overlap, the later To verify that the logging shows that the computed columns are being created: -When running `molt fetch`, set `--logging debug` and look for `ALTER TABLE ... ADD COLUMN` statements with the `STORED` or `VIRTUAL` keywords in the log output: +When running `molt fetch`, set [`--logging`]({% link molt/molt-fetch-commands-and-flags.md %}#logging) `debug` and look for `ALTER TABLE ... ADD COLUMN` statements with the `STORED` or `VIRTUAL` keywords in the log output: ~~~ json {"level":"debug","time":"2024-07-22T12:01:51-04:00","message":"running: ALTER TABLE IF EXISTS public.computed ADD COLUMN computed_col INT8 NOT NULL AS ((col1 + col2)) STORED"} @@ -689,7 +647,7 @@ SHOW CREATE TABLE computed; | ) ~~~ -### Fetch continuation +## Continue MOLT Fetch after interruption If MOLT Fetch fails while loading data into CockroachDB from intermediate files, it exits with an error message, fetch ID, and [continuation token](#list-active-continuation-tokens) for each table that failed to load on the target database. You can use this information to continue the task from the *continuation point* where it was interrupted. @@ -702,14 +660,14 @@ Continuation is only possible under the following conditions: Only one fetch ID and set of continuation tokens, each token corresponding to a table, are active at any time. See [List active continuation tokens](#list-active-continuation-tokens). {{site.data.alerts.end}} -To retry all data starting from the continuation point, reissue the `molt fetch` command and include the `--fetch-id`. +To retry all data starting from the continuation point, reissue the `molt fetch` command and include the [`--fetch-id`]({% link molt/molt-fetch-commands-and-flags.md %}#fetch-id). {% include_cached copy-clipboard.html %} ~~~ --fetch-id d44762e5-6f70-43f8-8e15-58b4de10a007 ~~~ -To retry a specific table that failed, include both `--fetch-id` and `--continuation-token`. The latter flag specifies a token string that corresponds to a specific table on the source database. A continuation token is written in the `molt fetch` output for each failed table. If the fetch task encounters a subsequent error, it generates a new token for each failed table. See [List active continuation tokens](#list-active-continuation-tokens). +To retry a specific table that failed, include both [`--fetch-id`]({% link molt/molt-fetch-commands-and-flags.md %}#fetch-id) and [`--continuation-token`]({% link molt/molt-fetch-commands-and-flags.md %}#continuation-token). The latter flag specifies a token string that corresponds to a specific table on the source database. A continuation token is written in the `molt fetch` output for each failed table. If the fetch task encounters a subsequent error, it generates a new token for each failed table. See [List active continuation tokens](#list-active-continuation-tokens). {{site.data.alerts.callout_info}} This will retry only the table that corresponds to the continuation token. If the fetch task succeeds, there may still be source data that is not yet loaded into CockroachDB. @@ -721,7 +679,7 @@ This will retry only the table that corresponds to the continuation token. If th --continuation-token 011762e5-6f70-43f8-8e15-58b4de10a007 ~~~ -To retry all data starting from a specific file, include both `--fetch-id` and `--continuation-file-name`. The latter flag specifies the filename of an intermediate file in [cloud or local storage](#data-path). All filenames are prepended with `part_` and have the `.csv.gz` or `.csv` extension, depending on compression type (gzip by default). For example: +To retry all data starting from a specific file, include both [`--fetch-id`]({% link molt/molt-fetch-commands-and-flags.md %}#fetch-id) and [`--continuation-file-name`]({% link molt/molt-fetch-commands-and-flags.md %}#continuation-file-name). The latter flag specifies the filename of an intermediate file in [cloud or local storage](#define-intermediate-storage). All filenames are prepended with `part_` and have the `.csv.gz` or `.csv` extension, depending on compression type (gzip by default). For example: {% include_cached copy-clipboard.html %} ~~~ @@ -733,9 +691,9 @@ To retry all data starting from a specific file, include both `--fetch-id` and ` Continuation is not possible when using [direct copy](#direct-copy). {{site.data.alerts.end}} -#### List active continuation tokens +### List active continuation tokens -To view all active continuation tokens, issue a `molt fetch tokens list` command along with `--conn-string`, which specifies the [connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url) for the target CockroachDB database. For example: +To view all active continuation tokens, issue a `molt fetch tokens list` command along with [`--conn-string`]({% link molt/molt-fetch-commands-and-flags.md %}#conn-string), which specifies the [connection string]({% link {{site.current_cloud_version}}/connection-parameters.md %}#connect-using-a-url) for the target CockroachDB database. For example: {% include_cached copy-clipboard.html %} ~~~ shell @@ -752,9 +710,9 @@ molt fetch tokens list \ Continuation Tokens. ~~~ -### CDC cursor +## Enable replication -A change data capture (CDC) cursor is written to the output as `cdc_cursor` at the beginning and end of the fetch task. +A change data capture (CDC) cursor is written to the MOLT Fetch output as `cdc_cursor` at the beginning and end of the fetch task. For MySQL: @@ -784,7 +742,7 @@ When migrating data to CockroachDB in a bulk load (without utilizing [continuous
  • -Specify the source and target database connections. For connection string formats, refer to [Source and target databases](#source-and-target-databases). +Specify the source and target database connections. For connection string formats, refer to [Source and target databases](#specify-source-and-target-databases).
    {% include_cached copy-clipboard.html %} @@ -795,7 +753,7 @@ Specify the source and target database connections. For connection string format
    -For Oracle Multitenant (CDB/PDB) sources, also include `--source-cdb` to specify the container database (CDB) connection string. +For Oracle Multitenant (CDB/PDB) sources, also include [`--source-cdb`]({% link molt/molt-fetch-commands-and-flags.md %}#source-cdb) to specify the container database (CDB) connection string. {% include_cached copy-clipboard.html %} ~~~ @@ -838,7 +796,7 @@ Optionally, filter the source data to migrate. By default, all schemas and table
    -For Oracle sources, `--schema-filter` is case-insensitive. You can use either lowercase or uppercase: +For Oracle sources, [`--schema-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#schema-filter) is case-insensitive. You can use either lowercase or uppercase: {% include_cached copy-clipboard.html %} ~~~ @@ -848,7 +806,7 @@ For Oracle sources, `--schema-filter` is case-insensitive. You can use either lo
    -For MySQL sources, omit `--schema-filter` because MySQL tables belong directly to the database specified in the connection string, not to a separate schema. If needed, use `--table-filter` to select specific tables: +For MySQL sources, omit [`--schema-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#schema-filter) because MySQL tables belong directly to the database specified in the connection string, not to a separate schema. If needed, use [`--table-filter`]({% link molt/molt-fetch-commands-and-flags.md %}#table-filter) to select specific tables: {% include_cached copy-clipboard.html %} ~~~ @@ -856,14 +814,14 @@ For MySQL sources, omit `--schema-filter` because MySQL tables belong directly t ~~~
    -Specify how to handle target tables. By default, `--table-handling` is set to `none`, which loads data without changing existing data in the tables. For details, refer to [Target table handling](#target-table-handling): +Specify how to handle target tables. By default, [`--table-handling`]({% link molt/molt-fetch-commands-and-flags.md %}#table-handling) is set to `none`, which loads data without changing existing data in the tables. For details, refer to [Target table handling](#handle-target-tables): {% include_cached copy-clipboard.html %} ~~~ --table-handling truncate-if-exists ~~~ -When performing a bulk load without subsequent replication, use `--ignore-replication-check` to skip querying for replication checkpoints (such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle). This is appropriate when: +When performing a bulk load without subsequent replication, use [`--ignore-replication-check`]({% link molt/molt-fetch-commands-and-flags.md %}#ignore-replication-check) to skip querying for replication checkpoints (such as `pg_current_wal_insert_lsn()` on PostgreSQL, `gtid_executed` on MySQL, and `CURRENT_SCN` on Oracle). This is appropriate when: - Performing a one-time data migration with no plan to replicate ongoing changes. - Exporting data from a read replica where replication checkpoints are unavailable. @@ -873,7 +831,7 @@ When performing a bulk load without subsequent replication, use `--ignore-replic --ignore-replication-check ~~~ -At minimum, the `molt fetch` command should include the source, target, data path, and `--ignore-replication-check` flags: +At minimum, the `molt fetch` command should include the source, target, data path, and [`--ignore-replication-check`]({% link molt/molt-fetch-commands-and-flags.md %}#ignore-replication-check) flags: {% include_cached copy-clipboard.html %} ~~~ shell @@ -893,7 +851,7 @@ For detailed walkthroughs of migrations that use `molt fetch` in this way, refer ### Initial bulk load (before replication) -In a migration that utilizes [continuous replication]({% link molt/migration-considerations-replication.md %}), perform an initial data load before [setting up ongoing replication with MOLT Replicator]({% link molt/molt-replicator.md %}#forward-replication-after-initial-load). Run the `molt fetch` command without `--ignore-replication-check`, as shown below: +In a migration that utilizes [continuous replication]({% link molt/migration-considerations-replication.md %}), perform an initial data load before [setting up ongoing replication with MOLT Replicator]({% link molt/molt-replicator.md %}#forward-replication-after-initial-load). Run the `molt fetch` command without [`--ignore-replication-check`]({% link molt/molt-fetch-commands-and-flags.md %}#ignore-replication-check), as shown below:
    @@ -903,11 +861,11 @@ In a migration that utilizes [continuous replication]({% link molt/migration-co The workflow is the same as [Bulk data load](#bulk-data-load), except: -- Exclude `--ignore-replication-check`. MOLT Fetch will query and record replication checkpoints. +- Exclude [`--ignore-replication-check`]({% link molt/molt-fetch-commands-and-flags.md %}#ignore-replication-check). MOLT Fetch will query and record replication checkpoints.
    - You must include `--pglogical-replication-slot-name` and `--pglogical-publication-and-slot-drop-and-recreate` to automatically create the publication and replication slot during the data load.
    -- After the data load completes, check the [CDC cursor](#cdc-cursor) in the output for the checkpoint value to use with MOLT Replicator. +- After the data load completes, check the [CDC cursor](#enable-replication) in the output for the checkpoint value to use with MOLT Replicator. At minimum, the `molt fetch` command should include the source, target, and data path flags: @@ -964,7 +922,7 @@ For detailed walkthroughs of migrations that use `molt fetch` in this way, refer - [MOLT Fetch Installation]({% link molt/molt-fetch-installation.md %}) - [MOLT Fetch Commands and Flags]({% link molt/molt-fetch-commands-and-flags.md %}) -- [MOLT Fetch Monitoring]({% link molt/molt-fetch-monitoring.md %}) +- [MOLT Fetch Metrics]({% link molt/molt-fetch-monitoring.md %}) - [MOLT Fetch Best Practices]({% link molt/molt-fetch-best-practices.md %}) - [MOLT Fetch Troubleshooting]({% link molt/molt-fetch-troubleshooting.md %}) - [Migration Overview]({% link molt/migration-overview.md %}) diff --git a/src/current/molt/molt-replicator.md b/src/current/molt/molt-replicator.md index 55955a23e89..c375b6a74e5 100644 --- a/src/current/molt/molt-replicator.md +++ b/src/current/molt/molt-replicator.md @@ -13,8 +13,8 @@ MOLT Replicator consumes change data from PostgreSQL [logical replication](https - *Checkpoint*: The position in the source database's transaction log from which replication begins or resumes: LSN (PostgreSQL), GTID (MySQL), or SCN (Oracle). - *Staging database*: A CockroachDB database used by Replicator to store replication metadata, checkpoints, and buffered mutations. Specified with [`--stagingSchema`]({% link molt/replicator-flags.md %}#staging-schema) and automatically created with [`--stagingCreateSchema`]({% link molt/replicator-flags.md %}#staging-create-schema). For details, refer to [Staging database](#staging-database). -- *Forward replication*: Replicate changes from a source database (PostgreSQL, MySQL, or Oracle) to CockroachDB during a migration. For usage details, refer to [Forward replication with initial load](#forward-replication-after-initial-load). -- *Failback*: Replicate changes from CockroachDB back to the source database. Used for migration rollback or to maintain data consistency on the source during migration. For usage details, refer to [Failback to source database](#failback-replication). +- *Forward replication*: Replicate changes from a source database (PostgreSQL, MySQL, or Oracle) to CockroachDB during a migration. For usage details, refer to [Forward replication (after initial load)](#forward-replication-after-initial-load). +- *Failback*: Replicate changes from CockroachDB back to the source database. Used for migration rollback or to maintain data consistency on the source during migration. For usage details, refer to [Failback replication](#failback-replication). ## How it works @@ -28,22 +28,6 @@ MOLT Replicator supports forward replication from PostgreSQL, MySQL, and Oracle, - Failback from CockroachDB ([`start`]({% link molt/replicator-flags.md %}#commands)): MOLT Replicator acts as an HTTP webhook sink for a single CockroachDB changefeed. Replicator receives mutations from source cluster nodes, can optionally buffer them in a CockroachDB staging cluster, and then applies time-ordered transactional batches to the target database. Mutations are applied as [`UPSERT`]({% link {{ site.current_cloud_version }}/upsert.md %}) or [`DELETE`]({% link {{ site.current_cloud_version }}/delete.md %}) statements while respecting [foreign-key]({% link {{ site.current_cloud_version }}/foreign-key.md %}) and table dependencies. -### Consistency modes - -MOLT Replicator supports three consistency modes for balancing throughput and transactional guarantees: - -1. *Consistent* (failback mode only, default for CockroachDB sources): Preserves per-row order and source transaction atomicity. Concurrent transactions are controlled by [`--parallelism`]({% link molt/replicator-flags.md %}#parallelism). - -1. *BestEffort* (failback mode only): Relaxes atomicity across tables that do not have foreign key constraints between them (maintains coherence within FK-connected groups). Enable with [`--bestEffortOnly`]({% link molt/replicator-flags.md %}#best-effort-only) or allow auto-entry via [`--bestEffortWindow`]({% link molt/replicator-flags.md %}#best-effort-window) set to a positive duration (such as `1s`). - - {{site.data.alerts.callout_info}} - For independent tables (with no foreign key constraints), BestEffort mode applies changes immediately as they arrive, without waiting for the resolved timestamp. This provides higher throughput for tables that have no relationships with other tables. - {{site.data.alerts.end}} - -1. *Immediate* (default for PostgreSQL, MySQL, and Oracle sources): Applies updates as they arrive to Replicator with no buffering or waiting for resolved timestamps. For CockroachDB sources, provides highest throughput but requires no foreign keys on the target schema. - -## Usage - ### Replicator commands MOLT Replicator provides four commands for different replication scenarios. For example commands, refer to [Common uses](#common-uses). @@ -148,14 +132,14 @@ For PostgreSQL, use [`--slotName`]({% link molt/replicator-flags.md %}#slot-name --slotName molt_slot ~~~ -For MySQL, set [`--defaultGTIDSet`]({% link molt/replicator-flags.md %}#default-gtid-set) to the [`cdc_cursor` value]({% link molt/molt-fetch.md %}#cdc-cursor) from the MOLT Fetch output: +For MySQL, set [`--defaultGTIDSet`]({% link molt/replicator-flags.md %}#default-gtid-set) to the [`cdc_cursor` value]({% link molt/molt-fetch.md %}#enable-replication) from the MOLT Fetch output: {% include_cached copy-clipboard.html %} ~~~ --defaultGTIDSet '4c658ae6-e8ad-11ef-8449-0242ac140006:1-29' ~~~ -For Oracle, set [`--scn`]({% link molt/replicator-flags.md %}#scn) and [`--backfillFromSCN`]({% link molt/replicator-flags.md %}#backfill-from-scn) to the [`cdc_cursor` values]({% link molt/molt-fetch.md %}#cdc-cursor) from the MOLT Fetch output: +For Oracle, set [`--scn`]({% link molt/replicator-flags.md %}#scn) and [`--backfillFromSCN`]({% link molt/replicator-flags.md %}#backfill-from-scn) to the [`cdc_cursor` values]({% link molt/molt-fetch.md %}#enable-replication) from the MOLT Fetch output: {% include_cached copy-clipboard.html %} ~~~ @@ -180,6 +164,20 @@ The staging database is used to: - Maintain consistency for time-ordered transactional batches while respecting table dependencies. - Provide restart capabilities after failures. +### Consistency modes + +MOLT Replicator supports three consistency modes for balancing throughput and transactional guarantees: + +1. *Consistent* (failback mode only, default for CockroachDB sources): Preserves per-row order and source transaction atomicity. Concurrent transactions are controlled by [`--parallelism`]({% link molt/replicator-flags.md %}#parallelism). + +1. *BestEffort* (failback mode only): Relaxes atomicity across tables that do not have foreign key constraints between them (maintains coherence within FK-connected groups). Enable with [`--bestEffortOnly`]({% link molt/replicator-flags.md %}#best-effort-only) or allow auto-entry via [`--bestEffortWindow`]({% link molt/replicator-flags.md %}#best-effort-window) set to a positive duration (such as `1s`). + + {{site.data.alerts.callout_info}} + For independent tables (with no foreign key constraints), BestEffort mode applies changes immediately as they arrive, without waiting for the resolved timestamp. This provides higher throughput for tables that have no relationships with other tables. + {{site.data.alerts.end}} + +1. *Immediate* (default for PostgreSQL, MySQL, and Oracle sources): Applies updates as they arrive to Replicator with no buffering or waiting for resolved timestamps. For CockroachDB sources, provides highest throughput but requires no foreign keys on the target schema. + ### Monitoring #### Metrics @@ -228,7 +226,7 @@ In a migration that utilizes [continuous replication]({% link molt/migration-co
    -To start replication after an [initial data load with MOLT Fetch]({% link molt/migrate-load-replicate.md %}#start-fetch), use the `pglogical` command: +To start replication after an initial data load with MOLT Fetch, use the `pglogical` command: {% include_cached copy-clipboard.html %} ~~~ shell @@ -237,7 +235,7 @@ replicator pglogical
    -To start replication after an [initial data load with MOLT Fetch]({% link molt/migrate-load-replicate.md %}?filters=mysql#start-fetch), use the `mylogical` command: +To start replication after an initial data load with MOLT Fetch, use the `mylogical` command: {% include_cached copy-clipboard.html %} ~~~ shell @@ -246,7 +244,7 @@ replicator mylogical
    -To start replication after an [initial data load with MOLT Fetch]({% link molt/migrate-load-replicate.md %}?filters=oracle#start-fetch), use the `oraclelogminer` command: +To start replication after an initial data load with MOLT Fetch, use the `oraclelogminer` command: {% include_cached copy-clipboard.html %} ~~~ shell diff --git a/src/current/molt/molt-type-mapping.md b/src/current/molt/molt-type-mapping.md new file mode 100644 index 00000000000..219569dd0e1 --- /dev/null +++ b/src/current/molt/molt-type-mapping.md @@ -0,0 +1,69 @@ +--- +title: Type Mappings +summary: Learn what the default type mappings are when using the MOLT Schema Conversion Tool and MOLT Fetch. +toc: true +docs_area: migrate +--- + +The MOLT Schema Conversion Tool and [MOLT Fetch]({% link molt/molt-fetch.md %}#handle-target-tables) can be used to automatically generate schema for a CockroachDB cluster. By default, types are mapped from the source database to CockroachDB as follows: + +- PostgreSQL types are mapped to existing CockroachDB [types]({% link {{site.current_cloud_version}}/data-types.md %}) that have the same [`OID`]({% link {{site.current_cloud_version}}/oid.md %}). +- The following MySQL types are mapped to corresponding CockroachDB types: + + | MySQL type | CockroachDB type | Notes | + |-----------------------------------------------------|-------------------------------------------------------------------------------------------|--------------------------------------------------------------| + | `CHAR`, `CHARACTER`, `VARCHAR`, `NCHAR`, `NVARCHAR` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | + | `TINYTEXT`, `TEXT`, `MEDIUMTEXT`, `LONGTEXT` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | + | `GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | + | `LINESTRING` | [`LINESTRING`]({% link {{site.current_cloud_version}}/linestring.md %}) | Spatial type (PostGIS-style) | + | `POINT` | [`POINT`]({% link {{site.current_cloud_version}}/point.md %}) | Spatial type (PostGIS-style) | + | `POLYGON` | [`POLYGON`]({% link {{site.current_cloud_version}}/polygon.md %}) | Spatial type (PostGIS-style) | + | `MULTIPOINT` | [`MULTIPOINT`]({% link {{site.current_cloud_version}}/multipoint.md %}) | Spatial type (PostGIS-style) | + | `MULTILINESTRING` | [`MULTILINESTRING`]({% link {{site.current_cloud_version}}/multilinestring.md %}) | Spatial type (PostGIS-style) | + | `MULTIPOLYGON` | [`MULTIPOLYGON`]({% link {{site.current_cloud_version}}/multipolygon.md %}) | Spatial type (PostGIS-style) | + | `GEOMETRYCOLLECTION`, `GEOMCOLLECTION` | [`GEOMETRYCOLLECTION`]({% link {{site.current_cloud_version}}/geometrycollection.md %}) | Spatial type (PostGIS-style) | + | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | + | `TINYINT`, `INT1` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | + | `BLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `SMALLINT`, `INT2` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | + | `MEDIUMINT`, `INT`, `INTEGER`, `INT4` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | + | `BIGINT`, `INT8` | [`INT`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | + | `FLOAT` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | + | `DOUBLE` | [`FLOAT`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | + | `DECIMAL`, `NUMERIC`, `REAL` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | + | `BINARY`, `VARBINARY` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `DATETIME` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time (no time zone) | + | `TIMESTAMP` | [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | Date and time with time zone | + | `TIME` | [`TIME`]({% link {{site.current_cloud_version}}/time.md %}) | Time of day (no date) | + | `BIT` | [`VARBIT`]({% link {{site.current_cloud_version}}/bit.md %}) | Variable-length bit array | + | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | + | `TINYBLOB`, `MEDIUMBLOB`, `LONGBLOB` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `BOOL`, `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | + +- The following Oracle types are mapped to CockroachDB types: + + | Oracle type(s) | CockroachDB type | Notes | + |---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| + | `NCHAR`, `CHAR`, `CHARACTER` | [`CHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`CHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Fixed-length character; falls back to unbounded if length not specified | + | `VARCHAR`, `VARCHAR2`, `NVARCHAR2` | [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %})(n) or [`VARCHAR`]({% link {{site.current_cloud_version}}/string.md %}) | Varying-length string; raises warning if BYTE semantics used | + | `STRING` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Unlimited-length string | + | `SMALLINT` | [`INT2`]({% link {{site.current_cloud_version}}/int.md %}) | 2-byte integer | + | `INTEGER`, `INT`, `SIMPLE_INTEGER` | [`INT4`]({% link {{site.current_cloud_version}}/int.md %}) | 4-byte integer | + | `LONG` | [`INT8`]({% link {{site.current_cloud_version}}/int.md %}) | 8-byte integer | + | `FLOAT`, `BINARY_FLOAT`, `REAL` | [`FLOAT4`]({% link {{site.current_cloud_version}}/float.md %}) | 32-bit float | + | `DOUBLE`, `BINARY_DOUBLE` | [`FLOAT8`]({% link {{site.current_cloud_version}}/float.md %}) | 64-bit float | + | `DEC`, `NUMBER`, `DECIMAL`, `NUMERIC` | [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %})(p, s) or [`DECIMAL`]({% link {{site.current_cloud_version}}/decimal.md %}) | Validates scale ≤ precision; warns if precision > 19 | + | `DATE` | [`DATE`]({% link {{site.current_cloud_version}}/date.md %}) | Date only (no time) | + | `BLOB`, `RAW`, `LONG RAW` | [`BYTES`]({% link {{site.current_cloud_version}}/bytes.md %}) | Binary data | + | `JSON` | [`JSONB`]({% link {{site.current_cloud_version}}/jsonb.md %}) | CRDB's native JSON format | + | `CLOB`, `NCLOB` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as large text | + | `BOOLEAN` | [`BOOL`]({% link {{site.current_cloud_version}}/bool.md %}) | Boolean | + | `TIMESTAMP` | [`TIMESTAMP`]({% link {{site.current_cloud_version}}/timestamp.md %}) or [`TIMESTAMPTZ`]({% link {{site.current_cloud_version}}/timestamp.md %}) | If `WITH TIME ZONE` → `TIMESTAMPTZ`, else `TIMESTAMP` | + | `ROWID`, `UROWID` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Treated as opaque identifier | + | `SDO_GEOMETRY` | [`GEOMETRY`]({% link {{site.current_cloud_version}}/architecture/glossary.md %}#geometry) | Spatial type (PostGIS-style) | + | `XMLTYPE` | [`STRING`]({% link {{site.current_cloud_version}}/string.md %}) | Stored as text | + +## See also + +- [MOLT Fetch]({% link molt/molt-fetch.md %}) +- [MOLT Schema Conversion Tool]({% link cockroachcloud/migrations-page.md %}) \ No newline at end of file diff --git a/src/current/molt/replicator-flags.md b/src/current/molt/replicator-flags.md index 8da1d276f7e..f09ae8bf84e 100644 --- a/src/current/molt/replicator-flags.md +++ b/src/current/molt/replicator-flags.md @@ -18,7 +18,7 @@ MOLT Replicator provides the following commands: | `make-jwt` | Generate JWT tokens for authorizing changefeed connections in failback scenarios. Supports signing tokens with RSA or EC keys, or generating claims for external JWT providers. For details, refer to [JWT authentication]({% link molt/molt-replicator-best-practices.md %}#jwt-authentication). | | `version` | Display version information and Go module dependencies with checksums. For details, refer to [Supply chain security]({% link molt/molt-replicator-best-practices.md %}#supply-chain-security). | -For command-specific flags and examples, refer to MOLT Replicator [Usage]({% link molt/molt-replicator.md %}#usage) and [Common uses]({% link molt/molt-replicator.md %}#common-uses). +For command-specific flags and examples, refer to MOLT Replicator's [How it works]({% link molt/molt-replicator.md %}#how-it-works) and [Common uses]({% link molt/molt-replicator.md %}#common-uses) documentation. ## Flags diff --git a/src/current/releases/molt.md b/src/current/releases/molt.md index f139ab7e054..fda58ef22ca 100644 --- a/src/current/releases/molt.md +++ b/src/current/releases/molt.md @@ -99,7 +99,7 @@ Cockroach Labs recommends using the latest available version of each tool. Refer `molt` 1.3.1 is [available](#installation). -- MOLT Fetch now supports [sharding]({% link molt/molt-fetch.md %}#table-sharding) of primary keys of any data type on PostgreSQL 11+ sources. This can be enabled with the [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag. +- MOLT Fetch now supports [sharding]({% link molt/molt-fetch.md %}#shard-tables-for-concurrent-export) of primary keys of any data type on PostgreSQL 11+ sources. This can be enabled with the [`--use-stats-based-sharding`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag. - Added the [`--ignore-replication-check`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag to allow data loads with planned downtime and no replication setup. The `--pglogical-ignore-wal-check` flag has been removed. - Added the `--enableParallelApplies` [replication flag]({% link molt/replicator-flags.md %}) to enable parallel application of independent table groups during replication. By default, applies are synchronous. When enabled, this increases throughput at the cost of increased target pool and memory usage. - Improved cleanup logic for scheduled tasks to ensure progress reporting and prevent indefinite hangs. @@ -185,7 +185,7 @@ Cockroach Labs recommends using the latest available version of each tool. Refer `molt` 1.2.2 is [available](#installation). - Added an [`--import-region`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag that is used to set the `AWS_REGION` query parameter explicitly in the [`s3` URL]({% link molt/molt-fetch.md %}#bucket-path). -- Fixed the [`truncate-if-exists`]({% link molt/molt-fetch.md %}#target-table-handling) schema mode for cases where there are uppercase table or schema names. +- Fixed the [`truncate-if-exists`]({% link molt/molt-fetch.md %}#handle-target-tables) schema mode for cases where there are uppercase table or schema names. - Fixed an issue with unsigned `BIGINT` values overflowing in replication. - Added a `--schemaRefresh` [replication flag]({% link molt/replicator-flags.md %}#schema-refresh) that is used to configure the schema watcher refresh delay in the replication phase. Previously, the refresh delay was set to a constant value of 1 minute. Set the flag as follows: `--replicator-flags "--schemaRefresh {value}"`. @@ -197,9 +197,9 @@ Cockroach Labs recommends using the latest available version of each tool. Refer - MySQL 5.7 and later are now supported with MOLT Fetch replication modes. - Fetch replication mode now defaults to a less verbose `INFO` logging level. To specify `DEBUG` logging, pass in the `--replicator-flags '-v'` setting, or `--replicator-flags '-vv'` for trace logging. - MySQL columns of type `BIGINT UNSIGNED` or `SERIAL` are now auto-mapped to [`DECIMAL`]({% link {{ site.current_cloud_version }}/decimal.md %}) type in CockroachDB. MySQL regular `BIGINT` types are mapped to [`INT`]({% link {{ site.current_cloud_version }}/int.md %}) type in CockroachDB. -- The `pglogical` replication workflow was modified in order to enforce safer and simpler defaults for the [`data-load`]({% link molt/molt-fetch.md %}#fetch-mode), `data-load-and-replication`, and `replication-only` workflows for PostgreSQL sources. Fetch now ensures that the publication is created before the slot, and that `replication-only` defaults to using publications and slots created either in previous Fetch runs or manually. +- The `pglogical` replication workflow was modified in order to enforce safer and simpler defaults for the [`data-load`]({% link molt/molt-fetch.md %}#define-fetch-mode), `data-load-and-replication`, and `replication-only` workflows for PostgreSQL sources. Fetch now ensures that the publication is created before the slot, and that `replication-only` defaults to using publications and slots created either in previous Fetch runs or manually. - Fixed scan iterator query ordering for `BINARY` and `TEXT` (of same collation) PKs so that they lead to the correct queries and ordering. -- For a MySQL source in `replication-only` mode, the [`--stagingSchema` replicator flag]({% link molt/replicator-flags.md %}#staging-schema) can now be used to resume streaming replication after being interrupted. Otherwise, the [`--defaultGTIDSet` replicator flag]({% link molt/replicator-flags.md %}#default-gtid-set) is used to start initial replication after a previous Fetch run in [`data-load`]({% link molt/molt-fetch.md %}#fetch-mode) mode, or as an override to the current replication stream. +- For a MySQL source in `replication-only` mode, the [`--stagingSchema` replicator flag]({% link molt/replicator-flags.md %}#staging-schema) can now be used to resume streaming replication after being interrupted. Otherwise, the [`--defaultGTIDSet` replicator flag]({% link molt/replicator-flags.md %}#default-gtid-set) is used to start initial replication after a previous Fetch run in [`data-load`]({% link molt/molt-fetch.md %}#define-fetch-mode) mode, or as an override to the current replication stream. ### October 29, 2024 @@ -207,11 +207,11 @@ Cockroach Labs recommends using the latest available version of each tool. Refer - Added `failback` mode to MOLT Fetch, which allows the user to replicate changes on CockroachDB back to the initial source database. Failback is supported for MySQL and PostgreSQL databases. - The [`--pprof-list-addr` flag]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags), which specifies the address of the `pprof` endpoint, is now configurable. The default value is `'127.0.0.1:3031'`. -- [Fetch modes]({% link molt/molt-fetch.md %}#fetch-mode) involving replication now state that MySQL 8.0 and later are supported for replication between MySQL and CockroachDB. -- [Partitioned tables]({% link molt/molt-fetch.md %}#transformations) can now be moved to CockroachDB using [`IMPORT INTO`]({% link {{ site.current_cloud_version }}/import-into.md %}). +- [Fetch modes]({% link molt/molt-fetch.md %}#define-fetch-mode) involving replication now state that MySQL 8.0 and later are supported for replication between MySQL and CockroachDB. +- [Partitioned tables]({% link molt/molt-fetch.md %}#define-transformations) can now be moved to CockroachDB using [`IMPORT INTO`]({% link {{ site.current_cloud_version }}/import-into.md %}). - Improved logging for the [Fetch]({% link molt/molt-fetch.md %}) schema check phases under the `trace` logging level, which is set with [`--logging trace`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags). - Added a [sample Grafana dashboard](https://molt.cockroachdb.com/molt/cli/grafana_dashboard.json) for monitoring MOLT tasks. -- Fetch now logs the name of the staging database in the target CockroachDB cluster used to store metadata for [replication modes]({% link molt/molt-fetch.md %}#fetch-mode). +- Fetch now logs the name of the staging database in the target CockroachDB cluster used to store metadata for [replication modes]({% link molt/molt-fetch.md %}#define-fetch-mode). - String [primary keys]({% link {{ site.current_cloud_version }}/primary-key.md %}) that use `C` [collations]({% link {{ site.current_cloud_version }}/collate.md %}) on PostgreSQL can now be compared to the default `en_US.utf8` on CockroachDB. - MOLT is now distributed under the [Cockroach Labs Product License Agreement](https://www.cockroachlabs.com/cockroach-labs-product-license-agreement/), which is bundled with the binary. @@ -219,7 +219,7 @@ Cockroach Labs recommends using the latest available version of each tool. Refer `molt` 1.1.7 is [available](#installation). -- When a [Fetch transformation rule]({% link molt/molt-fetch.md %}#transformations) is used to rename a table or map partitioned tables, a script in the format `partitionTableScript.{timestamp}.ts` is now automatically generated to ensure that [replication]({% link molt/molt-fetch.md %}#fetch-mode) works properly if enabled. +- When a [Fetch transformation rule]({% link molt/molt-fetch.md %}#define-transformations) is used to rename a table or map partitioned tables, a script in the format `partitionTableScript.{timestamp}.ts` is now automatically generated to ensure that [replication]({% link molt/molt-fetch.md %}#define-fetch-mode) works properly if enabled. ### August 19, 2024 @@ -232,8 +232,8 @@ Cockroach Labs recommends using the latest available version of each tool. Refer `molt` 1.1.5 is [available](#installation). - **Deprecated** the `--ongoing-replication` flag in favor of `--mode data-load-and-replication`, using the new `--mode` flag. Users should replace all instances of `--ongoing-replication` with `--mode data-load-and-replication`. -- Fetch can now be run in an export-only mode by specifying [`--mode export-only`]({% link molt/molt-fetch.md %}#fetch-mode). This will export all the data in `csv` or `csv.gz` format to the specified cloud or local store. -- Fetch can now be run in an import-only mode by specifying [`--mode import-only`]({% link molt/molt-fetch.md %}#fetch-mode). This will load all data in the specified cloud or local store into the target CockroachDB database, effectively skipping the export data phase. +- Fetch can now be run in an export-only mode by specifying [`--mode export-only`]({% link molt/molt-fetch.md %}#define-fetch-mode). This will export all the data in `csv` or `csv.gz` format to the specified cloud or local store. +- Fetch can now be run in an import-only mode by specifying [`--mode import-only`]({% link molt/molt-fetch.md %}#define-fetch-mode). This will load all data in the specified cloud or local store into the target CockroachDB database, effectively skipping the export data phase. - Strings for the `--mode` flag are now word-separated by hyphens instead of underscores. For example, `replication-only` instead of `replication_only`. ### August 8, 2024 @@ -241,7 +241,7 @@ Cockroach Labs recommends using the latest available version of each tool. Refer `molt` 1.1.4 is [available](#installation). - Added a replication-only mode for Fetch that allows the user to run ongoing replication without schema creation or initial data load. This requires users to set `--mode replication_only` and `--replicator-flags` to specify the `defaultGTIDSet` ([MySQL](https://github.com/cockroachdb/replicator/wiki/MYLogical)) or `slotName` ([PostgreSQL](https://github.com/cockroachdb/replicator/wiki/PGLogical)). -- Partitioned tables can now be mapped to renamed tables on the target database, using the Fetch [transformations framework]({% link molt/molt-fetch.md %}#transformations). +- Partitioned tables can now be mapped to renamed tables on the target database, using the Fetch [transformations framework]({% link molt/molt-fetch.md %}#define-transformations). - Added a new `--metrics-scrape-interval` flag to allow users to specify their Prometheus scrape interval and apply a sleep at the end to allow for the final metrics to be scraped. - Previously, there was a mismatch between the errors logged in log lines and those recorded in the exceptions table when an `IMPORT INTO` or `COPY FROM` operation failed due to a non-PostgreSQL error. Now, all errors will lead to an exceptions table entry that allows the user to continue progress from a certain table's file. - Fixed a bug that will allow Fetch to properly determine a GTID if there are multiple `source_uuids`. @@ -260,7 +260,7 @@ Cockroach Labs recommends using the latest available version of each tool. Refer - Fetch users can now specify columns to exclude from table migrations in order to migrate a subset of their data. This is supported in the schema creation, export, import, and direct copy phases. - Fetch now automatically maps a partitioned table from a PostgreSQL source to the target CockroachDB schema. -- Fetch now supports column exclusions and computed column mappings via a new [transformations framework]({% link molt/molt-fetch.md %}#transformations). +- Fetch now supports column exclusions and computed column mappings via a new [transformations framework]({% link molt/molt-fetch.md %}#define-transformations). - The new Fetch [`--transformations-file`]({% link molt/molt-fetch-commands-and-flags.md %}#global-flags) flag specifies a JSON file for schema/table/column transformations, which has validation utilities built in. ### July 10, 2024