diff --git a/TOC.md b/TOC.md index 78f0453fc009..e70fcfa3ce8c 100644 --- a/TOC.md +++ b/TOC.md @@ -565,6 +565,7 @@ - [双向复制](/ticdc/ticdc-bidirectional-replication.md) - [单行数据正确性校验](/ticdc/ticdc-integrity-check.md) - [主从集群一致性读和数据校验](/ticdc/ticdc-upstream-downstream-check.md) + - [TiCDC 行为变更说明](/ticdc/ticdc-behavior-change.md) - 监控告警 - [基本监控指标](/ticdc/ticdc-summary-monitor.md) - [详细监控指标](/ticdc/monitor-ticdc.md) diff --git a/releases/release-6.5.3.md b/releases/release-6.5.3.md index da0678d22a1f..483ab44407e8 100644 --- a/releases/release-6.5.3.md +++ b/releases/release-6.5.3.md @@ -11,6 +11,12 @@ TiDB 版本:6.5.3 试用链接:[快速体验](https://docs.pingcap.com/zh/tidb/v6.5/quick-start-with-tidb) | [生产部署](https://docs.pingcap.com/zh/tidb/v6.5/production-deployment-using-tiup) | [下载离线包](https://cn.pingcap.com/product-community/?version=v6.5.3#version-list) +## 兼容性变更 + +### 行为变更 + +- TiCDC 在处理 Update 事件时,如果事件的主键或者非空唯一索引的列值发生改变,则会将该条事件拆分为 Delete 和 Insert 两条事件。更多信息,请参考[用户文档](/ticdc/ticdc-behavior-change.md#含有单条-update-变更的事务拆分)。 + ## 改进提升 + TiDB diff --git a/releases/release-6.5.4.md b/releases/release-6.5.4.md index 83cc26952dad..f86ed62c9295 100644 --- a/releases/release-6.5.4.md +++ b/releases/release-6.5.4.md @@ -16,6 +16,10 @@ TiDB 版本:6.5.4 - 为了修复当使用 `Cursor Fetch` 获取大结果集时 TiDB 占用大量内存的问题,TiDB 会自动将结果集写入磁盘以释放内存资源 [#43233](https://github.com/pingcap/tidb/issues/43233) @[YangKeao](https://github.com/YangKeao) - 默认关闭 RocksDB 的周期性 compaction,使 TiKV RocksDB 的默认行为和 v6.5.0 之前的版本保持一致,避免在升级之后集中产生大量 compaction 影响系统的性能。同时,TiKV 新增 [`rocksdb.[defaultcf|writecf|lockcf].periodic-compaction-seconds`](https://docs.pingcap.com/zh/tidb/v6.5/tikv-configuration-file#periodic-compaction-seconds-从-v654-版本开始引入) 和 [`rocksdb.[defaultcf|writecf|lockcf].ttl`](https://docs.pingcap.com/zh/tidb/v6.5/tikv-configuration-file#ttl-从-v654-版本开始引入) 配置项,支持手动配置 RocksDB 的周期性 compaction [#15355](https://github.com/tikv/tikv/issues/15355) @[LykxSassinator](https://github.com/LykxSassinator) +### 行为变更 + +- 对于包含多条变更的事务,如果 Update 事件的主键或者非空唯一索引的列值发生改变,TiCDC 会将该其拆分为 Delete 和 Insert 两条事件,并确保将所有事件有序,以保证 Delete 事件在 Insert 事件之前。更多信息,请参考[用户文档](/ticdc/ticdc-behavior-change.md#含有多条-update-变更的事务拆分)。 + ## 改进提升 + TiDB diff --git a/releases/release-7.1.1.md b/releases/release-7.1.1.md index ae1df5f8d2a9..1b5daa051341 100644 --- a/releases/release-7.1.1.md +++ b/releases/release-7.1.1.md @@ -15,6 +15,10 @@ TiDB 版本:7.1.1 - TiDB 新增 `tidb_lock_unchanged_keys` 变量用于控制是否对于没有修改的 key 加锁 [#44714](https://github.com/pingcap/tidb/issues/44714) @[ekexium](https://github.com/ekexium) +### 行为变更 + +- TiCDC 在处理 Update 事件时,如果事件的主键或者非空唯一索引的列值发生改变,则会将该条事件拆分为 Delete 和 Insert 两条事件。更多信息,请参考[用户文档](/ticdc/ticdc-behavior-change.md#含有单条-update-变更的事务拆分)。 + ## 改进提升 + TiDB diff --git a/releases/release-7.1.2.md b/releases/release-7.1.2.md index dd2f2c70b3a3..0f0a8478c372 100644 --- a/releases/release-7.1.2.md +++ b/releases/release-7.1.2.md @@ -20,6 +20,10 @@ TiDB 版本:7.1.2 - 新增 TiCDC 配置项 [`sink.csv.binary-encoding-method`](/ticdc/ticdc-changefeed-config.md#ticdc-changefeed-配置文件说明),控制 CSV 协议中二进制类型数据的编码方式,默认值为 `'base64'` [#9373](https://github.com/pingcap/tiflow/issues/9373) @[CharlesCheung96](https://github.com/CharlesCheung96) - 新增 TiCDC 配置项 [`large-message-handle-option`](/ticdc/ticdc-sink-to-kafka.md#处理超过-kafka-topic-限制的消息)。默认为空,即消息大小超过 Kafka Topic 的限制后,同步任务失败。设置为 "handle-key-only" 时,如果消息超过大小,只发送 handle key 以减少消息的大小;如果依旧超过大小,则同步任务失败 [#9680](https://github.com/pingcap/tiflow/issues/9680) @[3AceShowHand](https://github.com/3AceShowHand) +### 行为变更 + +- 对于包含多条变更的事务,如果 Update 事件的主键或者非空唯一索引的列值发生改变,TiCDC 会将该其拆分为 Delete 和 Insert 两条事件,并确保将所有事件有序,以保证 Delete 事件在 Insert 事件之前。更多信息,请参考[用户文档](/ticdc/ticdc-behavior-change.md#含有多条-update-变更的事务拆分)。 + ## 改进提升 + TiDB diff --git a/releases/release-7.2.0.md b/releases/release-7.2.0.md index e64bb0f67314..90fb7bd3b88a 100644 --- a/releases/release-7.2.0.md +++ b/releases/release-7.2.0.md @@ -170,6 +170,10 @@ TiDB 版本:7.2.0 > > 以下为从 v7.1.0 升级至当前版本 (v7.2.0) 所需兼容性变更信息。如果从 v7.0.0 或之前版本升级到当前版本,可能也需要考虑和查看中间版本 release notes 中提到的兼容性变更信息。 +### 行为变更 + +- TiCDC 在处理 Update 事件时,如果事件的主键或者非空唯一索引的列值发生改变,则会将该条事件拆分为 Delete 和 Insert 两条事件。更多信息,请参考[用户文档](/ticdc/ticdc-behavior-change.md#含有单条-update-变更的事务拆分)。 + ### 系统变量 | 变量名 | 修改类型 | 描述 | diff --git a/releases/release-7.4.0.md b/releases/release-7.4.0.md index 76838d22f088..27333dc431a2 100644 --- a/releases/release-7.4.0.md +++ b/releases/release-7.4.0.md @@ -285,6 +285,7 @@ TiDB 版本:7.4.0 - 新增函数 [`TIDB_PARSE_TSO_LOGICAL()`](/functions-and-operators/tidb-functions.md#tidb-特有的函数),用于从 TiDB TSO 时间戳中提取逻辑时间戳。 - 新增表 [`information_schema.CHECK_CONSTRAINTS`](/information-schema/information-schema-check-constraints.md),提高与 MySQL 8.0 的兼容性。 +- 对于包含多条变更的事务,如果 Update 事件的主键或者非空唯一索引的列值发生改变,TiCDC 会将该其拆分为 Delete 和 Insert 两条事件,并确保将所有事件有序,以保证 Delete 事件在 Insert 事件之前。更多信息,请参考[用户文档](/ticdc/ticdc-behavior-change.md#含有多条-update-变更的事务拆分)。 ### 系统变量 diff --git a/ticdc/ticdc-behavior-change.md b/ticdc/ticdc-behavior-change.md new file mode 100644 index 000000000000..f3f13f8eb595 --- /dev/null +++ b/ticdc/ticdc-behavior-change.md @@ -0,0 +1,54 @@ +--- +title: TiCDC 行为变更说明 +summary: 介绍 TiCDC changefeed 的行为变更,说明变更原因以及影响范围。 +--- + +# TiCDC 行为变更说明 + +## 将 Update 事件拆分为 Delete 和 Insert 事件 + +### 含有单条 Update 变更的事务拆分 + +从 v6.5.3、v7.1.1 和 v7.2.0 开始,使用非 MySQL Sink 时,对于仅包含一条 Update 变更的事务,如果 Update 事件的主键或者非空唯一索引的列值发生改变,TiCDC 会将该条事件拆分为 Delete 和 Insert 两条事件。详情见 GitHub issue [#9086](https://github.com/pingcap/tiflow/issues/9086)。 + +该变更主要为了解决如下问题: + +* 在使用 CSV 和 AVRO 协议时,仅输出新值而不输出旧值。因此,当主键或者非空唯一索引的列值发生改变时,消费者只能接收到变化后的新值,无法得到旧值,导致无法处理变更前的值(例如删除旧值)。 +* 在使用 Index value dispatcher 将数据按照 Key 分发到不同的 Kafka partition 时,下游的消费者组内多个消费者进程独立消费 Kafka Topic partition,由于消费进度不同,可能导致数据不一致的问题。 + +以如下 SQL 为例: + +```sql +CREATE TABLE t (a INT PRIMARY KEY, b INT); +INSERT INTO t VALUES (1, 1); +UPDATE t SET a = 2 WHERE a = 1; +``` + +在上述示例中,主键 `a` 的值从 `1` 修改为 `2`。如果不将该 Update 事件进行拆分: + +* 在使用 CSV 和 AVRO 协议时,消费者仅能看到新值 `a = 2`,而无法得到旧值 `a = 1`。这可能导致下游消费者只插入了新值 `2`,而没有删除旧值 `1`。 +* 在使用 Index value dispatcher 时,插入记录 `(1, 1)` 的事件可能被发送到 Partition 0,而变更事件 `(2, 1)` 可能被发送到 Partition 1。如果 Partition 1 的消费进度快于 Partition 0,则可能由于下游数据系统中找不到相应数据而导致出错。因此,TiCDC 会将该条 Update 事件拆分为 Delete 和 Insert 两条事件,其中,删除记录 `(1, 1)` 被发送到 Partition 0,写入记录 `(2, 1)` 被发送到 Partition 1,以确保无论消费者的进度如何,事件都能被消费成功。 + +### 含有多条 Update 变更的事务拆分 + +从 v6.5.4、v7.1.2 和 v7.4.0 开始,对于一个含有多条变更的事务,如果 Update 事件的主键或者非空唯一索引的列值发生改变,TiCDC 会将该其拆分为 Delete 和 Insert 两条事件,并确保所有事件按照 Delete 事件在 Insert 事件之前的顺序进行排序。详情见 GitHub issue [#9430](https://github.com/pingcap/tiflow/issues/9430)。 + +该变更主要为了解决当使用 MySQL Sink 直接将这两条事件写入下游时,可能会出现主键冲突的问题,从而导致 changefeed 报错。 + +以如下 SQL 为例: + +```sql +CREATE TABLE t (a INT PRIMARY KEY, b INT); +INSERT INTO t VALUES (1, 1); +INSERT INTO t VALUES (2, 2); + +BEGIN; +UPDATE t SET a = 1 WHERE a = 3; +UPDATE t SET a = 2 WHERE a = 1; +UPDATE t SET a = 3 WHERE a = 2; +COMMIT; +``` + +在上述示例中,通过执行三条 SQL 语句对两行数据的主键进行交换,但 TiCDC 只会接收到两条 Update 变更事件,即将主键 `a` 从 `1` 变更为 `2`,将主键 `a` 从 `2` 变更为 `1`,如果 MYSQL Sink 直接将这两条 Update 事件写入下游,会出现主键冲突的问题,导致 changefeed 报错。 + +因此,TiCDC 会将这两条事件拆分为四条事件,即删除记录 `(1, 1)` 和 `(2, 2)` 以及写入记录 `(2, 1)` 和 `(1, 2)`。