MySQL SQL connector
This topic describes how to use the MySQL connector in SQL jobs.
Background information
The MySQL connector supports all databases that are compatible with the MySQL protocol, such as ApsaraDB RDS for MySQL, PolarDB for MySQL, OceanBase (MySQL mode), and self-managed MySQL.
When you use the MySQL connector to read data from OceanBase, ensure that binary logging (binlog) is enabled and correctly configured. For more information, see Binlog-related operations. This feature is in public preview. Use this feature with caution.
The MySQL connector supports the following.
Category | Details |
Supported types | Source tables, dimension tables, sink tables, and data ingestion data sources |
Runtime mode | Only streaming mode is supported. |
Data format | Not applicable |
Specific monitoring metrics | |
API types | DataStream, SQL, and data ingestion YAML |
Supports updating or deleting data in sink tables | Yes |
Features
A MySQL change data capture (CDC) source table, also known as a MySQL streaming source table, first reads the full historical data from the database. Then, it seamlessly switches to reading binary logs. This process ensures that no data is missed or duplicated. Even if a failure occurs, data is processed with exactly-once semantics. A MySQL CDC source table supports concurrent reading of full data. It uses an incremental snapshot algorithm to implement lock-free reading and resumable data transfer. For more information, see About MySQL CDC source tables.
Unified batch and stream processing that supports reading both full and incremental data, which eliminates the need to maintain two separate processes.
Concurrent reading of full data for horizontal performance scaling.
Seamless switching from full data reading to incremental data reading and automatic scale-in to save compute resources.
Resumable data transfer during the full data reading phase for improved stability.
Lock-free reading of full data, which does not affect online services.
Support for reading backup logs of ApsaraDB RDS for MySQL.
Parallel parsing of binary log files for lower read latency.
Prerequisites
Before you use a MySQL CDC source table, you must complete the prerequisite operations described in Configure MySQL.
ApsaraDB RDS for MySQL
Perform a network probe to ensure network connectivity to Realtime Compute for Apache Flink.
MySQL version: 5.6, 5.7, 8.0.x, or 8.4.
Binary logging must be enabled. This is enabled by default.
The binary log format must be ROW. This is the default format.
The `binlog_row_image` parameter must be set to FULL. This is the default setting.
Binary Log Transaction Compression must be disabled. This feature was introduced in MySQL 8.0.20 and is disabled by default.
A MySQL user has been created with the SELECT, SHOW DATABASES, REPLICATION SLAVE, and REPLICATION CLIENT permissions.
Create a MySQL database and table. For more information, see Create a database and an account for an ApsaraDB RDS for MySQL instance. Use a privileged account to create the MySQL database to prevent operation failures due to insufficient permissions.
Configure an IP address whitelist. For more information, see Configure an IP address whitelist for an ApsaraDB RDS for MySQL instance.
PolarDB for MySQL
Perform a network probe to ensure network connectivity to Realtime Compute for Apache Flink.
MySQL version: 5.6, 5.7, 8.0.x, or 8.4.
Binary logging must be enabled. This is disabled by default.
The binary log format must be ROW. This is the default format.
The `binlog_row_image` parameter must be set to FULL. This is the default setting.
Binary Log Transaction Compression must be disabled. This feature was introduced in MySQL 8.0.20 and is disabled by default.
You have created a MySQL user with the SELECT, SHOW DATABASES, REPLICATION SLAVE, and REPLICATION CLIENT permissions.
Create a MySQL database and table. For more information, see Create a database and an account for a PolarDB for MySQL cluster. Use a privileged account to create the MySQL database to prevent operation failures due to insufficient permissions.
Configure an IP address whitelist. For more information, see Configure an IP address whitelist for a PolarDB for MySQL cluster.
Self-managed MySQL
Perform a network probe to ensure network connectivity to Realtime Compute for Apache Flink.
MySQL version: 5.6, 5.7, 8.0.x, or 8.4.
Binary logging must be enabled. This is disabled by default.
The binary log format must be ROW. The default format is STATEMENT.
The `binlog_row_image` parameter must be set to FULL. This is the default setting.
Binary Log Transaction Compression must be disabled. This feature was introduced in MySQL 8.0.20 and is disabled by default.
Create a MySQL user and grant the SELECT, SHOW DATABASES, REPLICATION SLAVE, and REPLICATION CLIENT permissions.
Create a MySQL database and table. For more information, see Create a database and an account for a self-managed MySQL instance. Use a privileged account to create the MySQL database to prevent operation failures due to insufficient permissions.
Configure an IP address whitelist. For more information, see Configure an IP address whitelist for a self-managed MySQL instance.
Limits
General limits
MySQL CDC source tables do not support watermark definitions. To perform window aggregation, you can use a non-window aggregation method. For more information, see How do I perform window aggregation if watermark definitions are not supported?.
In Create Table As Select (CTAS) and Create Database As Select (CDAS) jobs, MySQL CDC source tables can synchronize some schema changes. For more information about the supported change types, see Schema evolution synchronization policies.
The MySQL CDC connector does not support the Binary Log Transaction Compression feature. Therefore, when you use the MySQL CDC connector to consume incremental data, ensure that Binary Log Transaction Compression is disabled. Otherwise, the connector may fail to retrieve incremental data.
ApsaraDB RDS for MySQL limits
For ApsaraDB RDS for MySQL, do not read data from a secondary database or read-only replica. This is because the default binary log retention period for secondary databases and read-only replicas is short. If binary logs expire and are cleared, the job may fail to consume the binary log data and report an error.
ApsaraDB RDS for MySQL enables parallel primary/secondary synchronization by default but does not guarantee a consistent transaction order between the primary and secondary instances. This may cause data to be missed during a primary/secondary switchover and checkpoint recovery. To avoid this issue, you can manually enable the `slave_preserve_commit_order` option for ApsaraDB RDS for MySQL.
PolarDB for MySQL limits
MySQL CDC source tables do not support reading data from Multi-master Cluster Architecture clusters of PolarDB for MySQL V1.0.19 and earlier. For more information, see What is a Multi-master Cluster?. The binary logs generated by these clusters may contain duplicate table IDs. This can cause schema mapping errors in the CDC source table, which leads to errors when parsing binary log data.
Open source MySQL limits
By default, MySQL maintains the transaction order during primary/secondary binary log replication. If a MySQL replica has parallel replication enabled (slave_parallel_workers > 1) but does not have slave_preserve_commit_order=ON enabled, its transaction commit order may be inconsistent with the primary database. When Flink CDC recovers from a checkpoint, it may miss data because of the disordered sequence. You can set `slave_preserve_commit_order` = ON on the MySQL replica. Alternatively, you can set `slave_parallel_workers` = 1, but this will sacrifice replication performance.
Usage notes
Source table
During the full data reading phase, you cannot save a savepoint, add a table to or delete a table from the source table, and then restart the job from the savepoint. If you perform these operations, the job will fail to read data.
Sink table
Auto-increment primary keys: Do not declare auto-increment primary keys in the DDL. MySQL automatically populates them when writing data.
You must declare at least one non-primary key field. Otherwise, an error is reported.
The `NOT ENFORCED` constraint in the DDL indicates that Flink does not enforce primary key validation. You are responsible for ensuring the correctness and integrity of the primary key. For more information, see Validity Check.
Dimension table
If you want to use an index to accelerate queries, the order of fields in the JOIN clause must match the order defined in the index. This is based on the leftmost prefix rule. For example, if the index is (a, b, c), the JOIN condition is
ON t.a = x AND t.b = y.The SQL generated by Flink may be rewritten by the optimizer. This can prevent the index from being hit during the actual database query. To confirm whether the index is used, check the execution plan (EXPLAIN) or the slow query log in MySQL to view the actual SELECT statement that is executed.
SQL
You can use the MySQL connector in SQL jobs as a source table, dimension table, or sink table.
Syntax
CREATE TEMPORARY TABLE mysqlcdc_source (
order_id INT,
order_date TIMESTAMP(0),
customer_name STRING,
price DECIMAL(10, 5),
product_id INT,
order_status BOOLEAN,
PRIMARY KEY(order_id) NOT ENFORCED
) WITH (
'connector' = 'mysql',
'hostname' = '<yourHostname>',
'port' = '3306',
'username' = '<yourUsername>',
'password' = '<yourPassword>',
'database-name' = '<yourDatabaseName>',
'table-name' = '<yourTableName>'
);When writing to a sink table, the connector constructs and executes an SQL statement for each received data record. The statement is structured as follows:
For a sink table without a primary key, an
INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...);statement is executed.For a sink table with a primary key, an
INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...) ON DUPLICATE KEY UPDATE column1 = VALUES(column1), column2 = VALUES(column2), ...;statement is executed. Note: If the physical table has a unique index constraint other than the primary key, inserting two records with different primary keys but the same unique index value causes a unique index conflict. This results in data being overwritten and lost.
If an auto-increment primary key is defined in the MySQL database, do not declare the auto-increment field in the Flink DDL. The database automatically populates this field when writing data. The connector supports writing and deleting data with auto-increment fields, but does not support updating this data.
WITH parameters
General
Parameter
Description
Required
Data type
Default value
Notes
connector
The table type.
Yes
STRING
None
When used as a source table, you can set this parameter to
mysql-cdcormysql. They are equivalent. When used as a dimension table or sink table, the value must bemysql.hostname
The IP address or hostname of the MySQL database.
Yes
STRING
None
We recommend that you specify a virtual private cloud (VPC) address.
NoteIf the MySQL database and Realtime Compute for Apache Flink are not in the same VPC, you must establish a cross-VPC network connection or use a public endpoint to access the database. For more information, see Manage and operate workspaces and How can a fully managed Flink cluster access the Internet?.
username
The username for the MySQL database service.
Yes
STRING
None
None.
password
The password for the MySQL database service.
Yes
STRING
None
None.
database-name
The name of the MySQL database.
Yes
STRING
None
When a database is used as a source table, you can use a regular expression for the database name to read data from multiple databases.
When you use regular expressions, do not use the ^ and $ symbols to match the beginning and end of the string. For more information, see the notes for the table-name parameter.
table-name
The name of the MySQL table.
Yes
STRING
None
You can use a regular expression for the source table name to read data from multiple tables.
When you read data from multiple MySQL tables, submit multiple CTAS statements as a single job. This avoids enabling multiple binary log listeners and improves performance and efficiency. For more information, see Multiple CTAS statements: Submit as a single job.
When you use regular expressions, do not use the ^ and $ symbols to match the beginning and end of the string. For more information, see the following note.
NoteWhen a MySQL CDC source table matches table names using a regular expression, it concatenates the database-name and table-name that you specify with the string \\. to form a full-path regular expression. Before VVR 8.0.1, the character . was used. The connector then uses this regular expression to match the fully qualified names of tables in the MySQL database.
For example, if you set 'database-name'='db_.*' and 'table-name'='tb_.+', the connector uses the regular expression db_.*\\.tb_.+ to match the fully qualified table names to determine which tables to read. Before VVR 8.0.1, the regular expression was db_.*.tb_.+.
port
The port number of the MySQL database service.
No
INTEGER
3306
None.
Source table only
Parameter
Description
Required
Data type
Default value
Notes
server-id
A numeric ID for the database client.
No
STRING
A random value between 5400 and 6400 is generated.
This ID must be globally unique within the MySQL cluster. Set a different ID for each job that connects to the same database.
This parameter also supports an ID range format, such as 5400-5408. When incremental reading is enabled, concurrent reading is supported. In this case, set an ID range so that each concurrent reader uses a different ID. For more information, see Use Server ID.
scan.incremental.snapshot.enabled
Specifies whether to enable incremental snapshots.
No
BOOLEAN
true
Incremental snapshots are enabled by default. Incremental snapshot is a new mechanism for reading full data snapshots. Compared to the old snapshot reading method, incremental snapshots have many advantages, including the following:
The source can read full data in parallel.
The source supports chunk-level checkpoints when reading full data.
The source does not need to acquire a global read lock (FLUSH TABLES WITH read lock) when reading full data.
If you want the source to support concurrent reading, each concurrent reader needs a unique server ID. Therefore, server-id must be a range, such as 5400-6400, and the size of the range must be greater than or equal to the concurrency.
NoteThis configuration item is removed in Ververica Runtime (VVR) 11.1 and later.
scan.incremental.snapshot.chunk.size
The size of each chunk in number of rows.
No
INTEGER
8096
When incremental snapshot reading is enabled, the table is split into multiple chunks for reading. The data of a chunk is cached in memory before it is fully read.
The fewer rows each chunk contains, the greater the total number of chunks in the table. Although this reduces the granularity of fault recovery, it may lead to out-of-memory (OOM) errors and lower overall throughput. Therefore, you need to make a trade-off and set a reasonable chunk size.
scan.snapshot.fetch.size
The maximum number of records to pull at a time when reading the full data of a table.
No
INTEGER
1024
None.
scan.startup.mode
The startup mode for data consumption.
No
STRING
initial
Valid values:
initial (default): On the first startup or a stateless startup, the connector scans the full historical data and then reads the latest binary log data.
latest-offset: On the first startup or a stateless startup, the connector does not scan the historical data. It starts reading from the end of the binary log, which means it only reads the latest changes made after the connector starts.
earliest-offset: The connector does not scan the historical data. It starts reading from the earliest available binary log.
specific-offset: The connector does not scan the historical data. It starts from a specific binary log offset. You can specify the offset by configuring both scan.startup.specific-offset.file and scan.startup.specific-offset.pos, or by configuring only scan.startup.specific-offset.gtid-set to start from a specific GTID set.
timestamp: The connector does not scan the historical data. It starts reading the binary log from a specified timestamp. The timestamp is specified by scan.startup.timestamp-millis in milliseconds.
ImportantWhen using the earliest-offset, specific-offset, or timestamp startup mode, ensure that the schema of the corresponding table does not change between the specified binary log consumption position and the job startup time. This prevents errors caused by schema mismatches.
scan.startup.specific-offset.file
The binary log filename for the start offset when using the specific-offset startup mode.
No
STRING
None
When you use this parameter, you must set scan.startup.mode to specific-offset. Example filename format:
mysql-bin.000003.scan.startup.specific-offset.pos
The offset within the specified binary log file for the start offset when using the specific-offset startup mode.
No
INTEGER
None
When you use this parameter, you must set scan.startup.mode to specific-offset.
scan.startup.specific-offset.gtid-set
The GTID set for the start offset when using the specific-offset startup mode.
No
STRING
None
When you use this parameter, you must set scan.startup.mode to specific-offset. Example GTID set format:
24DA167-0C0C-11E8-8442-00059A3C7B00:1-19.scan.startup.timestamp-millis
The timestamp in milliseconds for the start offset when using the timestamp startup mode.
No
LONG
None
When you use this parameter, you must set scan.startup.mode to timestamp. The timestamp unit is milliseconds.
ImportantWhen you specify a time, MySQL CDC attempts to read the initial event of each binary log file to determine its timestamp. It then locates the binary log file corresponding to the specified time. Make sure that the binary log file corresponding to the specified timestamp has not been cleared from the database and can be read.
server-time-zone
The session time zone used by the database.
No
STRING
If you do not specify this parameter, the system uses the environment time zone of the Flink job runtime as the database server time zone. This is the time zone of the zone you selected.
Example: Asia/Shanghai. This parameter controls how the TIMESTAMP type in MySQL is converted to the STRING type. For more information, see Debezium temporal values.
debezium.min.row.count.to.stream.results
When the number of rows in a table is greater than this value, batch reading mode is used.
No
INTEGER
1000
Flink reads data from a MySQL source table in one of the following ways:
Full read: Reads the entire table's data directly into memory. This method is fast but consumes a corresponding amount of memory. If the source table is very large, there is a risk of OOM errors.
Batch read: Reads data in multiple batches, with a certain number of rows per batch, until all data is read. This method avoids OOM risks when reading large tables but is relatively slow.
connect.timeout
The maximum time to wait for a connection to the MySQL database server to time out before retrying.
No
DURATION
30s
None.
connect.max-retries
The maximum number of retries after a failed connection to the MySQL database service.
No
INTEGER
3
None.
connection.pool.size
The size of the database connection pool.
No
INTEGER
20
The database connection pool is used to reuse connections, which can reduce the number of database connections.
jdbc.properties.*
Custom connection parameters in the JDBC URL.
No
STRING
None
You can pass custom connection parameters. For example, to not use the SSL protocol, you can configure 'jdbc.properties.useSSL' = 'false'.
For more information about the supported connection parameters, see MySQL Configuration Properties.
debezium.*
Custom parameters for Debezium to read binary logs.
No
STRING
None
You can pass custom Debezium parameters. For example, use 'debezium.event.deserialization.failure.handling.mode'='ignore' to specify the handling logic for parsing errors.
WarningDo not modify Debezium parameters arbitrarily. This may cause the connector to read data incorrectly. For example, the debezium.binlog.buffer.size parameter is not allowed to be configured.
heartbeat.interval
The interval at which the source advances the binary log offset using heartbeat events.
No
DURATION
30s
Heartbeat events are used to advance the binary log offset in the source. This is very useful for tables in MySQL that are updated infrequently. For such tables, the binary log offset cannot advance automatically. Heartbeat events can push the binary log offset forward, which prevents issues caused by an expired binary log offset. An expired binary log offset can cause the job to fail and be unrecoverable, requiring a stateless restart.
scan.incremental.snapshot.chunk.key-column
Specifies a column to be used as the splitting column for sharding during the snapshot phase.
See the Notes column.
STRING
None
Required for tables without a primary key. The selected column must be of a non-null type (NOT NULL).
Optional for tables with a primary key. Only one column can be selected from the primary key.
rds.region-id
The region ID of the Alibaba Cloud ApsaraDB RDS for MySQL instance.
Required when using the feature to read archived logs from OSS.
STRING
None
For more information about region IDs, see Regions and zones.
ImportantBecause the GTID string for MySQL CDC is randomly generated and not monotonically increasing like binary log file offsets, locating a GTID in a file requires downloading and parsing all archived logs from OSS. This process is very resource-intensive and time-consuming, making features that rely on GTID offsets infeasible. Therefore, the OSS archived log feature only supports starting from a specified timestamp or a specified binary log file offset. It does not support starting from a specified GTID, nor does it support scenarios with primary/secondary switchovers in the archived logs, because MySQL primary/secondary switchovers rely on GTIDs. Evaluate this feature carefully before use.
rds.access-key-id
The AccessKey ID of the Alibaba Cloud ApsaraDB RDS for MySQL account.
Required when using the feature to read archived logs from OSS.
STRING
None
For more information, see How do I view the AccessKey ID and AccessKey secret?.
ImportantTo prevent your AccessKey information from being leaked, use the secret management feature to specify the AccessKey ID. For more information, see Manage variables.
rds.access-key-secret
The AccessKey secret of the Alibaba Cloud ApsaraDB RDS for MySQL account.
Required when using the feature to read archived logs from OSS.
STRING
None
For more information, see How do I view the AccessKey ID and AccessKey secret?
ImportantTo prevent your AccessKey information from being leaked, use the secret management feature to specify the AccessKey secret. For more information, see Manage variables.
rds.db-instance-id
The ID of the Alibaba Cloud ApsaraDB RDS for MySQL instance.
Required when using the feature to read archived logs from OSS.
STRING
None
None.
rds.main-db-id
The primary database number of the Alibaba Cloud ApsaraDB RDS for MySQL instance.
No
STRING
None
For more information about how to obtain the primary database number, see ApsaraDB RDS for MySQL log backup.
Supported only in VVR 8.0.7 and later.
NoteIf this parameter is not specified, VVR 11.7 and later automatically query the primary database number based on the ApsaraDB RDS for MySQL connection information.
rds.download.timeout
The timeout period for downloading a single archived log from OSS.
No
DURATION
60s
None.
rds.endpoint
The service endpoint for obtaining OSS binary log information.
No
STRING
None
For more information about the valid values, see Endpoints.
Supported only in VVR 8.0.8 and later.
scan.incremental.close-idle-reader.enabled
Specifies whether to close idle readers after the snapshot is complete.
No
BOOLEAN
false
Supported only in VVR 8.0.1 and later.
For this configuration to take effect, you must set execution.checkpointing.checkpoints-after-tasks-finish.enabled to true.
scan.read-changelog-as-append-only.enabled
Specifies whether to convert the changelog data stream to an append-only data stream.
No
BOOLEAN
false
Valid values:
true: All types of messages, including INSERT, DELETE, UPDATE_BEFORE, and UPDATE_AFTER, are converted to INSERT messages. Enable this option only in special scenarios, such as when you need to save delete messages from the upstream table.
false (default): All types of messages are sent downstream as they are.
NoteSupported only in VVR 8.0.8 and later.
scan.only.deserialize.captured.tables.changelog.enabled
In the incremental phase, specifies whether to deserialize only the change events of the specified tables.
No
BOOLEAN
The default value is false in VVR 8.x versions.
The default value is true in VVR 11.1 and later.
Valid values:
true: Deserializes only the change data of the target tables to accelerate binary log reading.
false (default): Deserializes the change data of all tables.
NoteSupported only in VVR 8.0.7 and later.
When you use VVR 8.0.8 or earlier, you must change the parameter name to debezium.scan.only.deserialize.captured.tables.changelog.enable.
scan.parse.online.schema.changes.enabled
In the incremental phase, specifies whether to attempt to parse RDS lockless change DDL events.
No
BOOLEAN
false
Valid values:
true: Parses RDS lockless change DDL events.
false (default): Does not parse RDS lockless change DDL events.
This is an experimental feature. Before performing an online lockless change, take a snapshot of the Flink job for recovery.
NoteSupported only in VVR 11.1 and later.
scan.incremental.snapshot.backfill.skip
Specifies whether to skip backfill during the snapshot reading phase.
No
BOOLEAN
false
Valid values:
true: Skips backfill during the snapshot reading phase.
false (default): Does not skip backfill during the snapshot reading phase.
Backfill applies only during the snapshot query of a single chunk and does not cover the entire full-read phase. When backfill is skipped, each chunk's snapshot query reads the latest table data at that instant; updates that occur on a chunk after it has been read are not merged during the full-read phase and are read from the Binlog after entering the incremental phase. For example, an update to chunk5 that occurs while chunk5 is being snapshotted is reflected directly in chunk5's snapshot; if chunk5 is updated after the reader has advanced to chunk80, the update is applied later from the Binlog during the incremental phase.
ImportantWhen enabled, changes that occur during or after a chunk's scan are still delivered from the Binlog in the incremental phase and may be duplicated. Only at-least-once semantics are guaranteed. Enable this only when the downstream sink supports idempotent writes by primary key.
NoteSupported only in VVR 11.1 and later.
scan.incremental.snapshot.unbounded-chunk-first.enabled
Specifies whether to dispatch unbounded chunks first during the snapshot reading phase.
No
BOOELEAN
false
Valid values:
true: Dispatches unbounded chunks first during the snapshot reading phase.
false (default): Does not dispatch unbounded chunks first during the snapshot reading phase.
This is an experimental feature. Enabling it can reduce the risk of OOM errors on the TaskManager when synchronizing the last chunk during the snapshot phase. Add this parameter before the first startup of the job.
NoteSupported only in VVR 11.1 and later.
binlog.session.network.timeout
The network read/write timeout for the binary log connection.
No
DURATION
10m
If set to 0s, the default timeout of the MySQL server is used.
NoteSupported only in VVR 11.5 and later.
scan.rate-limit.records-per-second
Limits the maximum number of records sent by the source per second.
No
LONG
None
This is applicable to scenarios where data reading needs to be limited. This limit is effective in both the full and incremental phases.
The
numRecordsOutPerSecondmetric of the source reflects the number of records output by the entire data stream per second. You can adjust this parameter based on this metric.In the full data reading phase, you usually need to reduce the number of rows read in each batch. You can reduce the value of the
scan.incremental.snapshot.chunk.sizeparameter.NoteSupported only in VVR 11.5 and later.
scan.binlog.tolerate.gtid-holes
Enabling this parameter ignores gaps in the GTID sequence, allowing the job to bypass discontinuous events and continue running.
No
BOOLEAN
false
Before enabling this parameter, you must ensure that the job's start offset has not expired. If the job starts from a cleared or expired GTID offset, the engine will silently skip the missing logs, which will lead to data loss.
NoteThis parameter is supported only in VVR 11.6 and later.
Dimension table-specific parameters
Parameter
Description
Required
Data type
Default value
Notes
url
The MySQL JDBC URL.
No
STRING
None
The URL format is:
jdbc:mysql://<endpoint>:<port>/<database_name>.lookup.max-retries
The maximum number of retries after a failed data read.
No
INTEGER
3
Supported only in VVR 6.0.7 and later.
lookup.cache.strategy
The cache policy.
No
STRING
None
The supported cache policies are None, LRU, and ALL. For more information about the values, see Dimension table JOIN statements.
NoteWhen you use the LRU cache policy, you must also configure the lookup.cache.max-rows parameter.
lookup.cache.max-rows
The maximum number of cached rows.
No
INTEGER
100000
If you select the LRU cache policy, you must set the cache size.
If you select the ALL cache policy, you do not need to set the cache size.
lookup.cache.ttl
The cache time-to-live (TTL).
No
DURATION
10 s
The configuration of lookup.cache.ttl depends on lookup.cache.strategy:
If lookup.cache.strategy is set to None, you do not need to configure lookup.cache.ttl. This means the cache does not time out.
If lookup.cache.strategy is set to LRU, lookup.cache.ttl is the cache TTL. By default, the cache does not expire.
If lookup.cache.strategy is set to ALL, lookup.cache.ttl is the cache loading time. By default, the cache is not reloaded.
Use a time format, such as 1min or 10s.
lookup.max-join-rows
The maximum number of results returned when a record from the primary table matches records in the dimension table.
No
INTEGER
1024
None.
lookup.filter-push-down.enabled
Specifies whether to enable filter pushdown for the dimension table.
No
BOOLEAN
false
Valid values:
true: Enables filter pushdown for the dimension table. When loading data from the MySQL database table, the dimension table filters data in advance based on the conditions set in the SQL job.
false (default): Disables filter pushdown for the dimension table. When loading data from the MySQL database table, the dimension table loads all data.
NoteSupported only in VVR 8.0.7 and later.
ImportantDimension table pushdown should only be enabled when a Flink table is used as a dimension table. MySQL source tables do not support enabling filter pushdown. If a Flink table is used as both a source table and a dimension table, and filter pushdown is enabled for the dimension table, you must explicitly set this configuration item to false for the source table using SQL Hints. Otherwise, the job may run abnormally.
For sink tables only
Parameter
Description
Required
Data type
Default value
Notes
url
The MySQL JDBC URL.
No
STRING
None
The URL format is:
jdbc:mysql://<endpoint>:<port>/<database_name>.sink.max-retries
The maximum number of retries after a failed data write.
No
INTEGER
3
None.
sink.buffer-flush.batch-size
The number of rows in a single batch write.
No
INTEGER
4096
None.
sink.buffer-flush.max-rows
The number of data rows cached in memory.
No
INTEGER
10000
This parameter takes effect only after a primary key is specified.
sink.buffer-flush.interval
The interval for flushing the cache. If the data in the cache does not meet the output conditions after the specified waiting time, the system automatically outputs all data in the cache.
No
DURATION
1s
None.
sink.ignore-delete
Specifies whether to ignore data DELETE operations.
No
BOOLEAN
false
When the stream generated by Flink SQL includes delete or update-before records, if multiple output tasks update different fields of the same table simultaneously, data inconsistency may occur.
For example, after a record is deleted, another task updates only some fields. The un-updated fields will become null or default values, causing data errors.
By setting sink.ignore-delete to true, you can ignore upstream DELETE and UPDATE_BEFORE operations to avoid such issues.
NoteUPDATE_BEFORE is part of Flink's retraction mechanism, used to "retract" the old value in an update operation.
When ignoreDelete = true, all DELETE and UPDATE_BEFORE type records are skipped. Only INSERT and UPDATE_AFTER records are processed.
sink.ignore-delete-mode
The strategy for handling delete-type records after DELETE operations are ignored.
No
STRING
ALL
Valid values:
ALL: Ignore both -D and -U records.
REAL_DELETE: Ignore only -D records.
UPDATE_BEFORE: Ignore only -U records.
NoteThis option is supported only in Realtime Compute engine VVR 11.8 and later.
Effective only when sink.ignore-delete=true. Configuring it alone results in an error.
sink.ignore-null-when-update
When updating data, specifies whether to update the corresponding field to null or skip the update for that field if the incoming data field value is null.
No
BOOLEAN
false
Valid values:
true: Does not update the field. This parameter can be set to true only when a primary key is set for the Flink table. When set to true:
For VVR 8.0.6 and earlier, the sink table does not support batch writing.
For VVR 8.0.7 and later, the sink table supports batch writing.
Batch writing can significantly improve write efficiency and overall throughput, but it introduces data latency and the risk of OOM errors. Therefore, you must make a trade-off based on your business scenario.
false: Updates the field to null.
NoteThis parameter is supported only in VVR 8.0.5 and later.
Type mapping
CDC source tables
MySQL CDC field type
Flink field type
TINYINT
TINYINT
SMALLINT
SMALLINT
TINYINT UNSIGNED
TINYINT UNSIGNED ZEROFILL
INT
INT
MEDIUMINT
SMALLINT UNSIGNED
SMALLINT UNSIGNED ZEROFILL
BIGINT
BIGINT
INT UNSIGNED
INT UNSIGNED ZEROFILL
MEDIUMINT UNSIGNED
MEDIUMINT UNSIGNED ZEROFILL
BIGINT UNSIGNED
DECIMAL(20, 0)
BIGINT UNSIGNED ZEROFILL
SERIAL
FLOAT [UNSIGNED] [ZEROFILL]
FLOAT
DOUBLE [UNSIGNED] [ZEROFILL]
DOUBLE
DOUBLE PRECISION [UNSIGNED] [ZEROFILL]
REAL [UNSIGNED] [ZEROFILL]
NUMERIC(p, s) [UNSIGNED] [ZEROFILL]
DECIMAL(p, s)
DECIMAL(p, s) [UNSIGNED] [ZEROFILL]
BOOLEAN
BOOLEAN
TINYINT(1)
DATE
DATE
TIME [(p)]
TIME [(p)] [WITHOUT TIME ZONE]
DATETIME [(p)]
TIMESTAMP [(p)] [WITHOUT TIME ZONE]
TIMESTAMP [(p)]
TIMESTAMP [(p)]
TIMESTAMP [(p)] WITH LOCAL TIME ZONE
CHAR(n)
STRING
VARCHAR(n)
TEXT
BINARY
BYTES
VARBINARY
BLOB
ImportantDo not use the TINYINT(1) type in MySQL to store values other than 0 and 1. When property-version=0, the MySQL CDC source table maps TINYINT(1) to the BOOLEAN type in Flink by default. This can cause data inaccuracies. To use the TINYINT(1) type to store values other than 0 and 1, see the configuration parameter catalog.table.treat-tinyint1-as-boolean.
Dimension tables and sink tables
MySQL field type
Flink field type
TINYINT
TINYINT
SMALLINT
SMALLINT
TINYINT UNSIGNED
INT
INT
MEDIUMINT
SMALLINT UNSIGNED
BIGINT
BIGINT
INT UNSIGNED
BIGINT UNSIGNED
DECIMAL(20, 0)
FLOAT
FLOAT
DOUBLE
DOUBLE
DOUBLE PRECISION
NUMERIC(p, s)
DECIMAL(p, s)
Notewhere p <= 38.
DECIMAL(p, s)
BOOLEAN
BOOLEAN
TINYINT(1)
DATE
DATE
TIME [(p)]
TIME [(p)] [WITHOUT TIME ZONE]
DATETIME [(p)]
TIMESTAMP [(p)] [WITHOUT TIME ZONE]
TIMESTAMP [(p)]
CHAR(n)
CHAR(n)
VARCHAR(n)
VARCHAR(n)
BIT(n)
BINARY(⌈n/8⌉)
BINARY(n)
BINARY(n)
VARBINARY(N)
VARBINARY(N)
TINYTEXT
STRING
TEXT
MEDIUMTEXT
LONGTEXT
TINYBLOB
BYTES
ImportantFlink only supports MySQL BLOB type records that are less than or equal to 2,147,483,647 (2^31 - 1) bytes.
BLOB
MEDIUMBLOB
LONGBLOB
Usage examples
CDC source table
CREATE TEMPORARY TABLE mysqlcdc_source ( order_id INT, order_date TIMESTAMP(0), customer_name STRING, price DECIMAL(10, 5), product_id INT, order_status BOOLEAN, PRIMARY KEY(order_id) NOT ENFORCED ) WITH ( 'connector' = 'mysql', 'hostname' = '<yourHostname>', 'port' = '3306', 'username' = '<yourUsername>', 'password' = '<yourPassword>', 'database-name' = '<yourDatabaseName>', 'table-name' = '<yourTableName>' ); CREATE TEMPORARY TABLE blackhole_sink( order_id INT, customer_name STRING ) WITH ( 'connector' = 'blackhole' ); INSERT INTO blackhole_sink SELECT order_id, customer_name FROM mysqlcdc_source;Dimension table
CREATE TEMPORARY TABLE datagen_source( a INT, b BIGINT, c STRING, `proctime` AS PROCTIME() ) WITH ( 'connector' = 'datagen' ); CREATE TEMPORARY TABLE mysql_dim ( a INT, b VARCHAR, c VARCHAR ) WITH ( 'connector' = 'mysql', 'hostname' = '<yourHostname>', 'port' = '3306', 'username' = '<yourUsername>', 'password' = '<yourPassword>', 'database-name' = '<yourDatabaseName>', 'table-name' = '<yourTableName>' ); CREATE TEMPORARY TABLE blackhole_sink( a INT, b STRING ) WITH ( 'connector' = 'blackhole' ); INSERT INTO blackhole_sink SELECT T.a, H.b FROM datagen_source AS T JOIN mysql_dim FOR SYSTEM_TIME AS OF T.`proctime` AS H ON T.a = H.a;Sink table
CREATE TEMPORARY TABLE datagen_source ( `name` VARCHAR, `age` INT ) WITH ( 'connector' = 'datagen' ); CREATE TEMPORARY TABLE mysql_sink ( `name` VARCHAR, `age` INT ) WITH ( 'connector' = 'mysql', 'hostname' = '<yourHostname>', 'port' = '3306', 'username' = '<yourUsername>', 'password' = '<yourPassword>', 'database-name' = '<yourDatabaseName>', 'table-name' = '<yourTableName>' ); INSERT INTO mysql_sink SELECT * FROM datagen_source;Data ingestion data source
source: type: mysql name: MySQL Source hostname: ${mysql.hostname} port: ${mysql.port} username: ${mysql.username} password: ${mysql.password} tables: ${mysql.source.table} server-id: 7601-7604 sink: type: values name: Values Sink print.enabled: true sink.print.logger: true
About MySQL CDC source tables
How it works
When a MySQL CDC source table starts, it scans the entire table, splits the table into multiple chunks based on the primary key, and records the current binary log offset. The source table then uses an incremental snapshot algorithm to read the data from each chunk using SELECT statements. The job periodically performs checkpoints to record the completed chunks. If a failover occurs, the job continues to read data from the unfinished chunks. After all chunks are read, the job starts reading incremental change records from the previously recorded binary log offset. The Flink job continues to perform periodic checkpoints to record the binary log offset. If the job fails over, it resumes processing from the last recorded binary log offset, which achieves exactly-once semantics.
For a more detailed explanation of the incremental snapshot algorithm, see MySQL CDC Connector.
Metadata
Metadata is useful in scenarios where data from sharded databases and tables is merged and synchronized. This is because after merging, businesses often want to distinguish the source database and table for each data record. Metadata columns can access the database and table name information of the source table. Therefore, you can easily merge multiple sharded tables into a single destination table using metadata columns.
The MySQL CDC Source supports metadata column syntax. You can access the following metadata through metadata columns.
Metadata key
Metadata type
Description
database_name
STRING NOT NULL
The name of the database that contains the row.
table_name
STRING NOT NULL
The name of the table that contains the row.
op_ts
TIMESTAMP_LTZ(3) NOT NULL
The time the row was changed in the database. If the record is from the historical data of the table instead of the binary log, this value is always 0.
NoteThis field is accurate only to the second.
op_type
STRING NOT NULL
The change type of the row.
+I: INSERT message
-D: DELETE message
-U: UPDATE_BEFORE message
+U: UPDATE_AFTER message
NoteSupported only in VVR 8.0.7 and later.
query_log
STRING NOT NULL
You can read the MySQL query log record for this row.
NoteMySQL needs to have the binlog_rows_query_log_events parameter enabled to record query logs.
The following code example shows how to merge and synchronize multiple orders tables from multiple sharded databases in a MySQL instance to a holo_orders table in Hologres.
CREATE TEMPORARY TABLE mysql_orders ( db_name STRING METADATA FROM 'database_name' VIRTUAL, -- Read the database name. table_name STRING METADATA FROM 'table_name' VIRTUAL, -- Read the table name. operation_ts TIMESTAMP_LTZ(3) METADATA FROM 'op_ts' VIRTUAL, -- Read the change time. op_type STRING METADATA FROM 'op_type' VIRTUAL, -- Read the change type. order_id INT, order_date TIMESTAMP(0), customer_name STRING, price DECIMAL(10, 5), product_id INT, order_status BOOLEAN, PRIMARY KEY(order_id) NOT ENFORCED ) WITH ( 'connector' = 'mysql-cdc', 'hostname' = 'localhost', 'port' = '3306', 'username' = 'flinkuser', 'password' = 'flinkpw', 'database-name' = 'mydb_.*', -- Regular expression to match multiple sharded databases. 'table-name' = 'orders_.*' -- Regular expression to match multiple sharded tables. ); INSERT INTO holo_orders SELECT * FROM mysql_orders;Based on the code above, if the `scan.read-changelog-as-append-only.enabled` parameter is set to true in the WITH clause, the output result varies depending on the primary key setting of the downstream table:
If the primary key of the downstream table is `order_id`, the output result contains only the last change for each primary key in the upstream table. For data whose last change for a primary key was a delete operation, you can see a record in the downstream table with the same primary key and an `op_type` of -D.
If the primary key of the downstream table is `order_id`, `operation_ts`, and `op_type`, the output result contains the complete changes for each primary key in the upstream table.
Regular expression support
The MySQL CDC source table supports using regular expressions in the table name or database name to match multiple tables or databases. The following code example shows how to specify multiple tables using a regular expression.
CREATE TABLE products ( db_name STRING METADATA FROM 'database_name' VIRTUAL, table_name STRING METADATA FROM 'table_name' VIRTUAL, operation_ts TIMESTAMP_LTZ(3) METADATA FROM 'op_ts' VIRTUAL, order_id INT, order_date TIMESTAMP(0), customer_name STRING, price DECIMAL(10, 5), product_id INT, order_status BOOLEAN, PRIMARY KEY(order_id) NOT ENFORCED ) WITH ( 'connector' = 'mysql-cdc', 'hostname' = 'localhost', 'port' = '3306', 'username' = 'root', 'password' = '123456', 'database-name' = '(^(test).*|^(tpc).*|txc|.*[p$]|t{2})', -- Regular expression to match multiple databases. 'table-name' = '(t[5-8]|tt)' -- Regular expression to match multiple tables. );The regular expressions in the example are explained as follows:
`^(test).*` is a prefix matching example. This expression can match database names that start with "test", such as "test1" or "test2".
`.*[p$]` is a suffix matching example. This expression can match database names that end with "p", such as "cdcp" or "edcp".
`txc` is a specific match. It can match a database name that is exactly "txc".
When MySQL CDC matches a fully qualified table name, it uses the `database-name.table-name` pattern to uniquely identify a table. For example, the pattern `(^(test).*|^(tpc).*|txc|.*[p$]|t{2}).(t[ 5-8]|tt)` can match tables such as `txc.tt` and `test2.test5` in the database.
ImportantIn the configuration of an SQL job, the `table-name` and `database-name` parameters do not support using a comma (,) to specify multiple tables or databases.
To match multiple tables or use multiple regular expressions, connect them with a vertical bar (|) and enclose them in parentheses. For example, to read the `user` and `product` tables, you can set `table-name` to
(user|product).If a regular expression contains a comma, you must rewrite it using the vertical bar (|) operator. For example, the regular expression
mytable_\d{1, 2}must be rewritten as the equivalent(mytable_\d{1}|mytable_\d{2})to avoid using a comma.
Concurrency control
The MySQL connector supports multithreaded reading of full data, which can improve data loading efficiency. In conjunction with the Autopilot automatic tuning feature in the Realtime Compute for Apache Flink console, the connector can automatically scale in during the incremental phase after multithreaded reading is complete to save compute resources.
In the development console of Realtime Compute for Apache Flink, you can set the concurrency of a job in basic mode or expert mode on the Resource Configuration page.
The concurrency set in basic mode is the global concurrency for the entire job.
For example, when the parallelism is set to
8in basic mode, theserver-idin the SQL WITH clause should be configured as a continuous range (such as'404-412').Expert mode supports setting the concurrency for a specific VERTEX as needed.
For more information about resource configuration, see Configure deployment information for a job.
ImportantWhether you are in basic mode or expert mode, when you set the concurrency, the server ID range declared in the table must be greater than or equal to the job's concurrency. For example, if the server ID range is `5404-5412`, there are nine unique server IDs. Therefore, the job's concurrency can be set to a maximum of 9. Different jobs for the same MySQL instance must not have overlapping server ID ranges. This means each job must be explicitly configured with a different server ID or server ID range.
Autopilot automatic scale-in
The full data phase accumulates a large amount of historical data. To improve reading efficiency, historical data is usually read in parallel. In the incremental binary log phase, because the amount of binary log data is small and to ensure global order, single-threaded reading is usually sufficient. The different resource requirements of the full and incremental phases can be balanced for performance and resources using the automatic tuning feature.
Automatic tuning monitors the traffic of each task of the MySQL CDC Source. When entering the binary log phase, if only one task is responsible for binary log reading and the other tasks are idle, automatic tuning automatically reduces the CU count and concurrency of the source. To enable automatic tuning, set the automatic tuning mode to Active on the job O&M page.
NoteThe default minimum trigger interval for reducing concurrency is 24 hours. For more information about automatic tuning parameters and details, see Configure automatic tuning.
Startup modes
Use the `scan.startup.mode` configuration item to specify the startup mode of the MySQL CDC source table. The options include the following:
initial (default): On the first startup or a stateless startup, performs a full read of the database table and then switches to incremental mode to read the binary log.
earliest-offset: Skips the snapshot phase and starts reading from the earliest available binary log offset.
latest-offset: Skips the snapshot phase and starts reading from the end of the binary log. In this mode, the source table can only read data changes that occur after the job starts.
specific-offset: Skips the snapshot phase and starts reading from a specified binary log offset. The offset can be specified by the binary log filename and position, or by a GTID set.
timestamp: Skips the snapshot phase and starts reading binary log events from a specified timestamp.
A stateless startup reuses no state. The source connector treats it as a first startup, so scan.startup.mode takes effect again. For more information about deployment startup modes, see Start a deployment.
Usage example:
CREATE TABLE mysql_source (...) WITH ( 'connector' = 'mysql-cdc', 'scan.startup.mode' = 'earliest-offset', -- Start from the earliest offset. 'scan.startup.mode' = 'latest-offset', -- Start from the latest offset. 'scan.startup.mode' = 'specific-offset', -- Start from a specific offset. 'scan.startup.mode' = 'timestamp', -- Start from a specific timestamp. 'scan.startup.specific-offset.file' = 'mysql-bin.000003', -- Specify the binary log filename in specific-offset mode. 'scan.startup.specific-offset.pos' = '4', -- Specify the binary log position in specific-offset mode. 'scan.startup.specific-offset.gtid-set' = '24DA167-0C0C-11E8-8442-00059A3C7B00:1-19', -- Specify the GTID set in specific-offset mode. 'scan.startup.timestamp-millis' = '1667232000000' -- Specify the startup timestamp in timestamp mode. ... )ImportantThe MySQL source prints the current offset to the log at the INFO level during a checkpoint. The log prefix is
Binlog offset on checkpoint {checkpoint-id}. This log can help you start a job from a specific checkpoint offset.If the table being read has undergone schema changes, starting from the `earliest-offset`, `specific-offset`, or `timestamp` may cause an error. This is because the Debezium reader internally saves the latest table schema, and early data with a mismatched schema cannot be parsed correctly.
About CDC source tables without primary keys
Using a table without a primary key requires setting `scan.incremental.snapshot.chunk.key-column`, and only a non-null column can be selected.
The processing semantics for a CDC source table without a primary key are determined by the behavior of the column specified by `scan.incremental.snapshot.chunk.key-column`:
If the specified column is not updated, exactly-once semantics can be guaranteed.
If the specified column is updated, only at-least-once semantics can be guaranteed. However, you can ensure data correctness by combining it with the downstream, specifying a downstream primary key, and using idempotent operations.
Read backup logs of Alibaba Cloud ApsaraDB RDS for MySQL
The MySQL CDC source table supports reading backup logs of Alibaba Cloud ApsaraDB RDS for MySQL. This is useful in scenarios where the full data phase takes a long time and the local binary log files have been automatically cleared, but the automatically or manually uploaded backup files still exist.
Usage example:
CREATE TABLE mysql_source (...) WITH ( 'connector' = 'mysql-cdc', 'rds.region-id' = 'cn-beijing', 'rds.access-key-id' = 'xxxxxxxxx', 'rds.access-key-secret' = 'xxxxxxxxx', 'rds.db-instance-id' = 'rm-xxxxxxxxxxxxxxxxx', 'rds.main-db-id' = '12345678', 'rds.download.timeout' = '60s' ... )Enable CDC Source reuse
In the same job, multiple MySQL CDC source tables start multiple binary log clients. If all source tables are on the same instance, this increases the load on the database. For more information, see MySQL CDC FAQ.
Solution
VVR 8.0.7 and later versions support MySQL CDC source reuse. This feature merges MySQL CDC source tables that can be merged. Merging occurs when the source table configurations are identical, except for the database name, table name, and
server-id. The engine automatically merges MySQL CDC sources within the same job.Procedure
Use the
SETcommand in your SQL job:SET 'table.optimizer.source-merge.enabled' = 'true'; # (For VVR 8.0.8 and 8.0.9) Also set this item: SET 'sql-gateway.exec-plan.enabled' = 'false';VVR 11.1 and later versions have reuse enabled by default.
Start the job without a state. Because modifying the source reuse configuration changes the job topology, you must start the job without a state. Otherwise, the job may fail to start or you may lose data. If a source is merged, you can see a
MergetableSourceScannode in the topology.
ImportantAfter you enable reuse, do not disable operator chaining. If you set
pipeline.operator-chainingtofalse, it increases the overhead of data serialization and deserialization. The more sources are merged, the greater the overhead.In VVR 8.0.7, disabling operator chaining causes serialization issues.
Accelerate binary log reading
When you use the MySQL connector as a source table or a data ingestion data source, it parses binary log files to generate various change messages during the incremental phase. The binary log files record all table changes in binary format. You can accelerate the parsing of binary log files in the following ways.
Enable parallel parsing and parsing filters (This feature requires Realtime Compute for Apache Flink with Ververica Runtime (VVR) 8.0.7 or later. It is not available in the community edition of the MySQL CDC connector.)
Enable the
scan.only.deserialize.captured.tables.changelog.enabledoption to parse change events only for specified tables.Enable the
scan.parallel-deserialize-changelog.enabledoption to use multiple threads to parse the binary log file and deliver events to the consumer queue in order. When you enable this option, you usually need to increase theTaskManager CPUas well.
Optimize Debezium parameters
debezium.max.queue.size: 162580 debezium.max.batch.size: 40960 debezium.poll.interval.ms: 50debezium.max.queue.size: The maximum number of records that the blocking queue can hold. When Debezium reads an event stream from the database, it places the events in a blocking queue before writing them downstream. The default value is 8192.debezium.max.batch.size: The maximum number of events that the connector processes in each iteration. The default value is 2048.debezium.poll.interval.ms: The number of milliseconds the connector should wait before it requests new change events. The default value is 1000 milliseconds, or 1 second.
Usage example:
CREATE TABLE mysql_source (...) WITH (
'connector' = 'mysql-cdc',
-- Debezium configuration
'debezium.max.queue.size' = '162580',
'debezium.max.batch.size' = '40960',
'debezium.poll.interval.ms' = '50',
-- Enable parsing filter
'scan.only.deserialize.captured.tables.changelog.enabled' = 'true', -- Parse only the change events of specified tables.
...
)source:
type: mysql
name: MySQL Source
hostname: ${mysql.hostname}
port: ${mysql.port}
username: ${mysql.username}
password: ${mysql.password}
tables: ${mysql.source.table}
server-id: 7601-7604
# Debezium configuration
debezium.max.queue.size: 162580
debezium.max.batch.size: 40960
debezium.poll.interval.ms: 50
# Enable parsing filter
scan.only.deserialize.captured.tables.changelog.enabled: trueThe binary log consumption capacity of the MySQL CDC Enterprise Edition is 85 MB/s, which is about twice that of the open source community version. When the generation speed of binary log files exceeds 85 MB/s (that is, one 512 MB file every 6 seconds), the latency of the Flink job continues to increase. The processing latency gradually decreases after the binary log file generation speed slows down. If a binary log file contains a large transaction, the processing latency may temporarily increase. The latency decreases after the log for that transaction is read.
Diagnose data latency to optimize job throughput
If you experience data latency during the incremental phase, analyze the issue by following these steps:
Check the
currentFetchEventTimeLagandcurrentEmitEventTimeLagmetrics on the Overview page. ThecurrentFetchEventTimeLagmetric represents the latency in reading data from the binary log. ThecurrentEmitEventTimeLagmetric represents the latency in reading data for the tables relevant to the job from the binary log.Scenario
Description
currentFetchEventTimeLagis low, whilecurrentEmitEventTimeLagis high and rarely updates.A low
currentFetchEventTimeLagindicates that pulling the binary log from the database is efficient. However, the binary log contains little data for the tables that the job needs to read. Therefore,currentEmitEventTimeLagrarely updates. This is expected behavior.Both
currentFetchEventTimeLagandcurrentEmitEventTimeLagare high.This indicates that the source table has poor read performance. You can proceed to the subsequent steps in this section for optimization.
Backpressure can reduce the rate at which the source sends data to downstream operators. You may observe that sourceIdleTime periodically increases, and both currentFetchEventTimeLag and currentEmitEventTimeLag continuously grow. To resolve this, increase the parallelism of the node where the backpressure originates.
Check the TM CPU Usage metric on the CPU page and the TM GC Time metric on the JVM page to determine if there are insufficient CPU or memory resources. You can increase job resources to optimize read performance. You can also enable mini-batch parameters to improve throughput. For more information, see High-Performance Flink SQL Optimization Techniques.
If a SinkUpsertMaterializer operator with a large state exists in the job, it can affect read performance. Consider increasing the job parallelism or avoiding the SinkUpsertMaterializer operator. For more information, see Avoid using SinkUpsertMaterializer. Removing the SinkUpsertMaterializer operator from an existing job requires a stateless restart. This is because the job topology changes, and starting from the existing state may cause the job to fail or result in data loss.
Set server ID to avoid binlog conflicts
Each client that synchronizes data from a database has a unique ID called the server ID. If different jobs use the same server ID, conflicts can occur and cause job failures. We recommend that you assign a different server ID for each MySQL CDC data source.
How to configure the server ID
You can specify the server ID in a Flink table DDL statement or by using SQL Hints.
We recommend using SQL Hints to configure the server ID instead of specifying it in the WITH clause of the table DDL. For more information, see SQL Hints.
server ID configuration for different scenarios
Incremental snapshot disabled or parallelism is 1
If incremental snapshot is disabled or the parallelism is 1, you can specify a single server ID.
SELECT * FROM source_table /*+ OPTIONS('server-id'='123456') */ ;Incremental snapshot enabled and parallelism is greater than 1
When the incremental snapshot is enabled and the parallelism is greater than 1, you must specify a server ID range. The number of available server IDs in the range must be at least the parallelism. For example, if the parallelism is 3, you can use the following configuration:
SELECT * FROM source_table /*+ OPTIONS('server-id'='123456-123458') */ ;Data synchronization with CTAS
When you synchronize data by using CREATE TABLE AS (CTAS), CDC data sources with identical configurations are automatically merged and reused. In this case, you can assign the same server ID to multiple CDC data sources. For more information, see Example 4: Multiple CTAS Statements.
A job with multiple MySQL CDC source tables (non-CTAS)
If a job contains multiple MySQL CDC source tables, does not use CTAS statements, and has source reuse disabled, you must provide a different server ID for each CDC source table. Similarly, if the incremental snapshot is enabled and the parallelism is greater than 1, you must specify a server ID range.
select * from source_table1 /*+ OPTIONS('server-id'='123456-123457') */ left join source_table2 /*+ OPTIONS('server-id'='123458-123459') */ on source_table1.id=source_table2.id;
Set chunk parameters to optimize memory usage
When a MySQL CDC source table starts, it performs a full table scan, splits the table into multiple chunks based on the primary key, and records the current binary log position. The job then uses an incremental snapshot algorithm to read data from each chunk sequentially by using SELECT statements. The job periodically performs a checkpoint to record completed chunks. In the event of a failover, it resumes reading from the first unfinished chunk. After all chunks are read, the job switches to reading incremental changes from the previously recorded binary log position. The Flink job performs periodic checkpoints to save the binary log position. If a failover occurs, the job resumes processing from the last saved position, thus achieving exactly-once semantics.
For more details on the incremental snapshot algorithm, see MySQL CDC Connector.
For tables with a single-column primary key, chunks are split based on that key by default. For tables with a composite primary key, the first column of the primary key is used for splitting by default. Ververica Runtime (VVR) 6.0.7 and later supports reading source tables without a primary key. You must set the scan.incremental.snapshot.chunk.key-column parameter to specify a non-nullable column for splitting.
Chunk parameter optimization
Chunk data and metadata are stored in memory, which can sometimes lead to out-of-memory (OOM) errors. You can adjust parameters based on which component experiences the OOM error:
JobManager
The JobManager stores metadata for all chunks. An excessive number of chunks can cause an OOM error. To resolve this, increase the value of
scan.incremental.snapshot.chunk.sizeto reduce the number of chunks. Alternatively, you can increase the JobManager heap memory by settingjobmanager.memory.heap.sizein your runtime configuration. For more information, see Flink Parameter Configuration.TaskManager
The TaskManager reads the data for each chunk. If a chunk contains too many rows, an OOM error can occur. To resolve this, decrease the value of
scan.incremental.snapshot.chunk.sizeto reduce the number of rows per chunk. You can also increase the TaskManager heap memory by increasing theTaskManager Memoryvalue in your runtime configuration.In VVR 8.0.8 and earlier, the last chunk may contain a large amount of data, which can cause the TaskManager to experience an OOM error. We recommend upgrading to VVR 8.0.9 or later to avoid this issue.
For a MySQL CDC source table with a composite primary key, chunks are split based on the first column of the key by default. If data is significantly skewed, with many rows sharing the same value in that column, the chunk for that value can become very large and cause an OOM error in the TaskManager. You can set
scan.incremental.snapshot.chunk.key-columnto specify a different column from the primary key for splitting.
Accelerate reads in the snapshot phase
During the snapshot phase, the MySQL source table reads snapshot data through a JDBC connection. Use the following methods to accelerate reads during this phase.
Increase the source parallelism to speed up reads during the snapshot phase.
Increase the value of
scan.incremental.snapshot.chunk.sizeto fetch more data in a single chunk.If the downstream result table has a primary key and supports idempotent writes, you can enable
scan.incremental.snapshot.backfill.skipto skip reading the binary log for the backfill part. This speeds up processing during the snapshot phase.
Enable source reuse to reduce binlog connections
When a job includes multiple MySQL source tables, you can enable source reuse to reduce the database load by sharing a single binary log connection. This feature is available only in Realtime Compute for Apache Flink and is not supported in the community edition of the MySQL CDC connector.
Enable the source reuse feature in an SQL job by using the SET command:
SET 'table.optimizer.source-merge.enabled' = 'true';We recommend enabling source reuse only for new jobs. If you enable source reuse for an existing job, you must perform a stateless restart. This is because source reuse changes the job topology, and starting from an existing state may cause the job to fail or result in data loss.
After you enable source reuse, MySQL source tables with the same configuration parameters are merged. If all source tables in your job share the same configuration, the number of binary log connections is calculated as follows:
During the snapshot phase, the number of binary log connections is equal to the source parallelism.
During the incremental phase, the number of binary log connections is 1.
In VVR 8.0.8 and 8.0.9, you must also set
SET 'sql-gateway.exec-plan.enabled' = 'false';when you enable CDC source reuse.After enabling CDC source reuse, do not set the
pipeline.operator-chainingjob option to false. Breaking the operator chain adds serialization and deserialization overhead for data sent from the source to downstream operators. The more sources that are merged, the greater the overhead.In Ververica Runtime (VVR) 8.0.7, setting
pipeline.operator-chainingto false causes a serialization issue.
Read archived binlogs from OSS
When you use an ApsaraDB RDS for MySQL instance as a data source, you can read log backups stored in OSS. If the file corresponding to the specified timestamp or binary log position is stored in OSS, Flink automatically pulls the log file from OSS to the cluster. If the file is stored locally in the database, Flink automatically switches to reading through a database connection. This feature is available only in Realtime Compute for Apache Flink and is not supported in the community edition of the MySQL CDC connector.
To enable reading from OSS log backups, you must configure the ApsaraDB RDS for MySQL connection parameters. Example:
CREATE TABLE mysql_source (...) WITH (
'connector' = 'mysql-cdc',
'rds.region-id' = 'cn-beijing',
'rds.access-key-id' = 'your_access_key_id',
'rds.access-key-secret' = 'your_access_key_secret',
'rds.db-instance-id' = 'rm-xxxxxxxx', // The ID of the database instance.
'rds.main-db-id' = '12345678', // The ID of the primary database.
'rds.endpoint' = 'rds.aliyuncs.com'
...
)FAQ
For more information about problems you may encounter when using CDC source tables, see CDC FAQ.