github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/docs/design/2023-03-15-ticdc-storage-sink.md (about) 1 # TiCDC Design Documents 2 3 - Author(s): [CharlesCheung](https://github.com/CharlesCheung96), [zhaoxinyu](https://github.com/zhaoxinyu) 4 - Tracking Issue: https://github.com/pingcap/tiflow/issues/6797 5 6 ## Table of Contents 7 8 - [Introduction](#introduction) 9 - [Motivation or Background](#motivation-or-background) 10 - [Detailed Design](#detailed-design) 11 - [Storage path structure](#storage-path-structure) 12 - [Data change records](#data-change-records) 13 - [Index files](#index-files) 14 - [Metadata](#metadata) 15 - [DDL events](#ddl-events) 16 - [Data type in schema](#data-type-in-schema) 17 - [Integer types](#integer-types) 18 - [Decimal types](#decimal-types) 19 - [Date and time types](#date-and-time-types) 20 - [String types](#string-types) 21 - [Enum and Set types](#enum-and-set-types) 22 - [Protocols](#protocols) 23 - [CSV](#csv) 24 - [Canal json](#canal-json) 25 - [Test Design](#test-design) 26 - [Functional Tests](#functional-tests) 27 - [Scenario Tests](#scenario-tests) 28 - [Compatibility Tests](#compatibility-tests) 29 - [Benchmark Tests](#benchmark-tests) 30 - [Impacts & Risks](#impacts--risks) 31 - [Investigation & Alternatives](#investigation--alternatives) 32 - [Unresolved Questions](#unresolved-questions) 33 34 ## Introduction 35 36 This document provides a complete design on implementing storage sink, which provides 37 the ability to output changelogs to NFS, Amazon S3, GCP and Azure Blob Storage. 38 39 ## Motivation or Background 40 41 External storage services, such as Amazon S3, GCP and Azure Blob Storage, are designed 42 to handle large volumes of data and provide high availability and durability. By 43 leveraging such services, TiCDC can provide a scalable and cost-effective way to 44 store and manage TiDB's incremental changelogs, and enable users to build flexible 45 end-to-end data integration pipelines that can support a wide range of use cases 46 and scenarios. 47 48 ## Detailed Design 49 50 ### Storage path structure 51 52 This section describes the storage path structure of data change records, metadata, and DDL events. 53 Using the csv protocol as an example, files containing row change events should be organized as follows: 54 55 ``` 56 s3://bucket/prefix1/prefix2 <prefix> 57 ├── metadata 58 └── schema1 <schema> 59 ├── meta 60 │ └── schema_441349361156227000_3233644819.json [database schema file] 61 └── table1 <table> 62 │── meta 63 │ └── schema_441349361156227074_3131721815.json [table schema file] 64 └── 441349361156227074 <table-version-separator> 65 └── 13 <partition-separator, optional> 66 ├── 2023-05-09 <date-separator, optional> 67 │ ├── CDC00000000000000000001.csv 68 │ └── meta 69 │ └── CDC.index 70 └── 2023-05-10 <date-separator, optional> 71 ├── CDC00000000000000000001.csv 72 └── meta 73 └── CDC.index 74 ``` 75 76 #### Data change records 77 78 Data change records are saved to the following path: 79 80 ```shell 81 {scheme}://{prefix}/{schema}/{table}/{table-version-separator}/{partition-separator}/{date-separator}/CDC{num}.{extension} 82 ``` 83 84 - `scheme`: specifies the data transmission protocol, or the storage type, for example, <code>**s3**://xxxxx</code>. 85 - `prefix`: specifies the user-defined parent directory, for example, <code>s3://**bucket/prefix1/prefix2**</code>. 86 - `schema`: specifies the schema name, for example, <code>s3://bucket/prefix1/prefix2/**schema1**</code>. 87 - `table`: specifies the table name, for example, <code>s3://bucket/prefix1/prefix2/schema1/**table1**</code>. 88 - `table-version-separator`: specifies the separator that separates the path by the table version, for example, <code>s3://bucket/prefix1/prefix2/schema1/table1/**441349361156227074**</code>. 89 - `partition-separator`: specifies the separator that separates the path by the table partition, for example, <code>s3://bucket/prefix1/prefix2/schema1/table1/441349361156227074/**13**</code>. 90 - `date-separator`: classifies the files by the transaction commit date. Value options are: 91 - `none`: no `date-separator`. For example, all files with `test.table1` version being `441349361156227074` are saved to `s3://bucket/prefix1/prefix2/schema1/table1/441349361156227074`. 92 - `year`: the separator is the year of the transaction commit date, for example, <code>s3://bucket/prefix1/prefix2/schema1/table1/441349361156227074/**2022**</code>. 93 - `month`: the separator is the year and month of the transaction commit date, for example, <code>s3://bucket/prefix1/prefix2/schema1/table1/441349361156227074/**2022-05**</code>. 94 - `day`: the separator is the year, month, and day of the transaction commit date, for example, <code>s3://bucket/prefix1/prefix2/schema1/table1/441349361156227074/**2022-05-09**</code>. 95 - `num`: saves the serial number of the file that records the data change, for example, <code>s3://bucket/prefix1/prefix2/schema1/table1/441349361156227074/2022-01-02/CDC**000001**.csv</code>. 96 - `extension`: specifies the extension of the file. TiDB v6.5.0 supports the CSV and Canal-JSON formats. 97 98 > **Note:** 99 > 100 > The table version changes only after a DDL operation is performed, the table version is the TSO when the DDL is executed in the upstream TiDB. However, the change of the table version does not mean the change of the table schema. For example, adding a comment to a column does not cause the schema file content to change. 101 102 #### Index files 103 104 An index file is used to prevent written data from being overwritten by mistake. It is stored in the same path as the data change record. 105 106 ```shell 107 {scheme}://{prefix}/{schema}/{table}/{table-version-separator}/{partition-separator}/{date-separator}/meta/CDC.index 108 ``` 109 110 An index file records the largest file name used in the current directory. For example: 111 112 ``` 113 CDC000005.csv 114 ``` 115 116 In this example, the files CDC000001.csv through CDC000004.csv in this directory are occupied. When a table scheduling or node restart occurs in the TiCDC cluster, the new node reads the index file and determines if CDC000005.csv is occupied. If it is not occupied, the new node writes the file starting from CDC000005.csv. If it is occupied, it starts writing from CDC000006.csv, which prevents overwriting data written by other nodes. 117 118 #### Metadata 119 120 Metadata is saved in the following path: 121 122 ```shell 123 {protocol}://{prefix}/metadata 124 ``` 125 126 Metadata is a JSON-formatted file, for example: 127 128 ```json 129 { 130 "checkpoint-ts": 433305438660591626 131 } 132 ``` 133 134 - `checkpoint-ts`: Transactions with `commit-ts` smaller than `checkpoint-ts` are written to the target storage in the downstream. 135 136 #### DDL events 137 138 ##### Table DDL events 139 140 When DDL events cause the table version to change, TiCDC switches to a new path to write data change records. For example, when the version of `test.table1` changes to `441349361156227074`, data will be written to the path `s3://bucket/prefix1/prefix2/schema1/table1/441349361156227074/2022-01-02/CDC000001.csv`. In addition, when DDL events occur, TiCDC generates a file to save the table schema information. 141 142 Table schema information is saved in the following path: 143 144 ```shell 145 {scheme}://{prefix}/{schema}/{table}/meta/schema_{table-version}_{hash}.json 146 ``` 147 148 The following is a table schema file named `schema_441349361156227074_3131721815.json`: 149 150 ```json 151 { 152 "Table": "table1", 153 "Schema": "schema1", 154 "Version": 1, 155 "TableVersion": 441349361156227074, 156 "Query": "ALTER TABLE schema1.table1 ADD OfficeLocation blob(20)", 157 "Type": 5, 158 "TableColumns": [ 159 { 160 "ColumnName": "Id", 161 "ColumnType": "INT", 162 "ColumnNullable": "false", 163 "ColumnIsPk": "true" 164 }, 165 { 166 "ColumnName": "LastName", 167 "ColumnType": "CHAR", 168 "ColumnLength": "20" 169 }, 170 { 171 "ColumnName": "FirstName", 172 "ColumnType": "VARCHAR", 173 "ColumnLength": "30" 174 }, 175 { 176 "ColumnName": "HireDate", 177 "ColumnType": "DATETIME" 178 }, 179 { 180 "ColumnName": "OfficeLocation", 181 "ColumnType": "BLOB", 182 "ColumnLength": "20" 183 } 184 ], 185 "TableColumnsTotal": "5" 186 } 187 ``` 188 189 - `Table`: Table name. 190 - `Schema`: Schema name. 191 - `Version`: Protocol version of the storage sink. 192 - `TableVersion`: Table version. 193 - `Query`:DDL statement. 194 - `Type`: Type of DDL event. 195 - `TableColumns`: An array of one or more maps, each of which describes a column in the source table. 196 - `ColumnName`: Column name. 197 - `ColumnType`: Column type. For details, see [Data type](#data-type). 198 - `ColumnLength`: Column length. For details, see [Data type](#data-type). 199 - `ColumnPrecision`: Column precision. For details, see [Data type](#data-type). 200 - `ColumnScale`: The number of digits following the decimal point (the scale). For details, see [Data type](#data-type). 201 - `ColumnNullable`: The column can be NULL when the value of this option is `true`. 202 - `ColumnIsPk`: The column is part of the primary key when the value of this option is `true`. 203 - `TableColumnsTotal`: The size of the `TableColumns` array. 204 205 ##### Schema DDL events 206 207 Database schema information is saved in the following path: 208 209 ```shell 210 {scheme}://{prefix}/{schema}/meta/schema_{table-version}_{hash}.json 211 ``` 212 213 The following is a database schema file named `schema_441349361156227000_3131721815.json`: 214 215 ```json 216 { 217 "Table": "", 218 "Schema": "schema1", 219 "Version": 1, 220 "TableVersion": 441349361156227000, 221 "Query": "CREATE DATABASE `schema1`", 222 "Type": 1, 223 "TableColumns": null, 224 "TableColumnsTotal": 0 225 } 226 ``` 227 228 ### Data type in schema 229 230 This section describes the data types used in the schema file. The data types are defined as `T(M[, D])`. 231 232 #### Integer types 233 234 Integer types in TiDB are defined as `IT[(M)] [UNSIGNED]`, where 235 236 - `IT` is the integer type, which can be `TINYINT`, `SMALLINT`, `MEDIUMINT`, `INT`, `BIGINT`, or `BIT`. 237 - `M` is the display width of the type. 238 239 Integer types are defined as follows in schema: 240 241 ```json 242 { 243 "ColumnName": "COL1", 244 "ColumnType": "{IT} [UNSIGNED]", 245 "ColumnPrecision": "{M}" 246 } 247 ``` 248 249 #### Decimal types 250 251 Decimal types in TiDB are defined as `DT[(M,D)][UNSIGNED]`, where 252 253 - `DT` is the floating-point type, which can be `FLOAT`, `DOUBLE`, `DECIMAL`, or `NUMERIC`. 254 - `M` is the precision of the data type, or the total number of digits. 255 - `D` is the number of digits following the decimal point. 256 257 Decimal types are defined as follows in schema file: 258 259 ```json 260 { 261 "ColumnName": "COL1", 262 "ColumnType": "{DT} [UNSIGNED]", 263 "ColumnPrecision": "{M}", 264 "ColumnScale": "{D}" 265 } 266 ``` 267 268 #### Date and time types 269 270 Date types in TiDB are defined as `DT`, where 271 272 - `DT` is the date type, which can be `DATE` or `YEAR`. 273 274 The date types are defined as follows in schema file: 275 276 ```json 277 { 278 "ColumnName": "COL1", 279 "ColumnType": "{DT}" 280 } 281 ``` 282 283 The time types in TiDB are defined as `TT[(M)]`, where 284 285 - `TT` is the time type, which can be `TIME`, `DATETIME`, or `TIMESTAMP`. 286 - `M` is the precision of seconds in the range from 0 to 6. 287 288 The time types are defined as follows in schema file: 289 290 ```json 291 { 292 "ColumnName": "COL1", 293 "ColumnType": "{TT}", 294 "ColumnScale": "{M}" 295 } 296 ``` 297 298 #### String types 299 300 The string types in TiDB are defined as `ST[(M)]`, where 301 302 - `ST` is the string type, which can be `CHAR`, `VARCHAR`, `TEXT`, `BINARY`, `BLOB`, or `JSON`. 303 - `M` is the maximum length of the string. 304 305 The string types are defined as follows in schema file: 306 307 ```json 308 { 309 "ColumnName": "COL1", 310 "ColumnType": "{ST}", 311 "ColumnLength": "{M}" 312 } 313 ``` 314 315 #### Enum and Set types 316 317 The Enum and Set types are defined as follows in schema file: 318 319 ```json 320 { 321 "ColumnName": "COL1", 322 "ColumnType": "{ENUM/SET}" 323 } 324 ``` 325 326 ### Protocols 327 328 #### CSV 329 330 ##### Transactional constraints 331 332 - In a single CSV file, the commit-ts of a row is equal to or smaller than that of the subsequent row. 333 - The same transactions of a single table are stored in the same CSV file when `transaction-atomicity` is set to table level. 334 - Multiple tables of the same transaction can be stored in different CSV files. 335 336 ##### Definition of the data format 337 338 In the CSV file, each column is defined as follows: 339 340 - Column 1: The operation-type indicator, including `I`, `U`, and `D`. `I` means `INSERT`, `U` means `UPDATE`, and `D` means `DELETE`. 341 - Column 2: Table name. 342 - Column 3: Schema name. 343 - Column 4: The `commit-ts` of the source transaction. This column is optional. 344 - Column 5 to the last column: One or more columns that represent data to be changed. 345 346 Assume that table `hr.employee` is defined as follows: 347 348 ```sql 349 CREATE TABLE `employee` ( 350 `Id` int NOT NULL, 351 `LastName` varchar(20) DEFAULT NULL, 352 `FirstName` varchar(30) DEFAULT NULL, 353 `HireDate` date DEFAULT NULL, 354 `OfficeLocation` varchar(20) DEFAULT NULL 355 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 356 ``` 357 358 The DML events of this table are stored in the CSV format as follows: 359 360 ```shell 361 "I","employee","hr",433305438660591626,101,"Smith","Bob","2014-06-04","New York" 362 "U","employee","hr",433305438660591627,101,"Smith","Bob","2015-10-08","Los Angeles" 363 "D","employee","hr",433305438660591629,101,"Smith","Bob","2017-03-13","Dallas" 364 "I","employee","hr",433305438660591630,102,"Alex","Alice","2017-03-14","Shanghai" 365 "U","employee","hr",433305438660591630,102,"Alex","Alice","2018-06-15","Beijing" 366 ``` 367 368 ##### Data type mapping 369 370 | MySQL type | CSV type | Example | Description | 371 | ----------------------------------------------------------------- | -------- | ------------------------------ | ---------------------------------- | 372 | `BOOLEAN`/`TINYINT`/`SMALLINT`/`INT`/`MEDIUMINT`/`BIGINT` | Integer | `123` | - | 373 | `FLOAT`/`DOUBLE` | Float | `153.123` | - | 374 | `NULL` | Null | `\N` | - | 375 | `TIMESTAMP`/`DATETIME` | String | `"1973-12-30 15:30:00.123456"` | Format: `yyyy-MM-dd HH:mm:ss.%06d` | 376 | `DATE` | String | `"2000-01-01"` | Format: `yyyy-MM-dd` | 377 | `TIME` | String | `"23:59:59"` | Format: `yyyy-MM-dd` | 378 | `YEAR` | Integer | `1970` | - | 379 | `VARCHAR`/`JSON`/`TINYTEXT`/`MEDIUMTEXT`/`LONGTEXT`/`TEXT`/`CHAR` | String | `"test"` | UTF-8 encoded | 380 | `VARBINARY`/`TINYBLOB`/`MEDIUMBLOB`/`LONGBLOB`/`BLOB`/`BINARY` | String | `"6Zi/5pav"` | base64 encoded | 381 | `BIT` | Integer | `81` | - | 382 | `DECIMAL` | String | `"129012.1230000"` | - | 383 | `ENUM` | String | `"a"` | - | 384 | `SET` | String | `"a,b"` | - | 385 386 #### Canal json 387 388 Storage sink uses the same canal-json protocol as the mq sink. The [official documentation](https://docs.pingcap.com/tidb/dev/ticdc-canal-json/) shows how the Canal-JSON data format is implemented in TiCDC, including the TiDB extended fields, the definition of the Canal-JSON data format, and the comparison with the official Canal. 389 390 ## Test Design 391 392 Storage sink is a new feature, For tests, we focus on the functional tests, scenario tests and benchmark. 393 394 ### Functional Tests 395 396 - Regular unit testing and integration testing cover the correctness of data replication using csv and canal-json protocol. 397 - Manually test the availability and correctness of data synchronization using different external storage. 398 399 ### Scenario Tests 400 401 Run stability and chaos tests under different workloads. 402 403 - The upstream and downstream data are consistent. 404 - Throughput and latency are stable for most scenarios. 405 406 ### Compatibility Tests 407 408 #### Compatibility with other features/components 409 410 Should be compatible with other features. 411 412 #### Upgrade Downgrade Compatibility 413 414 Storage sink is a new feature, so there should be no upgrade 415 or downgrade compatibility issues. 416 417 ### Benchmark Tests 418 419 Perform benchmark tests under common scenarios, big data scenarios, multi-table scenarios, and wide table scenarios with different parameters. 420 421 ## Impacts & Risks 422 423 N/A 424 425 ## Investigation & Alternatives 426 427 N/A 428 429 ## Unresolved Questions 430 431 N/A