Set up the Openflow Connector for SQL Server (CDC)¶
Note
This connector is subject to the Snowflake Connector Terms.
This topic describes how to set up the Openflow Connector for SQL Server (CDC).
For information on the incremental load process, see Incremental replication.
Prerequisites¶
Before setting up the connector, ensure that you have completed the following prerequisites:
-
Ensure that you have reviewed About Openflow Connector for SQL Server (CDC).
-
Ensure that you have reviewed Supported SQL Server versions.
-
Ensure that you have set up your runtime deployment. For more information, see the following topics:
-
If you use Openflow - Snowflake Deployments, ensure that you have reviewed configuring required domains and have granted access to the required domains for the SQL Server connector.
Set up your SQL Server instance¶
Before setting up the connector, perform the following tasks in your SQL Server environment:
Note
You must perform these tasks as a database administrator.
-
Enable Change Data Capture on the databases and tables that you plan to replicate:
Note
Run the
sp_cdc_enable_tableprocedure for every table that you plan to replicate. Runsp_cdc_enable_dbonce per database.The connector requires that CDC is enabled on the databases and tables before replication starts. You can also enable CDC on additional tables while the connector is running.
Note
Platform-specific variants for enabling CDC at the database level. The
sp_cdc_enable_tablecall shown above is the same on every platform; only the database-level enable procedure differs.-
AWS RDS for SQL Server. You can’t call
sys.sp_cdc_enable_dbdirectly on RDS because RDS doesn’t expose thesysadminserver role. Use the RDS-provided wrapper instead:See Using change data capture for Amazon RDS for SQL Server. CDC isn’t supported on the Web edition of RDS for SQL Server.
-
Google Cloud SQL for SQL Server. You can’t call
sys.sp_cdc_enable_dbdirectly. Use the Cloud SQL-provided wrapper instead:See Enable change data capture (CDC) on Cloud SQL for SQL Server. Cloud SQL for SQL Server currently offers SQL Server 2017, 2019, and 2022 only.
-
Azure SQL Database (single database). Use the standard
sys.sp_cdc_enable_dbprocedure. On the DTU-based purchasing model, CDC requires the S3 service tier or higher (CDC isn’t supported on Basic, S0, S1, or S2). On the vCore-based purchasing model, CDC is supported on any tier. See Change data capture with Azure SQL Database. -
Azure SQL Managed Instance. Use the standard
sys.sp_cdc_enable_dbprocedure. Enabling CDC requires membership in thesysadminserver role.
Raise max text repl size for large LOB columns
If replicated tables contain LOB columns (such as
VARCHAR(MAX),NVARCHAR(MAX), orVARBINARY(MAX)) with values larger than 64 KB, raise the SQL Servermax text repl sizesetting on the source instance. SQL Server CDC defaults this setting to 65536 bytes (64 KB), which is lower than the connector’s 16 MB per-value limit. Without raising it, replication can fail with an error such as the following:Length of LOB data (N) to be replicated exceeds configured maximum 65536. Use the stored procedure sp_configure to increase the configured maximum value for max text repl size option.
Set the value based on the largest LOB sizes in your source data. It must be at least as large as the biggest value SQL Server CDC needs to replicate, including when Oversized Value Strategy is set to Set Null (the connector still reads the full value before replacing it with
NULL).Warning
Raising
max text repl sizeallows SQL Server CDC to capture larger LOB values, but those values are written to the transaction log and copied into CDC change tables. Capturing very large values can increase transaction log generation, storage consumption, and latency in CDC capture and cleanup jobs. Set the limit to match the LOB sizes you actually need rather than the maximum, unless you require that headroom.How you change this setting depends on your platform:
-
On-premises SQL Server, Azure SQL Managed Instance, and Google Cloud SQL for SQL Server. Use
sp_configure. The example below sets the maximum allowed value of2147483647(~2 GB):For more information, see Configure the max text repl size server configuration option.
-
AWS RDS for SQL Server. You can’t change this setting with
sp_configureormsdb.dbo.rds_set_configuration. Configure it through an RDS DB parameter group instead:-
Create a custom DB parameter group for your SQL Server version family (for example,
sqlserver-se-16.0): -
Set
max text repl size (b)(note the exact parameter name, including(b)in lowercase). The example below uses2147483647(~2 GB), the maximum allowed value: -
Attach the parameter group to the RDS instance:
-
Reboot the RDS instance. This parameter requires a reboot to take effect on RDS for SQL Server.
-
-
Azure SQL Database (single database). Open a query window connected to the specific database and run:
A value of
-1is also supported and removes the size limit other than the limit imposed by the column data type.
-
-
Create a login for the SQL Server instance:
This login is used to create users for the databases you plan to replicate.
-
Create a user for each database you are replicating by running the following SQL Server command in each database:
-
Grant the required permissions to the user for each database that you are replicating.
Add the user to the
db_datareaderrole and grant SELECT on thecdcschema so the connector can read both the source tables and the CDC change tables:Run these commands in each database that you plan to replicate.
Note
These permissions give the connector read access to every user table in the database. To scope access more tightly, grant
SELECTonly on the specific tables being replicated and onSCHEMA::cdcinstead of adding the user to thedb_datareaderrole.Note
Azure SQL Database (single database) only — database owner before deploying wrapper scripts. The wrapper procedures use
EXECUTE AS OWNER. If the database owner is a Microsoft Entra ID principal (common after importing a database from a.bacpacfile) and the connector authenticates with SQL Server authentication, calls todbo.sf_openflow_cdc_enable_tableanddbo.sf_openflow_cdc_disable_tablefail with an error such asOnly active directory users can impersonate other active directory users(error 33171). The connector does not receive extra privileges from this step; it only changes who owns the database.Before deploying the Openflow CDC wrapper scripts in step 5, connect to each replicated database as the server administrator and run:
Use the SQL Server authentication login that administers the logical server (for example the login you specified when you created the server), not the connector login.
-
Deploy the Openflow CDC wrapper procedures so the connector can manage capture instances and apply source schema changes autonomously. For more information, see Deploy the Openflow CDC wrapper procedures.
-
(Optional) Grant the VIEW DEFINITION privilege on the User Defined Data Types (UDDT).
If your tables contain columns that use User Defined Data Types (UDDT), and the UDDT is owned by a different user than the connector user, you must grant the VIEW DEFINITION permission to the connector user as shown in the following SQL Server example:
Without this permission, columns using UDDT are silently excluded from replication.
-
(Optional) Configure SSL connection.
If you use an SSL connection to connect SQL Server, create the root certificate for your database server. This is required when configuring the connector.
Deploy the Openflow CDC wrapper procedures¶
The connector applies supported source table schema changes (DDL) without stopping replication or requiring a manual re-snapshot. To do this, the connector manages SQL Server capture instances autonomously: when a tracked table’s schema changes, the connector creates a new capture instance for the updated schema and drops the old one after it finishes the transition. For an overview of the process, see Schema changes.
Creating and dropping capture instances normally requires db_owner. Rather than granting the
connector that level of access, deploy a small set of wrapper procedures that perform these
operations on the connector’s behalf and grant the connector permission to run only those two
procedures.
This design has the following properties:
- The connector can run only the two wrapper procedures. For capture-instance management, the
connector is granted
EXECUTEon onlydbo.sf_openflow_cdc_enable_tableanddbo.sf_openflow_cdc_disable_table. It doesn’t holddb_ownerand can’t call the underlyingsys.sp_cdc_enable_tableorsys.sp_cdc_disable_tableprocedures directly. The wrapper procedures run withEXECUTE AS OWNER, so they supply the elevated privileges only for the specific, audited operation. - Every operation is recorded in an audit table. Each invocation of a wrapper procedure writes an
attemptrow to thedbo.openflow_cdc_audittable before it calls the engine, then asuccessorfailurerow (including the SQL Server error number and message on failure) after the call. The rows are append-only: the wrappers never update or delete audit rows.
Deploy the procedures as a database administrator. Run the following scripts, in order, in each
CDC-enabled database being replicated. Run them as a principal that already holds
db_owner.
Note
Perform these tasks as a database administrator, after creating the connector’s database user as described in Set up your SQL Server instance.
-
openflow_cdc_audit_setup.sql: Creates the append-onlydbo.openflow_cdc_audittable that the wrapper procedures write to. -
sf_openflow_cdc_enable_table.sql: Creates the wrapper procedure that the connector calls to add a new capture instance during a schema transition. -
sf_openflow_cdc_disable_table.sql: Creates the wrapper procedure that the connector calls to drop the old capture instance after a schema transition completes. -
openflow_cdc_grants.sql: Grants the connector’s database user permission to run the two wrapper procedures and to read the CDC metadata, change tables, and audit trail. Replace<user_name>with the connector’s database user created in Set up your SQL Server instance, then run the script.
Note
The connector also needs SELECT on each replicated source table. SQL Server applies row-level
filtering to cdc.change_tables for callers that don’t hold db_owner, returning only rows for
source tables that the caller can read. The db_datareader role granted in
Set up your SQL Server instance satisfies this requirement. If access was scoped
more tightly instead of using db_datareader, make sure the connector has SELECT on every source
table that it replicates.
-
Verify the deployment. Confirm that the two wrapper procedures exist and that the audit table is queryable:
The first query returns both
sf_openflow_cdc_enable_tableandsf_openflow_cdc_disable_table. The second query confirms that the audit table exists and is readable.
Set up your Snowflake environment¶
As a Snowflake administrator, perform the following tasks:
-
Create a destination database in Snowflake to store the replicated data:
-
Create a Snowflake service user:
-
Create a Snowflake role for the connector and grant the required privileges:
Use this role to manage the connector’s access to the Snowflake database.
To create objects in the destination database, you must grant the USAGE and CREATE SCHEMA privileges on the database to the role used to manage access.
-
Create a Snowflake warehouse for the connector and grant the required privileges:
Snowflake recommends starting with an XSMALL warehouse size, then experimenting with size depending on the number of tables being replicated and the amount of data transferred. Large numbers of tables typically scale better with multi-cluster warehouses, rather than a larger warehouse size. For more information, see multi-cluster warehouses.
-
Set up the public and private keys for key pair authentication:
-
Create a pair of secure keys (public and private).
-
Store the private key for the user in a file to supply to the connector’s configuration.
-
Assign the public key to the Snowflake service user:
For more information, see Key-pair authentication and key-pair rotation.
-
Install the connector¶
To install the connector, do the following as a data engineer:
-
Navigate to the Openflow overview page. In the Featured connectors section, select View more connectors.
-
On the Openflow connectors page, find the connector and select Install.
-
In the Select runtime dialog, select your runtime from the Available runtimes drop-down list and click Install.
Note
Before you install the connector, ensure that you have created a database and schema in Snowflake for the connector to store ingested data.
-
Authenticate to the deployment with your Snowflake account credentials and select Allow when prompted to allow the runtime application to access your Snowflake account. The connector installation process takes a few minutes to complete.
-
Authenticate to the runtime with your Snowflake account credentials.
The Openflow canvas appears with the connector process group added to it.
Runtime sizing¶
The runtime size determines the CPU, memory, and disk available to the connector. The available sizes are Small, Medium, and Large. Choose the size when you create the runtime: you can’t change the size of an existing runtime in place.
Size the runtime based on the sustained workload it needs to handle across all connectors running on it. Sustained means typical steady-state throughput, not peak. Peak load can temporarily increase connector queues and end-to-end replication latency; the workload catches up when the load drops back to the steady-state level.
The following ranges are starting points based on internal benchmarks and production customer data. They aren’t service guarantees. Your fit depends on row size, event distribution, schema width, and source burstiness. Start at the lower bound, measure runtime CPU, memory, queue depth, and end-to-end replication latency in production, then increase from there.
- Light workload (aggregate sustained throughput below approximately 1,000 events per second, fewer than approximately 100 actively changing tables): a Small runtime can host a single low-volume connector. Pack additional connectors on Small only when each source is genuinely light.
- Moderate workload (approximately 1,000 to 5,000 events per second, hundreds of actively changing tables): a Medium runtime, typically running 5 to 8 connectors.
- Heavy workload (approximately 5,000 to 15,000 events per second, hundreds to low thousands of actively changing tables): a Large runtime, typically running 15 or more connectors. If you want a smaller blast radius, split across two Medium runtimes instead.
Running multiple connectors on one runtime¶
You can run multiple CDC connector instances on a single runtime. This is useful for replicating many small databases, for example a multi-tenant SaaS with one database per tenant, or a fleet of operational databases per business unit or region.
When you run multiple CDC connector instances of the same type on one runtime, keep their shared Source and Destination parameter contexts intact and override only the per-connector values in each Ingestion context. For the recommended process, see Run multiple CDC connector instances on one runtime in the configuration section for the connector you are setting up.
Important
Run a connector on a dedicated runtime, not packed with others, when any of the following applies:
- A single source sustains more than approximately 15,000 events per second.
- You need sub-1-minute end-to-end replication latency under load.
- You can’t tolerate noisy-neighbor effects from other sources sharing the runtime.
Each replicated table can consume two Snowpipe Streaming pipes: one for snapshot replication and one for incremental replication. As you pack more tables onto a runtime, check your account’s Snowpipe Streaming pipe limit and raise it before you approach the cap.
Resize a runtime¶
Runtime size is fixed at creation, so to change size you run the connector on a different runtime. You have two options depending on whether you want to preserve the current replication progress.
If you don’t need to keep the progress of the current connector, the simplest path is to create a new runtime at the size you need and install a new connector instance on it. The new connector starts from scratch: it snapshots all configured tables and then captures ongoing changes from that point. The replication progress of the existing connector is discarded.
To keep the progress of the current connector, for example to avoid re-snapshotting tables that took a long time to snapshot initially, migrate the connector to the new runtime. This reuses the existing destination tables and resumes incremental replication from where it left off.
For migration instructions, see Reinstall the connector.
Configure the connector¶
To configure the connector, do the following as a data engineer:
-
Right-click on the imported process group and select Parameters.
-
Populate the required parameter values.
For more information on the required parameter values, see the following sections:
- SQLServer Source Parameters: Used to establish a connection with SQL Server.
- SQLServer Destination Parameters: Used to establish a connection with Snowflake.
- SQLServer Ingestion Parameters: Used to specify the tables to replicate.
Start by setting the parameters of the SQLServer Source Parameters context, then the SQLServer Destination Parameters context. After you complete this, enable the connector. The connector connects to both SQL Server and Snowflake and starts running. However, the connector doesn’t replicate any data until tables to be replicated are explicitly added to its configuration.
To configure specific tables for replication, edit the SQLServer Ingestion Parameters context. After you apply the changes to the SQLServer Ingestion Parameters context, the configuration is picked up by the connector, and the replication lifecycle starts for every table.
Run multiple CDC connector instances on one runtime¶
Tip
You don’t have to configure multiple CDC connector instances by hand. The openflow skill in Snowflake CoCo is the recommended path when you need to run many CDC connectors on one runtime. The skill applies this pattern consistently across the connector fleet. To get started, install and connect the Snowflake CoCo CLI, then ask the bundled openflow skill to configure the layout.
Each CDC connector instance uses Source, Destination, and Ingestion parameter contexts. The Ingestion context inherits from the Source and Destination contexts, so any value you don’t override in Ingestion resolves from the parent context.
Use shared Source and Destination contexts with per-connector overrides in Ingestion¶
Snowflake recommends this setup for running multiple CDC connector instances manually. It’s the same pattern the openflow skill applies automatically at scale.
When you import more than one CDC connector instance of the same type into one runtime, keep the Source and Destination contexts at their default names and let every connector instance inherit from them. In that connector’s Ingestion parameter context, override only the values that differ from the shared defaults: the connection URL, replication slot or server ID, destination database, and table list. Leave shared values, such as the Snowflake role, warehouse, and JDBC driver, in the Source and Destination contexts so every connector instance inherits them.
Use the following process for each additional connector instance:
- Import the connector instance.
- Confirm that its Ingestion context inherits from the existing Source and Destination contexts, instead of creating a new set of Source and Destination contexts.
- In the Ingestion context, override every value that must differ from the shared defaults: at minimum, the source connection identity (for example, the JDBC URL and replication slot or server ID) and the destination database.
- Confirm that the connector replicates from the correct source into the correct destination before moving on to the next connector instance.
Don’t rename the Source and Destination contexts¶
Don’t rename the Source or Destination parameter contexts to make them unique per connector instance. Renaming these contexts might seem like a simpler way to keep each connector instance visually distinct, but it silently breaks future connector version upgrades.
When Snowflake ships a connector version that adds a new parameter to the Source or Destination context, the upgrade process looks for a context with the connector’s default name to apply that new parameter to. If you renamed the context, the upgrade process can’t find it, and the new parameter isn’t added to the context your connector instances actually use. Your connector instances then silently fall out of sync with the new version, and the Snowflake registry can’t repair this automatically. This risk applies whether you rename the contexts to a single shared alternate name or to a distinct name per connector instance.
The Ingestion context is safe to rename, because the registry creates a fresh Ingestion context for every new connector instance. Renaming it doesn’t affect any other connector instance or any future upgrade. If you want every connector instance to be individually identifiable in the parameter context list, rename only its Ingestion context, for example to the source database name, tenant name, or region.
Avoid unintended inheritance from an earlier connector instance¶
The most common mistake when importing an additional CDC connector instance is unintentionally reusing the previous instance’s Ingestion context, instead of creating a dedicated context. If this happens, the new connector instance uses the earlier instance’s source database, destination database, table list, replication slot, server ID, or XStream configuration, and replicates the wrong data without any error.
After importing each additional connector instance, always confirm that its Ingestion context is new and dedicated to that instance, and not shared with any earlier connector instance. If the import wizard offers an option to inherit existing parameter contexts, confirm that it creates a new Ingestion context rather than reusing an existing one.
SQLServer Source Parameters¶
| Parameter | Description |
|---|---|
| SQLServer Connection URL | The full JDBC URL used to connect to the source. For a standalone SQL Server instance or Azure SQL Managed Instance, point the URL at the instance. The connector discovers the databases to replicate from that instance.
For Always On Availability Groups, see Always On Availability Groups. For Azure SQL Database, point the URL at a specific database using the
|
| SQLServer JDBC Driver | Select the Reference asset checkbox to upload the SQL Server JDBC driver. |
| SQLServer Username | The username for the connector. |
| SQLServer Password | The password for the connector. |
Note
To connect with Windows authentication using NTLMv2, configure the SQL Server source parameters as follows:
- SQLServer Connection URL:
jdbc:sqlserver://<host>:1433;databaseName=<db>;integratedSecurity=true;authenticationScheme=NTLM;domain=<domain>; - SQLServer JDBC Driver: Upload the
mssql-jdbcJAR. The driver class name iscom.microsoft.sqlserver.jdbc.SQLServerDriver. - SQLServer Username: Enter the domain user.
- SQLServer Password: Enter the domain password.
Note
Azure SQL Database refers to the single-database PaaS offering, not Azure SQL Managed Instance.
Always On Availability Groups¶
Configure the connector to connect through the availability group listener (the virtual network name for the group), not through an individual replica node. Set the listener hostname in the SQLServer Connection URL parameter in the SQLServer Source Parameters context.
Always On Availability Groups provide high availability through a shared listener and automatic failover between replicas. Always On Availability Groups are separate from SQL Server transactional replication.
Warning
Do not change the connection target after replication has started. Each database maintains its own replication position independently, so switching to a different server or listener can cause the connector to lose track of which changes have already been processed. This might result in data loss.
For ApplicationIntent in the JDBC URL on Always On Availability Groups:
Note
To route reads to a readable secondary, append ;ApplicationIntent=ReadOnly to the SQLServer Connection URL when read-only routing is configured on the availability group listener.
On topologies that do not expose a readable secondary (for example, AWS RDS Multi-AZ with a single endpoint), the driver connects to the primary even when ApplicationIntent=ReadOnly is set.
When connections are routed to a readable secondary, the connector reads from CDC change tables on that replica. Those tables reflect changes only after capture lag and redo lag on the primary, so replication latency can be higher than when you connect to the primary. To reduce lag, tune SQL Server CDC capture and availability group redo settings on the primary.
During availability group failovers, replication resumes automatically and tables are not moved to FAILED. During each failover window, the connector logs a transient error that the database is not accessible for queries while data movement is suspended or a replica is not enabled for read access. This error is expected during the transition; the connector retries and recovers once failover completes.
To connect to the primary through the listener without read-only routing, omit ApplicationIntent or use the default ReadWrite intent.
For failover behavior, see Always On Availability Groups and source failover.
SQLServer Destination Parameters¶
| Parameter | Description | Required |
|---|---|---|
| Destination Database | The database where data is persisted. It must already exist in Snowflake. The name is case-sensitive. For unquoted identifiers, provide the name in uppercase. | Yes |
| Destination Schema Pattern | A pattern for the names of destination schemas where data is persisted. The connector creates the schemas if they don’t exist. You can customize the pattern per ingested table using these optional variables:
For example, for a table with the qualified name To ingest all tables into a single schema, provide a schema name without any variables,
like Important Don’t change this setting after the connector has begun ingesting data. Changing this setting after ingestion has begun breaks the existing ingestion. If you must change this setting, create a new connector instance. | Yes |
| Snowflake Authentication Strategy | When using:
| Yes |
| Snowflake Account Identifier | When using:
| Yes |
| Snowflake Connection Strategy | When using KEY_PAIR, specify the strategy for connecting to Snowflake:
| Required for BYOC with KEY_PAIR only, otherwise ignored. |
| Snowflake Object Identifier Resolution | Specifies how source object identifiers such as schemas, tables, and column names are stored and queried in Snowflake. This setting dictates whether you must use double quotes in SQL queries. Option 1: Default, case-insensitive (recommended).
For example, Note Snowflake recommends using this option if database objects are not expected to have mixed case names. Important Do not change this setting after connector ingestion has begun. Changing this setting after ingestion has begun breaks the existing ingestion. If you must change this setting, create a new connector instance. Option 2: Case-sensitive.
Note Snowflake recommends using this option if you must preserve source casing for legacy or compatibility reasons.
For example, the source database includes table names that differ in case only, such as | Yes |
| Snowflake Private Key | When using:
| No |
| Snowflake Private Key File | When using:
| No |
| Snowflake Private Key Password | When using:
| No |
| Snowflake Role | When using:
| Yes |
| Snowflake Username | When using:
| Yes |
| Oversized Value Strategy | Determines how the connector handles values that exceed its internal size limits (16 MB) during replication. Possible values are:
| No |
| Snowflake Warehouse | Snowflake warehouse used to run queries. | Yes |
SQLServer Ingestion Parameters¶
| Parameter | Description |
|---|---|
| Included Table Names | A comma-separated list of source table paths, including their databases and schemas, for example:
|
| Included Table Regex | A regular expression to match against table paths, including database and schema names. Every path matching the expression is replicated, and new tables matching the pattern that are created later are also included automatically, for example:
|
| Column Filter JSON | Optional. A JSON array of filter objects specifying which columns to include or exclude per table. For syntax details and examples, see Replicate a subset of columns in a table. |
| Table Key Configuration JSON | Optional. A JSON array that declares a logical key for one or more tables. When set, the
logical key takes the highest priority and overrides any primary key, unique constraint, or unique index
that the connector would otherwise auto-detect. The connector reads this parameter through its
For syntax details and examples, see Specify a logical key for a table. |
| Merge Task Schedule CRON | CRON expression defining periods when merge operations from Journal to Destination Table will be
triggered. Set it to For example:
For additional information and examples, see the cron triggers tutorial in the Quartz Documentation. |
Read the source under SNAPSHOT isolation¶
During the snapshot phase, the connector reads directly from the source tables to perform the initial full copy. Under SQL Server’s default READ COMMITTED isolation level, these reads acquire shared locks that can deadlock with concurrent writes from other database clients. During incremental replication, the connector reads from dedicated CDC change tables instead of the source tables, so it doesn’t take these locks. To avoid deadlocks during the snapshot phase without affecting the isolation level that other applications use, configure the connector to read under SNAPSHOT isolation. For background, see Source database locking behavior.
Enable SNAPSHOT isolation for the connector in two steps:
-
On each source database, allow snapshot isolation:
-
Add a dynamic property named Use Snapshot Isolation with the value
trueto theMultiDatabaseFetchTableSnapshotprocessor. Only the snapshot phase takes shared locks on the source tables, so incremental replication doesn’t require the Use Snapshot Isolation property.
The connector checks each source database when it starts and uses SNAPSHOT isolation only for databases that
have ALLOW_SNAPSHOT_ISOLATION enabled. For a database that doesn’t have it enabled, the connector falls back
to the default isolation level. Because this check runs at startup, restart the processor after you change
ALLOW_SNAPSHOT_ISOLATION.
Caution
ALLOW_SNAPSHOT_ISOLATION only makes SNAPSHOT isolation available to sessions that explicitly request it, such
as the connector. It doesn’t change the default READ COMMITTED isolation level, so other applications that use
the source database are unaffected.
Don’t use READ_COMMITTED_SNAPSHOT (RCSI) for this purpose. Although RCSI also removes the shared locks, it
redefines the default READ COMMITTED isolation level for every connection to the database. Applications that
rely on the default lock-based READ COMMITTED behavior (for example, expecting readers to block on concurrent
uncommitted writes) can see different results after the change.
Restart table replication¶
A table in FAILED state — for example, due to a missing primary key or unsupported schema change — does not restart automatically. If a table enters a FAILED state or you need to restart replication from scratch, use the following procedure to remove and re-add the table to replication.
Note
If the failure was caused by an issue in the source table such as a missing primary key, resolve that issue in the source database before continuing.
-
Remove the table from replication, using one of the following methods:
- Add the table to the Re-snapshot Table Exclusions parameter to temporarily exclude it from replication. This is convenient when the table is matched by an Included Table Regex that you don’t want to change.
- In the Ingestion Parameters context, either remove the table from Included Table Names or modify the Included Table Regex so the table is no longer matched.
-
Verify the table has been removed:
- In the Openflow runtime canvas, right-click a processor group and choose Controller Services.
- In the table listing controller services, locate the Table State Store row, click the three vertical dots on the right side of the row, then choose View State.
Important
You must wait until the table’s state is fully removed from this list before proceeding. Do not continue until this configuration change has completed.
-
Clean up the destination: Once the table’s state shows as fully removed, manually DROP the destination table in Snowflake. Note that the connector will not overwrite an existing destination table during the snapshot phase; if the table still exists, replication will fail again. Optionally, the journal table and stream can also be removed if they are no longer needed.
-
Re-add the table by reversing the change you made in the first step: either remove the table from Re-snapshot Table Exclusions, or add it back to Included Table Names or Included Table Regex. The connector then re-snapshots the table.
-
Verify the restart: Check the Table State Store using the instructions given previously. The state of the table should appear with the status NEW, then transition to SNAPSHOT_REPLICATION, and finally INCREMENTAL_REPLICATION.
Replicate a subset of columns in a table¶
The connector can filter the data replicated per table to a subset of configured columns. Primary key columns are always included regardless of exclusions.
To apply column filters, set the Column Filter JSON parameter in the Ingestion Parameters context to a JSON array of filter objects, one per table you want to filter.
Columns can be included or excluded by name or by regular expression pattern. You can apply a single condition per table, or combine multiple conditions, with exclusions always taking precedence over inclusions.
Syntax¶
Each object in the array identifies a table and specifies which columns to include or exclude.
Because this connector uses three-part fully qualified names (database, schema, and table), each object
can include a database or databasePattern field in addition to the schema and table fields.
The following rules apply:
- Use
database,schema, andtablefor exact name matching, ordatabasePattern,schemaPattern, andtablePatternfor regex matching. You can’t use both a field and its pattern variant in the same object (for example,schemaandschemaPatterncan’t both appear). - At least one of
included,excluded,includedPattern, orexcludedPatternmust be provided. - When both included and excluded filters are specified, exclusions take precedence.
- When multiple filters match the same table, the last matching filter is used, with exact matches taking precedence over pattern-based filters.
- The value can be an array of objects to apply different filters to different tables.
Examples¶
Include specific columns by name:
Exclude specific columns by name:
Combine an include pattern with a specific exclusion (for example, include all email columns except admin_email):
Mix a database pattern with an exact schema and table name to apply a filter across databases:
Pass multiple filter objects to apply different rules to different tables:
Including and excluding the same column¶
Removing a column from a table’s replicated set (by excluding it or by removing
it from the included list) has the same effect on the destination as dropping
the column at the source: the connector soft-deletes the column on the
destination by renaming it with a suffix (by default, __SNOWFLAKE_DELETED).
If you then add the column back to the replicated set and later remove it a
second time, replication for the affected table fails because the soft-deleted
column name is already taken. To recover, restart replication for the affected
table.
Replicate a partitioned table¶
The connector supports replication of partitioned tables. A SQL Server partitioned table is replicated into Snowflake as a single destination table, containing data from all partitions.
To replicate a partitioned table, ensure that CDC is enabled on the partitioned table, as described in Set up your SQL Server instance.
For more information about how the connector handles snapshots of large partitioned tables, see Snapshot of partitioned tables.
Specify a logical key for a table¶
The connector requires a replication key for every table it replicates. By default, the connector uses the table’s primary key, or falls back to a qualifying unique constraint or unique index if no primary key exists. For the full priority order the connector uses to choose a key, see How the connector chooses a replication key. A logical key is a user-declared replacement for the auto-detected key. Configure a logical key when:
- A table has no primary key, but one or more columns are unique in the data.
- A specific column or set of columns should be used as the replication key, regardless of what the connector would auto-detect (for example, to override a synthetic primary key).
A logical key takes the highest priority. When the connector finds a logical key for a table, it uses that key and ignores any primary key on the table.
JSON syntax¶
The Table Key Configuration JSON value is a JSON array. Each entry maps one table to its logical key columns:
The fields are:
| Field | Description |
|---|---|
database | Required. The exact source database name. |
schema | Required. The exact source schema name. |
table | Required. The exact source table name. |
logicalKey | Required. A non-empty array of source column names that uniquely identify rows in the table. |
The following rules apply:
database,schema, andtablematching is case-sensitive. Use the exact names as reported by SQL Server.logicalKeycolumn names are matched case-insensitively: the connector lowercases both the configured names and the source column names before comparing them. On a case-sensitive SQL Server collation this matching is lenient. A key whose case differs from the actual column is still accepted, and two source columns that differ only by letter case are treated as the same key column. Use the exact column case to avoid ambiguity.- An entry whose
database,schema, andtabledon’t match any replicated table is silently ignored.
Logical key configuration examples¶
A single-column logical key on a table without a primary key:
A composite logical key:
Logical keys for several tables in one JSON value:
Restrictions¶
The connector rejects the configuration when any of the following is true:
logicalKeyis missing, empty, or not an array.logicalKeycontains duplicate column names.logicalKeycontains a nullable column. Logical key columns must be defined asNOT NULLto reliably identify rows.logicalKeycontains a column name that doesn’t exist in the source table.
When the configuration is rejected, verification surfaces a clear error and the table stays
in the NEW state (never FAILED). After you fix the configuration, replication for the
table resumes without resetting state.
Warnings logged for risky configurations¶
The connector accepts the following configurations but logs a warning at table initialization.
When choosing logical-key columns, prefer columns with high cardinality and, where possible, monotonically increasing values. Low-cardinality or non-monotonic keys can degrade snapshot performance.
- A logical-key column is a floating-point type (
float,real). Floating-point comparisons can produce inconsistent results because of precision differences. - A logical-key column is a large-object type (
text,image,varbinary(max)). Using large objects as keys severely degrades MERGE performance. - The composite logical key includes more than five columns. Long composite keys often indicate a design issue and might degrade MERGE performance.
- The logical key overrides an existing primary key on the table. Verify that the replacement key is intentional: the connector no longer uses the primary key for MERGE operations.
If you observe data divergence after any of these warnings, run a periodic full reload to reconcile the destination with the source.
Schema changes that affect a logical key¶
The connector doesn’t track schema evolution of the unique or logical key columns after the CDC capture instance exists. Dropping or altering a logical-key column isn’t detected at runtime:
- If a logical-key column is dropped on the source, replication for the affected table fails. Restart table replication to recover. For more information, see Restart table replication.
- If a logical-key column is renamed on the source, the configuration still references the old name and replication fails. Update the JSON to use the new name and restart table replication.
Track data changes in tables¶
The connector replicates the current state of data from the source tables, as well as detected changes from each polling interval. This data is stored in journal tables created in the same schema as the destination table.
The journal table names are formatted as: <source_table_name>_JOURNAL_<timestamp>_<schema_generation>
where <timestamp> is the value of epoch seconds when the source table was added to replication, and <schema_generation> is an integer increasing with every schema change on the source table.
As a result, source tables that undergo schema changes will have multiple journal tables.
When you remove a table from replication, then add it back, the <timestamp> value changes, and <schema_generation> starts again from 1.
Important
Snowflake recommends not altering the structure of journal tables in any way. The connector uses them to update the destination table as part of the replication process.
The connector never drops journal tables, but uses the latest journal for every replicated source table, only reading append-only streams on top of journals. To reclaim the storage, you can:
- Truncate all journal tables at any time.
- Drop the journal tables related to source tables that were removed from replication.
- Drop all but the latest generation journal tables for actively replicated tables.
For example, if your connector is set to actively replicate source table orders,
and you have earlier removed table customers from replication, you may have
the following journal tables. In this case you can drop all of them except orders_5678_2.
Configure scheduling of merge tasks¶
The connector uses a warehouse to merge change data capture (CDC) data into destination tables. The processor named Merge Journal to Destination triggers this operation. When there are no new changes, or when no new FlowFiles are waiting in the Merge Journal to Destination queue, no merge is triggered and the warehouse is available for auto-suspension.
To limit warehouse cost and restrict merges to scheduled times, use the CRON expression in the Merge Task Schedule CRON parameter. It throttles the FlowFiles that reach the Merge Journal to Destination processor, so merges are triggered only during the specified period. The connector evaluates the schedule in the UTC time zone.
For additional information and examples, see the cron triggers tutorial in the Quartz Documentation.
Run the flow¶
- Right-click on the canvas and select Enable all Controller Services.
- Right-click on the imported process group and select Start. The connector starts the data ingestion.