From 9786bd2455f8091135db51ec25eb731072512110 Mon Sep 17 00:00:00 2001 From: Aolin Date: Mon, 26 Feb 2024 18:26:00 +0800 Subject: [PATCH 01/82] tidb: remove experimental warnings for stats lock (#16593) --- basic-features.md | 2 +- releases/release-7.4.0.md | 4 ++-- sql-statements/sql-statement-lock-stats.md | 4 ---- sql-statements/sql-statement-show-stats-locked.md | 4 ---- sql-statements/sql-statement-unlock-stats.md | 4 ---- statistics.md | 4 ---- 6 files changed, 3 insertions(+), 19 deletions(-) diff --git a/basic-features.md b/basic-features.md index 6a68246b8b849..909567ef55057 100644 --- a/basic-features.md +++ b/basic-features.md @@ -180,7 +180,7 @@ You can try out TiDB features on [TiDB Playground](https://play.tidbcloud.com/?u | [Collect statistics for `PREDICATE COLUMNS`](/statistics.md#collect-statistics-on-some-columns) | E | E | E | E | E | E | E | N | N | N | N | | [Control the memory quota for collecting statistics](/statistics.md#the-memory-quota-for-collecting-statistics) | E | E | E | E | E | N | N | N | N | N | N | | [Randomly sample about 10000 rows of data to quickly build statistics](/system-variables.md#tidb_enable_fast_analyze) | Deprecated | Deprecated | E | E | E | E | E | E | E | E | E | -| [Lock statistics](/statistics.md#lock-statistics) | E | E | E | E | N | N | N | N | N | N | N | +| [Lock statistics](/statistics.md#lock-statistics) | Y | Y | E | E | N | N | N | N | N | N | N | | [Lightweight statistics initialization](/statistics.md#load-statistics) | Y | Y | E | N | N | N | N | N | N | N | N | | [Show the progress of collecting statistics](/sql-statements/sql-statement-show-analyze-status.md) | Y | Y | N | N | N | N | N | N | N | N | N | diff --git a/releases/release-7.4.0.md b/releases/release-7.4.0.md index c9bc9287b1f1e..269e71620ff3c 100644 --- a/releases/release-7.4.0.md +++ b/releases/release-7.4.0.md @@ -185,9 +185,9 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.4/quick-start-with- For more information, see [documentation](/tidb-resource-control.md#manage-background-tasks). -* Enhance the ability to lock statistics [#46351](https://github.com/pingcap/tidb/issues/46351) @[hi-rustin](https://github.com/hi-rustin) +* Lock statistics becomes generally available (GA) [#46351](https://github.com/pingcap/tidb/issues/46351) @[hi-rustin](https://github.com/hi-rustin) - In v7.4.0, TiDB has enhanced the ability to [lock statistics](/statistics.md#lock-statistics). Now, to ensure operational security, locking and unlocking statistics require the same privileges as collecting statistics. In addition, TiDB supports locking and unlocking statistics for specific partitions, providing greater flexibility. If you are confident in queries and execution plans in the database and want to prevent any changes from occurring, you can lock statistics to enhance stability. + In v7.4.0, [lock statistics](/statistics.md#lock-statistics) becomes generally available. Now, to ensure operational security, locking and unlocking statistics require the same privileges as collecting statistics. In addition, TiDB supports locking and unlocking statistics for specific partitions, providing greater flexibility. If you are confident in queries and execution plans in the database and want to prevent any changes from occurring, you can lock statistics to enhance stability. For more information, see [documentation](/statistics.md#lock-statistics). diff --git a/sql-statements/sql-statement-lock-stats.md b/sql-statements/sql-statement-lock-stats.md index a924a0b2c1a36..25057e7ba9476 100644 --- a/sql-statements/sql-statement-lock-stats.md +++ b/sql-statements/sql-statement-lock-stats.md @@ -7,10 +7,6 @@ summary: An overview of the usage of LOCK STATS for the TiDB database. `LOCK STATS` is used to lock the statistics of tables or partitions. When the statistics is locked, TiDB does not automatically update the statistics of the table or partition. For details on the behavior, see [Behaviors of locking statistics](/statistics.md#behaviors-of-locking-statistics). -> **Warning:** -> -> Locking statistics is an experimental feature for the current version. It is not recommended to use it in the production environment. - ## Synopsis ```ebnf+diagram diff --git a/sql-statements/sql-statement-show-stats-locked.md b/sql-statements/sql-statement-show-stats-locked.md index 51e026bdcc8da..a3f9d66e41273 100644 --- a/sql-statements/sql-statement-show-stats-locked.md +++ b/sql-statements/sql-statement-show-stats-locked.md @@ -7,10 +7,6 @@ summary: An overview of the usage of SHOW STATS_LOCKED for the TiDB database. `SHOW STATS_LOCKED` shows the tables whose statistics are locked. -> **Warning:** -> -> Locking statistics is an experimental feature for the current version. It is not recommended to use it in the production environment. - ## Synopsis ```ebnf+diagram diff --git a/sql-statements/sql-statement-unlock-stats.md b/sql-statements/sql-statement-unlock-stats.md index 059229a2889be..cd6446a8bafaf 100644 --- a/sql-statements/sql-statement-unlock-stats.md +++ b/sql-statements/sql-statement-unlock-stats.md @@ -7,10 +7,6 @@ summary: An overview of the usage of UNLOCK STATS for the TiDB database. `UNLOCK STATS` is used to unlock the statistics of a table or tables. -> **Warning:** -> -> Locking statistics is an experimental feature for the current version. It is not recommended to use it in the production environment. - ## Synopsis ```ebnf+diagram diff --git a/statistics.md b/statistics.md index 6c4ff858a538c..8d3fc672b66cd 100644 --- a/statistics.md +++ b/statistics.md @@ -807,10 +807,6 @@ LOAD STATS 'file_name' ## Lock statistics -> **Warning:** -> -> Locking statistics is an experimental feature for the current version. It is not recommended to use it in the production environment. - Starting from v6.5.0, TiDB supports locking statistics. After the statistics of a table or a partition are locked, the statistics of the table cannot be modified and the `ANALYZE` statement cannot be executed on the table. For example: Create table `t`, and insert data into it. When the statistics of table `t` are not locked, the `ANALYZE` statement can be successfully executed. From 9b750c2003126d47d8006a99b12ce6f7d4360951 Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Tue, 27 Feb 2024 15:17:01 +0800 Subject: [PATCH 02/82] Update the introduction to UPPER() and WEIGHT_STRING() (#16534) --- functions-and-operators/string-functions.md | 131 ++++++++++++-------- 1 file changed, 81 insertions(+), 50 deletions(-) diff --git a/functions-and-operators/string-functions.md b/functions-and-operators/string-functions.md index 7c3762a95d949..e94e26851fe25 100644 --- a/functions-and-operators/string-functions.md +++ b/functions-and-operators/string-functions.md @@ -28,36 +28,20 @@ The `ASCII(str)` function is used to get the ASCII value of the leftmost charact > > `ASCII(str)` only works for characters represented using 8 bits of binary digits (one byte). -Examples: +Example: ```sql -SELECT ASCII('A'); - -+------------+ -| ASCII('A') | -+------------+ -| 65 | -+------------+ +SELECT ASCII('A'), ASCII('TiDB'), ASCII(23); ``` -```sql -SELECT ASCII('TiDB'); - -+---------------+ -| ASCII('TiDB') | -+---------------+ -| 84 | -+---------------+ -``` +Output: ```sql -SELECT ASCII(23); - -+-----------+ -| ASCII(23) | -+-----------+ -| 50 | -+-----------+ ++------------+---------------+-----------+ +| ASCII('A') | ASCII('TiDB') | ASCII(23) | ++------------+---------------+-----------+ +| 65 | 84 | 50 | ++------------+---------------+-----------+ ``` ### [`BIN()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_bin) @@ -68,24 +52,34 @@ The `BIN()` function is used to convert the given argument into a string represe - If the argument is a negative number, the function converts the absolute value of the argument to its binary representation, inverts each bit of the binary value (changing `0` to `1` and `1` to `0`), and then adds `1` to the inverted value. - If the argument is a string containing only digits, the function returns the result according to those digits. For example, the results for `"123"` and `123` are the same. - If the argument is a string and its first character is not a digit (such as `"q123"`), the function returns `0`. -- If the argument is a string that consists of digits and non-digits, the function returns the result according to the consecutive digits at the beginning of the argument. For example, the results for `"123q123"` and `123` are the same. +- If the argument is a string that consists of digits and non-digits, the function returns the result according to the consecutive digits at the beginning of the argument. For example, the results for `"123q123"` and `123` are the same, but `BIN('123q123')` generates a warning like `Truncated incorrect INTEGER value: '123q123'`. - If the argument is `NULL`, the function returns `NULL`. -Examples: +Example 1: ```sql -SELECT BIN(123); +SELECT BIN(123), BIN('123q123'); +``` + +Output 1: -+----------+ -| BIN(123) | -+----------+ -| 1111011 | -+----------+ +```sql ++----------+----------------+ +| BIN(123) | BIN('123q123') | ++----------+----------------+ +| 1111011 | 1111011 | ++----------+----------------+ ``` +Example 2: + ```sql SELECT BIN(-7); +``` +Output 2: + +```sql +------------------------------------------------------------------+ | BIN(-7) | +------------------------------------------------------------------+ @@ -93,18 +87,6 @@ SELECT BIN(-7); +------------------------------------------------------------------+ ``` -```sql -SELECT BIN("123q123"); - -+----------------+ -| BIN("123q123") | -+----------------+ -| 1111011 | -+----------------+ -``` - -Return a string containing binary representation of a number. - ### [`BIT_LENGTH()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_bit-length) The `BIT_LENGTH()` function is used to return the length of a given argument in bits. @@ -1307,7 +1289,7 @@ Example 1: SELECT SUBSTRING_INDEX('www.tidbcloud.com', '.', 2); ``` -Result 1: +Output 1: ```sql +-----------------------------------------+ @@ -1323,7 +1305,7 @@ Example 2: SELECT SUBSTRING_INDEX('www.tidbcloud.com', '.', -1); ``` -Result 2: +Output 2: ```sql +------------------------------------------+ @@ -1352,7 +1334,7 @@ Example 1: SELECT TO_BASE64('abc'); ``` -Result 1: +Output 1: ```sql +------------------+ @@ -1368,7 +1350,7 @@ Example 2: SELECT TO_BASE64(6); ``` -Result 2: +Output 2: ```sql +--------------+ @@ -1396,11 +1378,60 @@ Return a string containing hex representation of a number. ### [`UPPER()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_upper) -Convert to uppercase. +The `UPPER()` function is used to convert a string to uppercase letters. This function is equivalent to the `UCASE()` function. + +> **Note:** +> +> When the string is null, the `UPPER()` function returns `NULL`. + +Example: + +```sql +SELECT UPPER('bigdata') AS result_upper, UPPER(null) AS result_null; +``` + +Output: + +```sql ++--------------+-------------+ +| result_upper | result_null | ++--------------+-------------+ +| BIGDATA | NULL | ++--------------+-------------+ +``` ### [`WEIGHT_STRING()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_weight-string) -Return the weight string for the input string. +The `WEIGHT_STRING()` function returns the weight string (binary characters) for the input string, primarily used for sorting and comparison operations in multi-character set scenarios. If the argument is `NULL`, it returns `NULL`. The syntax is as follows: + +```sql +WEIGHT_STRING(str [AS {CHAR|BINARY}(N)]) +``` + +- `str`: the input string expression. If it is a non-binary string, such as a `CHAR`, `VARCHAR`, or `TEXT` value, the return value contains the collation weights for the string. If it is a binary string, such as a `BINARY`, `VARBINARY`, or `BLOB` value, the return value is the same as the input. + +- `AS {CHAR|BINARY}(N)`: optional parameters used to specify the type and length of the output. `CHAR` represents the character data type, and `BINARY` represents the binary data type. `N` specifies the output length, which is an integer greater than or equal to 1. + +> **Note:** +> +> If `N` is less than the string length, the string is truncated. If `N` exceeds the string length, `AS CHAR(N)` pads the string with spaces to the specified length, and `AS BINARY(N)` pads the string with `0x00` to the specified length. + +Example: + +```sql +SET NAMES 'utf8mb4'; +SELECT HEX(WEIGHT_STRING('ab' AS CHAR(3))) AS char_result, HEX(WEIGHT_STRING('ab' AS BINARY(3))) AS binary_result; +``` + +Output: + +```sql ++-------------+---------------+ +| char_result | binary_result | ++-------------+---------------+ +| 6162 | 616200 | ++-------------+---------------+ +``` ## Unsupported functions From 1f2d904be6142c7190a92fc76802521ee6fd6e0f Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Tue, 27 Feb 2024 15:23:01 +0800 Subject: [PATCH 03/82] Update the introduction to UCASE() and UNHEX() (#16533) --- functions-and-operators/string-functions.md | 44 ++++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/functions-and-operators/string-functions.md b/functions-and-operators/string-functions.md index e94e26851fe25..d6c9f6bf1ad7b 100644 --- a/functions-and-operators/string-functions.md +++ b/functions-and-operators/string-functions.md @@ -1370,11 +1370,51 @@ Remove leading and trailing spaces. ### [`UCASE()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ucase) -Synonym for `UPPER()`. +The `UCASE()` function is used to convert a string to uppercase letters. This function is equivalent to the `UPPER()` function. + +> **Note:** +> +> When the string is null, the `UCASE()` function returns `NULL`. + +Example: + +```sql +SELECT UCASE('bigdata') AS result_upper, UCASE(null) AS result_null; +``` + +Output: + +```sql ++--------------+-------------+ +| result_upper | result_null | ++--------------+-------------+ +| BIGDATA | NULL | ++--------------+-------------+ +``` ### [`UNHEX()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_unhex) -Return a string containing hex representation of a number. +The `UNHEX()` function performs the reverse operation of the `HEX()` function. It treats each pair of characters in the argument as a hexadecimal number and converts it to the character represented by that number, returning the result as a binary string. + +> **Note:** +> +> The argument must be a valid hexadecimal value that contains `0`–`9`, `A`–`F`, or `a`–`f`. If the argument is `NULL` or falls outside this range, the function returns `NULL`. + +Example: + +```sql +SELECT UNHEX('54694442'); +``` + +Output: + +```sql ++--------------------------------------+ +| UNHEX('54694442') | ++--------------------------------------+ +| 0x54694442 | ++--------------------------------------+ +``` ### [`UPPER()`](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_upper) From 6b278880cab638eeaeee40cd688c0bc61cf3dad2 Mon Sep 17 00:00:00 2001 From: Aolin Date: Tue, 27 Feb 2024 17:15:31 +0800 Subject: [PATCH 04/82] Update placement-rules-in-sql.md to fix the incorrect part (#16609) --- placement-rules-in-sql.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/placement-rules-in-sql.md b/placement-rules-in-sql.md index 2e35f8828ffc2..75d234c5c9c01 100644 --- a/placement-rules-in-sql.md +++ b/placement-rules-in-sql.md @@ -232,7 +232,7 @@ You can configure `CONSTRAINTS`, `FOLLOWER_CONSTRAINTS`, and `LEARNER_CONSTRAINT | CONSTRAINTS format | Description | |----------------------------|-----------------------------------------------------------------------------------------------------------| | List format | If a constraint to be specified applies to all replicas, you can use a key-value list format. Each key starts with `+` or `-`. For example:
  • `[+region=us-east-1]` means placing data on nodes that have a `region` label as `us-east-1`.
  • `[+region=us-east-1,-type=fault]` means placing data on nodes that have a `region` label as `us-east-1` but do not have a `type` label as `fault`.

| -| Dictionary format | If you need to specify different numbers of replicas for different constraints, you can use the dictionary format. For example:
  • `FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,+region=us-east-2: 1,+region=us-west-1: 1}";` means placing one Follower in `us-east-1`, one Follower in `us-east-2`, and one Follower in `us-west-1`.
  • `FOLLOWER_CONSTRAINTS='{"+region=us-east-1,+type=scale-node": 1,"+region=us-west-1": 1}';` means placing one Follower on a node that is located in the `us-east-1` region and has the `type` label as `scale-node`, and one Follower in `us-west-1`.
The dictionary format supports each key starting with `+` or `-` and allows you to configure the special `#reject-leader` attribute. For example, `FOLLOWER_CONSTRAINTS='{"+region=us-east-1":1, "+region=us-east-2": 2, "+region=us-west-1,#reject-leader": 1}'` means that the Leaders elected in `us-west-1` will be evicted as much as possible during disaster recovery.| +| Dictionary format | If you need to specify different numbers of replicas for different constraints, you can use the dictionary format. For example:
  • `FOLLOWER_CONSTRAINTS="{+region=us-east-1: 1,+region=us-east-2: 1,+region=us-west-1: 1}";` means placing one Follower in `us-east-1`, one Follower in `us-east-2`, and one Follower in `us-west-1`.
  • `FOLLOWER_CONSTRAINTS='{"+region=us-east-1,+type=scale-node": 1,"+region=us-west-1": 1}';` means placing one Follower on a node that is located in the `us-east-1` region and has the `type` label as `scale-node`, and one Follower in `us-west-1`.
The dictionary format supports each key starting with `+` or `-` and allows you to configure the special `#evict-leader` attribute. For example, `FOLLOWER_CONSTRAINTS='{"+region=us-east-1":1, "+region=us-east-2": 2, "+region=us-west-1,#evict-leader": 1}'` means that the Leaders elected in `us-west-1` will be evicted as much as possible during disaster recovery.| > **Note:** > @@ -413,10 +413,10 @@ CREATE PLACEMENT POLICY deploy221_primary_east1 LEADER_CONSTRAINTS="[+region=us- After this placement policy is created and attached to the desired data, the Raft Leader replicas of the data will be placed in the `us-east-1` region specified by the `LEADER_CONSTRAINTS` option, while other replicas of the data will be placed in regions specified by the `FOLLOWER_CONSTRAINTS` option. Note that if the cluster fails, such as a node outage in the `us-east-1` region, a new Leader will still be elected from other regions, even if these regions are specified in `FOLLOWER_CONSTRAINTS`. In other words, ensuring service availability takes the highest priority. -In the event of a failure in the `us-east-1` region, if you do not want to place new Leaders in `us-west-1`, you can configure a special `reject-leader` attribute to evict the newly elected Leaders in that region: +In the event of a failure in the `us-east-1` region, if you do not want to place new Leaders in `us-west-1`, you can configure a special `evict-leader` attribute to evict the newly elected Leaders in that region: ```sql -CREATE PLACEMENT POLICY deploy221_primary_east1 LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWER_CONSTRAINTS='{"+region=us-east-1": 1, "+region=us-east-2": 2, "+region=us-west-1,#reject-leader": 1}'; +CREATE PLACEMENT POLICY deploy221_primary_east1 LEADER_CONSTRAINTS="[+region=us-east-1]" FOLLOWER_CONSTRAINTS='{"+region=us-east-1": 1, "+region=us-east-2": 2, "+region=us-west-1,#evict-leader": 1}'; ``` #### Use `PRIMARY_REGION` From 6ecc80feb2f47832cb34f9bb438f0bf839306979 Mon Sep 17 00:00:00 2001 From: Yasuo Honda Date: Tue, 27 Feb 2024 18:23:02 +0900 Subject: [PATCH 05/82] fix: `mycuster` should be `mycluster` (#16560) --- tiflash/tiflash-disaggregated-and-s3.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiflash/tiflash-disaggregated-and-s3.md b/tiflash/tiflash-disaggregated-and-s3.md index 556dfd806a525..856d64dbe2a6e 100644 --- a/tiflash/tiflash-disaggregated-and-s3.md +++ b/tiflash/tiflash-disaggregated-and-s3.md @@ -64,7 +64,7 @@ TiFlash disaggregated storage and compute architecture is suitable for cost-effe ``` ```shell - tiup cluster scale-in mycuster -N 'node0,node1...' # Remove all TiFlash nodes + tiup cluster scale-in mycluster -N 'node0,node1...' # Remove all TiFlash nodes tiup cluster display mycluster # Wait for all TiFlash nodes to enter the Tombstone state tiup cluster prune mycluster # Remove all TiFlash nodes in the Tombstone state ``` From 65c1fd271f035c804a7f5ca92c959ec29467d90c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Eeden?= Date: Tue, 27 Feb 2024 14:45:30 +0100 Subject: [PATCH 06/82] Various TLS related updates (#16267) --- certificate-authentication.md | 59 +++++++---------- enable-tls-between-clients-and-servers.md | 65 ++++++++++--------- sql-statements/sql-statement-alter-user.md | 4 ++ sql-statements/sql-statement-create-user.md | 4 ++ .../sql-statement-grant-privileges.md | 4 ++ .../sql-statement-revoke-privileges.md | 4 ++ tidb-configuration-file.md | 6 +- 7 files changed, 80 insertions(+), 66 deletions(-) diff --git a/certificate-authentication.md b/certificate-authentication.md index 7f7dd5b160a13..56e6d22296b91 100644 --- a/certificate-authentication.md +++ b/certificate-authentication.md @@ -241,7 +241,7 @@ ssl-ca="path/to/ca-cert.pem" Start TiDB and check logs. If the following information is displayed in the log, the configuration is successful: ``` -[INFO] [server.go:264] ["secure connection is enabled"] ["client verification enabled"=true] +[INFO] [server.go:286] ["mysql protocol server secure connection is enabled"] ["client verification enabled"=true] ``` ### Configure the client to use client certificate @@ -266,9 +266,9 @@ First, connect TiDB using the client to configure the login verification. Then, ### Get user certificate information -The user certificate information can be specified by `require subject`, `require issuer`, `require san`, and `require cipher`, which are used to check the X509 certificate attributes. +The user certificate information can be specified by `REQUIRE SUBJECT`, `REQUIRE ISSUER`, `REQUIRE SAN`, and `REQUIRE CIPHER`, which are used to check the X.509 certificate attributes. -+ `require subject`: Specifies the `subject` information of the client certificate when you log in. With this option specified, you do not need to configure `require ssl` or x509. The information to be specified is consistent with the entered `subject` information in [Generate client keys and certificates](#generate-client-key-and-certificate). ++ `REQUIRE SUBJECT`: Specifies the subject information of the client certificate when you log in. With this option specified, you do not need to configure `require ssl` or x509. The information to be specified is consistent with the entered subject information in [Generate client keys and certificates](#generate-client-key-and-certificate). To get this option, execute the following command: @@ -290,7 +290,7 @@ The user certificate information can be specified by `require subject`, `require + `require san`: Specifies the `Subject Alternative Name` information of the CA certificate that issues the user certificate. The information to be specified is consistent with the [`alt_names` of the `openssl.cnf` configuration file](https://docs.pingcap.com/tidb/stable/generate-self-signed-certificates) used to generate the client certificate. - + Execute the following command to get the information of the `require san` item in the generated certificate: + + Execute the following command to get the information of the `REQUIRE SAN` item in the generated certificate: {{< copyable "shell-regular" >}} @@ -298,25 +298,23 @@ The user certificate information can be specified by `require subject`, `require openssl x509 -noout -extensions subjectAltName -in client.crt ``` - + `require san` currently supports the following `Subject Alternative Name` check items: + + `REQUIRE SAN` currently supports the following `Subject Alternative Name` check items: - URI - IP - DNS - + Multiple check items can be configured after they are connected by commas. For example, configure `require san` as follows for the `u1` user: + + Multiple check items can be configured after they are connected by commas. For example, configure `REQUIRE SAN` as follows for the `u1` user: {{< copyable "sql" >}} ```sql - create user 'u1'@'%' require san 'DNS:d1,URI:spiffe://example.org/myservice1,URI:spiffe://example.org/myservice2'; + CREATE USER 'u1'@'%' REQUIRE SAN 'DNS:d1,URI:spiffe://example.org/myservice1,URI:spiffe://example.org/myservice2'; ``` The above configuration only allows the `u1` user to log in to TiDB using the certificate with the URI item `spiffe://example.org/myservice1` or `spiffe://example.org/myservice2` and the DNS item `d1`. -+ `require cipher`: Checks the cipher method supported by the client. Use the following statement to check the list of supported cipher methods: - - {{< copyable "sql" >}} ++ `REQUIRE CIPHER`: Checks the cipher method supported by the client. Use the following statement to check the list of supported cipher methods: ```sql SHOW SESSION STATUS LIKE 'Ssl_cipher_list'; @@ -324,24 +322,16 @@ The user certificate information can be specified by `require subject`, `require ### Configure user certificate information -After getting the user certificate information (`require subject`, `require issuer`, `require san`, `require cipher`), configure these information to be verified when creating a user, granting privileges, or altering a user. Replace `` with the corresponding information in the following statements. +After getting the user certificate information (`REQUIRE SUBJECT`, `REQUIRE ISSUER`, `REQUIRE SAN`, `REQUIRE CIPHER`), configure these information to be verified when creating a user, granting privileges, or altering a user. Replace `` with the corresponding information in the following statements. You can configure one option or multiple options using the space or `and` as the separator. -+ Configure user certificate when creating a user (`create user`): - - {{< copyable "sql" >}} - - ```sql - create user 'u1'@'%' require issuer '' subject '' san '' cipher ''; - ``` - -+ Configure user certificate when granting privileges: ++ Configure user certificate when creating a user (`CREATE USER`): {{< copyable "sql" >}} ```sql - grant all on *.* to 'u1'@'%' require issuer '' subject '' san '' cipher ''; + CREATE USER 'u1'@'%' REQUIRE ISSUER '' SUBJECT '' SAN '' CIPHER ''; ``` + Configure user certificate when altering a user: @@ -349,22 +339,20 @@ You can configure one option or multiple options using the space or `and` as the {{< copyable "sql" >}} ```sql - alter user 'u1'@'%' require issuer '' subject '' san '' cipher ''; + ALTER USER 'u1'@'%' REQUIRE ISSUER '' SUBJECT '' SAN '' CIPHER ''; ``` After the above configuration, the following items will be verified when you log in: + SSL is used; the CA that issues the client certificate is consistent with the CA configured in the server. -+ The `issuer` information of the client certificate matches the information specified in `require issuer`. -+ The `subject` information of the client certificate matches the information specified in `require cipher`. -+ The `Subject Alternative Name` information of the client certificate matches the information specified in `require san`. ++ The `issuer` information of the client certificate matches the information specified in `REQUIRE ISSUER`. ++ The `subject` information of the client certificate matches the information specified in `REQUIRE CIPHER`. ++ The `Subject Alternative Name` information of the client certificate matches the information specified in `REQUIRE SAN`. You can log into TiDB only after all the above items are verified. Otherwise, the `ERROR 1045 (28000): Access denied` error is returned. You can use the following command to check the TLS version, the cipher algorithm and whether the current connection uses the certificate for the login. Connect the MySQL client and execute the following statement: -{{< copyable "sql" >}} - ```sql \s ``` @@ -373,20 +361,18 @@ The output: ``` -------------- -mysql Ver 15.1 Distrib 10.4.10-MariaDB, for Linux (x86_64) using readline 5.1 +mysql Ver 8.3.0 for Linux on x86_64 (MySQL Community Server - GPL) Connection id: 1 Current database: test Current user: root@127.0.0.1 -SSL: Cipher in use is TLS_AES_256_GCM_SHA384 +SSL: Cipher in use is TLS_AES_128_GCM_SHA256 ``` Then execute the following statement: -{{< copyable "sql" >}} - ```sql -show variables like '%ssl%'; +SHOW VARIABLES LIKE '%ssl%'; ``` The output: @@ -395,13 +381,14 @@ The output: +---------------+----------------------------------+ | Variable_name | Value | +---------------+----------------------------------+ -| ssl_cert | /path/to/server-cert.pem | -| ssl_ca | /path/to/ca-cert.pem | -| have_ssl | YES | | have_openssl | YES | +| have_ssl | YES | +| ssl_ca | /path/to/ca-cert.pem | +| ssl_cert | /path/to/server-cert.pem | +| ssl_cipher | | | ssl_key | /path/to/server-key.pem | +---------------+----------------------------------+ -6 rows in set (0.067 sec) +6 rows in set (0.06 sec) ``` ## Update and replace certificate diff --git a/enable-tls-between-clients-and-servers.md b/enable-tls-between-clients-and-servers.md index 34724f5cfbb93..30e6b8dd25645 100644 --- a/enable-tls-between-clients-and-servers.md +++ b/enable-tls-between-clients-and-servers.md @@ -1,16 +1,16 @@ --- title: Enable TLS Between TiDB Clients and Servers -summary: Use the encrypted connection to ensure data security. +summary: Use secure connections to ensure data security. aliases: ['/docs/dev/enable-tls-between-clients-and-servers/','/docs/dev/how-to/secure/enable-tls-clients/','/docs/dev/encrypted-connections-with-tls-protocols/'] --- # Enable TLS between TiDB Clients and Servers -Non-encrypted connection between TiDB's server and clients is allowed by default, which enables third parties that monitor channel traffic to know the data sent and received between the server and the client, including query content and query results. If a channel is untrustworthy (such as if the client is connected to the TiDB server via a public network), then a non-encrypted connection is prone to information leakage. In this case, for security reasons, it is recommended to require an encrypted connection. +By default, TiDB allows insecure connections between the server and clients. This enables third parties that monitor channel traffic to know and possibly modify the data sent and received between the server and the client, including query content and query results. If a channel is untrustworthy (such as if the client is connected to the TiDB server via a public network), an insecure connection is prone to information leakage. In this case, for security reasons, it is recommended to require a connection that is secured with TLS. -The TiDB server supports the encrypted connection based on the TLS (Transport Layer Security). The protocol is consistent with MySQL encrypted connections and is directly supported by existing MySQL clients such as MySQL Client, MySQL Shell and MySQL drivers. TLS is sometimes referred to as SSL (Secure Sockets Layer). Because the SSL protocol has [known security vulnerabilities](https://en.wikipedia.org/wiki/Transport_Layer_Security), TiDB does not support SSL. TiDB supports the following protocols: TLSv1.0, TLSv1.1, TLSv1.2 and TLSv1.3. +The TiDB server supports secure connections based on the TLS (Transport Layer Security) protocol. The protocol is consistent with MySQL secure connections and is directly supported by existing MySQL clients such as MySQL Client, MySQL Shell and MySQL drivers. TLS is sometimes referred to as SSL (Secure Sockets Layer). Because the SSL protocol has [known security vulnerabilities](https://en.wikipedia.org/wiki/Transport_Layer_Security), TiDB does not support SSL. TiDB supports the following protocols: TLSv1.0, TLSv1.1, TLSv1.2 and TLSv1.3. -When an encrypted connection is used, the connection has the following security properties: +When a TLS secured connection is used, the connection has the following security properties: - Confidentiality: the traffic plaintext is encrypted to avoid eavesdropping - Integrity: the traffic plaintext cannot be tampered @@ -20,8 +20,8 @@ To use connections secured with TLS, you first need to configure the TiDB server Similar to MySQL, TiDB allows TLS and non-TLS connections on the same TCP port. For a TiDB server with TLS enabled, you can choose to securely connect to the TiDB server through an encrypted connection, or to use an unencrypted connection. You can use the following ways to require the use of secure connections: -+ Configure the system variable `require_secure_transport` to require secure connections to the TiDB server for all users. -+ Specify `REQUIRE SSL` when you create a user (`create user`), or modify an existing user (`alter user`), which is to specify that specified users must use the encrypted connection to access TiDB. The following is an example of creating a user: ++ Configure the system variable [`require_secure_transport`](/system-variables.md#require_secure_transport-new-in-v610) to require secure connections to the TiDB server for all users. ++ Specify `REQUIRE SSL` when you create a user (`create user`), or modify an existing user (`alter user`), which is to specify that specified users must use TLS connections to access TiDB. The following is an example of creating a user: {{< copyable "sql" >}} @@ -47,27 +47,27 @@ See the following descriptions about the related parameters to enable secure con To enable secure connections with your own certificates in the TiDB server, you must specify both of the `ssl-cert` and `ssl-key` parameters in the configuration file when you start the TiDB server. You can also specify the `ssl-ca` parameter for client authentication (see [Enable authentication](#enable-authentication)). -All the files specified by the parameters are in PEM (Privacy Enhanced Mail) format. Currently, TiDB does not support the import of a password-protected private key, so it is required to provide a private key file without a password. If the certificate or private key is invalid, the TiDB server starts as usual, but the client cannot connect to the TiDB server through an encrypted connection. +All the files specified by the parameters are in PEM (Privacy Enhanced Mail) format. Currently, TiDB does not support the import of a password-protected private key, so it is required to provide a private key file without a password. If the certificate or private key is invalid, the TiDB server starts as usual, but the client cannot connect to the TiDB server through a TLS connection. -If the certificate parameters are correct, TiDB outputs `secure connection is enabled` when started; otherwise, it outputs `secure connection is NOT ENABLED`. +If the certificate parameters are correct, TiDB outputs `mysql protocol server secure connection is enabled` to the logs on `"INFO"` level when started. -For TiDB versions earlier than v5.2.0, you can use `mysql_ssl_rsa_setup --datadir=./certs` to generate certficates. The `mysql_ssl_rsa_setup` tool is a part of MySQL Server. +## Configure the MySQL client to use TLS connections -## Configure the MySQL client to use encrypted connections - -The client of MySQL 5.7 or later versions attempts to establish an encrypted connection by default. If the server does not support encrypted connections, it automatically returns to unencrypted connections. The client of MySQL earlier than version 5.7 uses the unencrypted connection by default. +The client of MySQL 5.7 or later versions attempts to establish a TLS connection by default. If the server does not support TLS connections, it automatically returns to unencrypted connections. The client of MySQL earlier than version 5.7 uses the non-TLS connections by default. You can change the connection behavior of the client using the following `--ssl-mode` parameters: -- `--ssl-mode=REQUIRED`: The client requires an encrypted connection. The connection cannot be established if the server side does not support encrypted connections. -- In the absence of the `--ssl-mode` parameter: The client attempts to use an encrypted connection, but the encrypted connection cannot be established if the server side does not support encrypted connections. Then the client uses an unencrypted connection. +- `--ssl-mode=REQUIRED`: The client requires a TLS connection. The connection cannot be established if the server side does not support TLS connections. +- In the absence of the `--ssl-mode` parameter: The client attempts to use a TLS connection, but the encrypted connection cannot be established if the server side does not support encrypted connections. Then the client uses an unencrypted connection. - `--ssl-mode=DISABLED`: The client uses an unencrypted connection. -MySQL 8.0 clients have two SSL modes in addition to this parameter: +MySQL 8.x clients have two SSL modes in addition to this parameter: - `--ssl-mode=VERIFY_CA`: Validates the certificate from the server against the CA that requires `--ssl-ca`. - `--ssl-mode=VERIFY_IDENTITY`: The same as `VERIFY_CA`, but also validating whether the hostname you are connecting to matches the certificate. +For MySQL 5.7 and MariaDB clients and earlier you can use `--ssl-verify-server-cert` to enable validation of the server certificate. + For more information, see [Client-Side Configuration for Encrypted Connections](https://dev.mysql.com/doc/refman/8.0/en/using-encrypted-connections.html#using-encrypted-connections-client-side-configuration) in MySQL. ## Enable authentication @@ -87,17 +87,15 @@ If the `ssl-ca` parameter is not specified in the TiDB server or MySQL client, t - To perform mutual authentication, meet both of the above requirements. -By default, the server-to-client authentication is optional. Even if the client does not present its certificate of identification during the TLS handshake, the TLS connection can be still established. You can also require the client to be authenticated by specifying `require x509` when creating a user (`create user`), granting permissions (`grant`), or modifying an existing user (`alter user`). The following is an example of creating a user: - -{{< copyable "sql" >}} +By default, the server-to-client authentication is optional. Even if the client does not present its certificate of identification during the TLS handshake, the TLS connection can be still established. You can also require the client to be authenticated by specifying `REQUIRE x509` when creating a user (`CREATE USER`), or modifying an existing user (`ALTER USER`). The following is an example of creating a user: ```sql -create user 'u1'@'%' require x509; +CREATE USER 'u1'@'%' REQUIRE X509; ``` > **Note:** > -> If the login user has configured using the [TiDB Certificate-Based Authentication for Login](/certificate-authentication.md#configure-the-user-certificate-information-for-login-verification), the user is implicitly required to enable the encrypted connection to TiDB. +> If the login user has configured using the [TiDB Certificate-Based Authentication for Login](/certificate-authentication.md#configure-the-user-certificate-information-for-login-verification), the user is implicitly required to enable the TLS connection to TiDB. ## Check whether the current connection uses encryption @@ -105,13 +103,22 @@ Use the `SHOW STATUS LIKE "%Ssl%";` statement to get the details of the current See the following example of the result in an encrypted connection. The results change according to different TLS versions or encryption protocols supported by the client. +```sql +SHOW STATUS LIKE "Ssl%"; +``` + ``` -mysql> SHOW STATUS LIKE "%Ssl%"; -...... -| Ssl_verify_mode | 5 | -| Ssl_version | TLSv1.2 | -| Ssl_cipher | ECDHE-RSA-AES128-GCM-SHA256 | -...... ++-----------------------+-------------------------------------------------------> +| Variable_name | Value > ++-----------------------+-------------------------------------------------------> +| Ssl_cipher | TLS_AES_128_GCM_SHA256 > +| Ssl_cipher_list | RC4-SHA:DES-CBC3-SHA:AES128-SHA:AES256-SHA:AES128-SHA2> +| Ssl_server_not_after | Apr 23 07:59:47 2024 UTC > +| Ssl_server_not_before | Jan 24 07:59:47 2024 UTC > +| Ssl_verify_mode | 5 > +| Ssl_version | TLSv1.3 > ++-----------------------+-------------------------------------------------------> +6 rows in set (0.0062 sec) ``` For the official MySQL client, you can also use the `STATUS` or `\s` statement to view the connection status: @@ -119,13 +126,13 @@ For the official MySQL client, you can also use the `STATUS` or `\s` statement t ``` mysql> \s ... -SSL: Cipher in use is ECDHE-RSA-AES128-GCM-SHA256 +SSL: Cipher in use is TLS_AES_128_GCM_SHA256 ... ``` ## Supported TLS versions, key exchange protocols, and encryption algorithms -The TLS versions, key exchange protocols and encryption algorithms supported by TiDB are determined by the official Golang libraries. +The TLS versions, key exchange protocols and encryption algorithms supported by TiDB are determined by the official Go libraries. The crypto policy for your operating system and the client library you are using might also impact the list of supported protocols and cipher suites. @@ -136,7 +143,7 @@ The crypto policy for your operating system and the client library you are using - TLSv1.2 - TLSv1.3 -The `tls-version` configuration option can be used to limit the TLS versions that can be used. +You can use the [`tls-version`](/tidb-configuration-file.md#tls-version) configuration option to limit the TLS versions that can be used. The actual TLS versions that can be used depend on the OS crypto policy, MySQL client version and the SSL/TLS library that is used by the client. diff --git a/sql-statements/sql-statement-alter-user.md b/sql-statements/sql-statement-alter-user.md index 62cacea484759..f4ff2a33454e1 100644 --- a/sql-statements/sql-statement-alter-user.md +++ b/sql-statements/sql-statement-alter-user.md @@ -33,6 +33,10 @@ LockOption ::= ( 'ACCOUNT' 'LOCK' | 'ACCOUNT' 'UNLOCK' )? AttributeOption ::= ( 'COMMENT' CommentString | 'ATTRIBUTE' AttributeString )? ResourceGroupNameOption::= ( 'RESOURCE' 'GROUP' Identifier)? + +RequireClauseOpt ::= ('REQUIRE' ('NONE' | 'SSL' | 'X509' | RequireListElement ('AND'? RequireListElement)*))? + +RequireListElement ::= 'ISSUER' Issuer | 'SUBJECT' Subject | 'CIPHER' Cipher | 'SAN' SAN | 'TOKEN_ISSUER' TokenIssuer ``` ## Examples diff --git a/sql-statements/sql-statement-create-user.md b/sql-statements/sql-statement-create-user.md index 76d0c78569c07..00345c11bf7a3 100644 --- a/sql-statements/sql-statement-create-user.md +++ b/sql-statements/sql-statement-create-user.md @@ -37,6 +37,10 @@ LockOption ::= ( 'ACCOUNT' 'LOCK' | 'ACCOUNT' 'UNLOCK' )? AttributeOption ::= ( 'COMMENT' CommentString | 'ATTRIBUTE' AttributeString )? ResourceGroupNameOption::= ( 'RESOURCE' 'GROUP' Identifier)? + +RequireClauseOpt ::= ('REQUIRE' ('NONE' | 'SSL' | 'X509' | RequireListElement ('AND'? RequireListElement)*))? + +RequireListElement ::= 'ISSUER' Issuer | 'SUBJECT' Subject | 'CIPHER' Cipher | 'SAN' SAN | 'TOKEN_ISSUER' TokenIssuer ``` ## Examples diff --git a/sql-statements/sql-statement-grant-privileges.md b/sql-statements/sql-statement-grant-privileges.md index b8b36190047f6..adedcb211f1af 100644 --- a/sql-statements/sql-statement-grant-privileges.md +++ b/sql-statements/sql-statement-grant-privileges.md @@ -55,6 +55,10 @@ PrivLevel ::= UserSpecList ::= UserSpec ( ',' UserSpec )* + +RequireClauseOpt ::= ('REQUIRE' ('NONE' | 'SSL' | 'X509' | RequireListElement ('AND'? RequireListElement)*))? + +RequireListElement ::= 'ISSUER' Issuer | 'SUBJECT' Subject | 'CIPHER' Cipher | 'SAN' SAN | 'TOKEN_ISSUER' TokenIssuer ``` ## Examples diff --git a/sql-statements/sql-statement-revoke-privileges.md b/sql-statements/sql-statement-revoke-privileges.md index dc60a2658b236..532b601db0949 100644 --- a/sql-statements/sql-statement-revoke-privileges.md +++ b/sql-statements/sql-statement-revoke-privileges.md @@ -55,6 +55,10 @@ PrivLevel ::= UserSpecList ::= UserSpec ( ',' UserSpec )* + +RequireClauseOpt ::= ('REQUIRE' ('NONE' | 'SSL' | 'X509' | RequireListElement ('AND'? RequireListElement)*))? + +RequireListElement ::= 'ISSUER' Issuer | 'SUBJECT' Subject | 'CIPHER' Cipher | 'SAN' SAN | 'TOKEN_ISSUER' TokenIssuer ``` ## Examples diff --git a/tidb-configuration-file.md b/tidb-configuration-file.md index 722c89d0c23b9..e1894d514868e 100644 --- a/tidb-configuration-file.md +++ b/tidb-configuration-file.md @@ -413,8 +413,12 @@ Configuration items related to security. ### `tls-version` +> **Warning:** +> +> `"TLSv1.0"` and `"TLSv1.1"` protocols are deprecated in TiDB v7.6.0, and will be removed in v8.0.0. + - Set the minimum TLS version for MySQL Protocol connections. -- Default value: "", which allows TLSv1.2 or higher. Before TiDB v7.6.0, the default value allows TLSv1.1 or higher. +- Default value: "", which allows TLSv1.2 or later versions. Before TiDB v7.6.0, the default value allows TLSv1.1 or later versions. - Optional values: `"TLSv1.0"`, `"TLSv1.1"`, `"TLSv1.2"` and `"TLSv1.3"` ### `auth-token-jwks` New in v6.4.0 From 596137d86422aadfcc1508ce9d8056b9c047a6e1 Mon Sep 17 00:00:00 2001 From: Aolin Date: Wed, 28 Feb 2024 11:53:00 +0800 Subject: [PATCH 07/82] fix link, parser.y (#16611) --- expression-syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/expression-syntax.md b/expression-syntax.md index 09489d4f95975..fe5fae943a5ba 100644 --- a/expression-syntax.md +++ b/expression-syntax.md @@ -18,7 +18,7 @@ The expressions can be divided into the following types: - ParamMarker (`?`), system variables, user variables and CASE expressions. -The following rules are the expression syntax, which is based on the [parser.y](https://github.com/pingcap/parser/blob/master/parser.y) rules of TiDB parser. For the navigable version of the following syntax diagram, refer to [TiDB SQL Syntax Diagram](https://pingcap.github.io/sqlgram/#Expression). +The following rules are the expression syntax, which is based on the [`parser.y`](https://github.com/pingcap/tidb/blob/master/pkg/parser/parser.y) rules of TiDB parser. For the navigable version of the following syntax diagram, refer to [TiDB SQL Syntax Diagram](https://pingcap.github.io/sqlgram/#Expression). ```ebnf+diagram Expression ::= From 0ca50a61241001a2b8bb74f562726f126bb51074 Mon Sep 17 00:00:00 2001 From: YangKeao Date: Wed, 28 Feb 2024 16:50:01 +0800 Subject: [PATCH 08/82] remove support for tls 1.1 and 1.0 (#16221) --- enable-tls-between-clients-and-servers.md | 4 +--- tidb-configuration-file.md | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/enable-tls-between-clients-and-servers.md b/enable-tls-between-clients-and-servers.md index 30e6b8dd25645..3e47532a9bb88 100644 --- a/enable-tls-between-clients-and-servers.md +++ b/enable-tls-between-clients-and-servers.md @@ -8,7 +8,7 @@ aliases: ['/docs/dev/enable-tls-between-clients-and-servers/','/docs/dev/how-to/ By default, TiDB allows insecure connections between the server and clients. This enables third parties that monitor channel traffic to know and possibly modify the data sent and received between the server and the client, including query content and query results. If a channel is untrustworthy (such as if the client is connected to the TiDB server via a public network), an insecure connection is prone to information leakage. In this case, for security reasons, it is recommended to require a connection that is secured with TLS. -The TiDB server supports secure connections based on the TLS (Transport Layer Security) protocol. The protocol is consistent with MySQL secure connections and is directly supported by existing MySQL clients such as MySQL Client, MySQL Shell and MySQL drivers. TLS is sometimes referred to as SSL (Secure Sockets Layer). Because the SSL protocol has [known security vulnerabilities](https://en.wikipedia.org/wiki/Transport_Layer_Security), TiDB does not support SSL. TiDB supports the following protocols: TLSv1.0, TLSv1.1, TLSv1.2 and TLSv1.3. +The TiDB server supports secure connections based on the TLS (Transport Layer Security) protocol. The protocol is consistent with MySQL secure connections and is directly supported by existing MySQL clients such as MySQL Client, MySQL Shell and MySQL drivers. TLS is sometimes referred to as SSL (Secure Sockets Layer). Because the SSL protocol has [known security vulnerabilities](https://en.wikipedia.org/wiki/Transport_Layer_Security), TiDB does not support SSL. TiDB supports the following protocols: TLSv1.2 and TLSv1.3. When a TLS secured connection is used, the connection has the following security properties: @@ -138,8 +138,6 @@ The crypto policy for your operating system and the client library you are using ### Supported TLS versions -- TLSv1.0 (disabled by default) -- TLSv1.1 (disabled by default) - TLSv1.2 - TLSv1.3 diff --git a/tidb-configuration-file.md b/tidb-configuration-file.md index e1894d514868e..35ec304fd08a3 100644 --- a/tidb-configuration-file.md +++ b/tidb-configuration-file.md @@ -419,7 +419,7 @@ Configuration items related to security. - Set the minimum TLS version for MySQL Protocol connections. - Default value: "", which allows TLSv1.2 or later versions. Before TiDB v7.6.0, the default value allows TLSv1.1 or later versions. -- Optional values: `"TLSv1.0"`, `"TLSv1.1"`, `"TLSv1.2"` and `"TLSv1.3"` +- Optional values: `"TLSv1.2"` and `"TLSv1.3"`. Before TiDB v8.0.0, `"TLSv1.0"` and `"TLSv1.1"` are also allowed. ### `auth-token-jwks` New in v6.4.0 From aa4d3aaab87d1769977c0ed612d675a76b44ab16 Mon Sep 17 00:00:00 2001 From: Aolin Date: Thu, 29 Feb 2024 09:56:01 +0800 Subject: [PATCH 09/82] v7.5.1: enhance observability related to resource control (#16463) --- sql-statements/sql-statement-flashback-cluster.md | 2 +- statement-summary-tables.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql-statements/sql-statement-flashback-cluster.md b/sql-statements/sql-statement-flashback-cluster.md index a9152831a174f..4bf8cca95c3c2 100644 --- a/sql-statements/sql-statement-flashback-cluster.md +++ b/sql-statements/sql-statement-flashback-cluster.md @@ -8,7 +8,7 @@ aliases: ['/tidb/dev/sql-statement-flashback-to-timestamp'] TiDB v6.4.0 introduces the `FLASHBACK CLUSTER TO TIMESTAMP` syntax. You can use it to restore a cluster to a specific point in time. When specifying the timestamp, you can either set a datetime value or use a time function. The format of datetime is like '2016-10-08 16:45:26.999', with millisecond as the minimum time unit. But in most cases, specifying the timestamp with second as the time unit is sufficient, for example, '2016-10-08 16:45:26'. -Starting from v6.5.6, v7.1.3, and v7.6.0, TiDB introduces the `FLASHBACK CLUSTER TO TSO` syntax. This syntax enables you to use [TSO](/tso.md) to specify a more precise recovery point in time, thereby enhancing flexibility in data recovery. +Starting from v6.5.6, v7.1.3, v7.5.1, and v7.6.0, TiDB introduces the `FLASHBACK CLUSTER TO TSO` syntax. This syntax enables you to use [TSO](/tso.md) to specify a more precise recovery point in time, thereby enhancing flexibility in data recovery. > **Warning:** > diff --git a/statement-summary-tables.md b/statement-summary-tables.md index 0a4f814738941..13c1708c76198 100644 --- a/statement-summary-tables.md +++ b/statement-summary-tables.md @@ -87,7 +87,7 @@ The following is a sample output of querying `statements_summary`: > **Note:** > > - In TiDB, the time unit of fields in statement summary tables is nanosecond (ns), whereas in MySQL the time unit is picosecond (ps). -> - Starting from v7.6.0, for clusters with [resource control](/tidb-resource-control.md) enabled, `statements_summary` will be aggregated by resource group, for example, the same statements executed in different resource groups will be collected as different records. +> - Starting from v7.5.1 and v7.6.0, for clusters with [resource control](/tidb-resource-control.md) enabled, `statements_summary` will be aggregated by resource group, for example, the same statements executed in different resource groups will be collected as different records. ## `statements_summary_history` From f0469b9bb3d5bbe43f1130c4e9d976aac8afd7ba Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Thu, 29 Feb 2024 10:18:30 +0800 Subject: [PATCH 10/82] v7.5.1: tikv configuration doc: add gc thread number (#16564) (#16631) --- releases/release-7.6.0.md | 2 +- tikv-configuration-file.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/release-7.6.0.md b/releases/release-7.6.0.md index c7a98e069a5a1..62499af3452a4 100644 --- a/releases/release-7.6.0.md +++ b/releases/release-7.6.0.md @@ -284,7 +284,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.6/quick-start-with- | TiKV | [`blob-file-compression`](/tikv-configuration-file.md#blob-file-compression) | Modified | The algorithm used for compressing values in Titan, which takes value as the unit. Starting from TiDB v7.6.0, the default compression algorithm is `zstd`. | | TiKV | [`rocksdb.defaultcf.titan.min-blob-size`](/tikv-configuration-file.md#min-blob-size) | Modified | Starting from TiDB v7.6.0, the default value for new clusters is `32KB`. For existing clusters upgrading to v7.6.0, the default value `1KB` remains unchanged. | | TiKV | [`rocksdb.titan.enabled`](/tikv-configuration-file.md#enabled) | Modified | Enables or disables Titan. For v7.5.0 and earlier versions, the default value is `false`. Starting from v7.6.0, the default value is `true` for only new clusters. Existing clusters upgraded to v7.6.0 or later versions will retain the original configuration. | -| TiKV | [`gc.num-threads`](/tikv-configuration-file.md#num-threads-new-in-v658-and-v760) | Newly added | When `enable-compaction-filter` is set to `false`, this parameter controls the number of GC threads. The default value is `1`. | +| TiKV | [`gc.num-threads`](/tikv-configuration-file.md#num-threads-new-in-v658-v751-and-v760) | Newly added | When `enable-compaction-filter` is set to `false`, this parameter controls the number of GC threads. The default value is `1`. | | TiKV | [`raftstore.periodic-full-compact-start-times`](/tikv-configuration-file.md#periodic-full-compact-start-times-new-in-v760) | Newly added | Sets the specific times that TiKV initiates periodic full compaction. The default value `[]` means periodic full compaction is disabled. | | TiKV | [`raftstore.periodic-full-compact-start-max-cpu`](/tikv-configuration-file.md#periodic-full-compact-start-max-cpu-new-in-v760) | Newly added | Limits the maximum CPU usage rate for TiKV periodic full compaction. The default value is `0.1`. | | TiKV | [`zstd-dict-size`](/tikv-configuration-file.md#zstd-dict-size) | Newly added | Specifies the `zstd` dictionary compression size. The default value is `"0KB"`, which means to disable the `zstd` dictionary compression. | diff --git a/tikv-configuration-file.md b/tikv-configuration-file.md index 5477cd5dfcccc..4707e3b5caa4e 100644 --- a/tikv-configuration-file.md +++ b/tikv-configuration-file.md @@ -2066,7 +2066,7 @@ Configuration items related to TiDB Lightning import and BR restore. + The garbage ratio threshold to trigger GC. + Default value: `1.1` -### `num-threads` New in v6.5.8 and v7.6.0 +### `num-threads` New in v6.5.8, v7.5.1, and v7.6.0 + The number of GC threads when `enable-compaction-filter` is `false`. + Default value: `1` From 277b621d0b7c94ea27923838c3d7a4ae191aa227 Mon Sep 17 00:00:00 2001 From: Aolin Date: Thu, 29 Feb 2024 13:36:31 +0800 Subject: [PATCH 11/82] add release note for v7.5.1 (#16595) --- TOC.md | 1 + releases/release-7.5.1.md | 227 +++++++++++++++++++++++++++++++++++ releases/release-notes.md | 1 + releases/release-timeline.md | 1 + 4 files changed, 230 insertions(+) create mode 100644 releases/release-7.5.1.md diff --git a/TOC.md b/TOC.md index 94ce25a8736ee..ea68b1097f752 100644 --- a/TOC.md +++ b/TOC.md @@ -1035,6 +1035,7 @@ - v7.6 - [7.6.0](/releases/release-7.6.0.md) - v7.5 + - [7.5.1](/releases/release-7.5.1.md) - [7.5.0](/releases/release-7.5.0.md) - v7.4 - [7.4.0-DMR](/releases/release-7.4.0.md) diff --git a/releases/release-7.5.1.md b/releases/release-7.5.1.md new file mode 100644 index 0000000000000..6a975f4df1186 --- /dev/null +++ b/releases/release-7.5.1.md @@ -0,0 +1,227 @@ +--- +title: TiDB 7.5.1 Release Notes +summary: Learn about the compatibility changes, improvements, and bug fixes in TiDB 7.5.1. +--- + +# TiDB 7.5.1 Release Notes + +Release date: February 29, 2024 + +TiDB version: 7.5.1 + +Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.5/quick-start-with-tidb) | [Production deployment](https://docs.pingcap.com/tidb/v7.5/production-deployment-using-tiup) | [Installation packages](https://www.pingcap.com/download/?version=v7.5.1#version-list) + +## Compatibility changes + +- Prohibit setting [`require_secure_transport`](https://docs.pingcap.com/tidb/v7.5/system-variables#require_secure_transport-new-in-v610) to `ON` in Security Enhanced Mode (SEM) to prevent potential connectivity issues for users [#47665](https://github.com/pingcap/tidb/issues/47665) @[tiancaiamao](https://github.com/tiancaiamao) +- To reduce the overhead of log printing, TiFlash changes the default value of `logger.level` from `"debug"` to `"info"` [#8641](https://github.com/pingcap/tiflash/issues/8641) @[JaySon-Huang](https://github.com/JaySon-Huang) +- Introduce the TiKV configuration item [`gc.num-threads`](https://docs.pingcap.com/tidb/v7.5/tikv-configuration-file#num-threads-new-in-v658-and-v751) to set the number of GC threads when `enable-compaction-filter` is `false` [#16101](https://github.com/tikv/tikv/issues/16101) @[tonyxuqqi](https://github.com/tonyxuqqi) +- TiCDC Changefeed introduces the following new configuration items: + - [`compression`](/ticdc/ticdc-changefeed-config.md): enables you to configure the compression behavior of redo log files [#10176](https://github.com/pingcap/tiflow/issues/10176) @[sdojjy](https://github.com/sdojjy) + - [`sink.cloud-storage-config`](/ticdc/ticdc-changefeed-config.md): enables you to set the automatic cleanup of historical data when replicating data to object storage [#10109](https://github.com/pingcap/tiflow/issues/10109) @[CharlesCheung96](https://github.com/CharlesCheung96) + - [`consistent.flush-concurrency`](/ticdc/ticdc-changefeed-config.md): enables you to set the concurrency for uploading a single redo file [#10226](https://github.com/pingcap/tiflow/issues/10226) @[sdojjy](https://github.com/sdojjy) + +## Improvements + ++ TiDB + + - Use `tikv_client_read_timeout` during the DDL schema reload process to reduce the impact of Meta Region Leader read unavailability on the cluster [#48124](https://github.com/pingcap/tidb/issues/48124) @[cfzjywxk](https://github.com/cfzjywxk) + - Enhance observability related to resource control [#49318](https://github.com/pingcap/tidb/issues/49318) @[glorv](https://github.com/glorv) @[bufferflies](https://github.com/bufferflies) @[nolouch](https://github.com/nolouch) + + As more and more users use resource groups to isolate application workloads, Resource Control provides enhanced data based on resource groups. This helps you monitor resource group workloads and settings, ensuring that you can quickly identify and accurately diagnose problems, including: + + - [Slow Queries](/identify-slow-queries.md): add the resource group name, resource unit (RU) consumption, and time for waiting for resources. + - [Statement Summary Tables](/statement-summary-tables.md): add the resource group name, RU consumption, and time for waiting for resources. + - In the system variable [`tidb_last_query_info`](/system-variables.md#tidb_last_query_info-new-in-v4014), add a new entry `ru_consumption` to indicate the consumed [RU](/tidb-resource-control.md#what-is-request-unit-ru) by SQL statements. You can use this variable to get the resource consumption of the last statement in the session. + - Add database metrics based on resource groups: QPS/TPS, execution time (P999/P99/P95), number of failures, and number of connections. + + - Modify the `CANCEL IMPORT JOB` statement to a synchronous statement [#48736](https://github.com/pingcap/tidb/issues/48736) @[D3Hunter](https://github.com/D3Hunter) + - Support the [`FLASHBACK CLUSTER TO TSO`](https://docs.pingcap.com/tidb/v7.5/sql-statement-flashback-cluster) syntax [#48372](https://github.com/pingcap/tidb/issues/48372) @[BornChanger](https://github.com/BornChanger) + - Optimize the TiDB implementation when handling some type conversions and fix related issues [#47945](https://github.com/pingcap/tidb/issues/47945) [#47864](https://github.com/pingcap/tidb/issues/47864) [#47829](https://github.com/pingcap/tidb/issues/47829) [#47816](https://github.com/pingcap/tidb/issues/47816) @[YangKeao](https://github.com/YangKeao) @[lcwangchao](https://github.com/lcwangchao) + - When a non-binary collation is set and the query includes `LIKE`, the optimizer generates an `IndexRangeScan` to improve the execution efficiency [#48181](https://github.com/pingcap/tidb/issues/48181) [#49138](https://github.com/pingcap/tidb/issues/49138) @[time-and-fate](https://github.com/time-and-fate) + - Enhance the ability to convert `OUTER JOIN` to `INNER JOIN` in specific scenarios [#49616](https://github.com/pingcap/tidb/issues/49616) @[qw4990](https://github.com/qw4990) + - Support multiple accelerated `ADD INDEX` DDL tasks to be queued for execution, instead of falling back to normal `ADD INDEX` tasks [#47758](https://github.com/pingcap/tidb/issues/47758) @[tangenta](https://github.com/tangenta) + - Improve the speed of adding indexes to empty tables [#49682](https://github.com/pingcap/tidb/issues/49682) @[zimulala](https://github.com/zimulala) + ++ TiFlash + + - Improve the calculation method for [Request Unit (RU)](/tidb-resource-control.md#what-is-request-unit-ru) to make RU values more stable [#8391](https://github.com/pingcap/tiflash/issues/8391) @[guo-shaoge](https://github.com/guo-shaoge) + - Reduce the impact of disk performance jitter on read latency [#8583](https://github.com/pingcap/tiflash/issues/8583) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Reduce the impact of background GC tasks on read and write task latency [#8650](https://github.com/pingcap/tiflash/issues/8650) @[JaySon-Huang](https://github.com/JaySon-Huang) + ++ Tools + + + Backup & Restore (BR) + + - Improve the speed of merging SST files during data restore by using a more efficient algorithm [#50613](https://github.com/pingcap/tidb/issues/50613) @[Leavrth](https://github.com/Leavrth) + - Support creating databases in batch during data restore [#50767](https://github.com/pingcap/tidb/issues/50767) @[Leavrth](https://github.com/Leavrth) + - Support ingesting SST files in batch during data restore [#16267](https://github.com/tikv/tikv/issues/16267) @[3pointer](https://github.com/3pointer) + - Print the information of the slowest Region that affects global checkpoint advancement in logs and metrics during log backups [#51046](https://github.com/pingcap/tidb/issues/51046) @[YuJuncen](https://github.com/YuJuncen) + - Improve the table creation performance of the `RESTORE` statement in scenarios with large datasets [#48301](https://github.com/pingcap/tidb/issues/48301) @[Leavrth](https://github.com/Leavrth) + - BR can pause Region merging by setting the `merge-schedule-limit` configuration to `0` [#7148](https://github.com/tikv/pd/issues/7148) @[BornChanger](https://github.com/3pointer) + - Refactor the BR exception handling mechanism to increase tolerance for unknown errors [#47656](https://github.com/pingcap/tidb/issues/47656) @[3pointer](https://github.com/3pointer) + + + TiCDC + + - Support searching TiCDC logs in the TiDB Dashboard [#10263](https://github.com/pingcap/tiflow/issues/10263) @[CharlesCheung96](https://github.com/CharlesCheung96) + - Support [querying the downstream synchronization status of a changefeed](https://docs.pingcap.com/tidb/v7.5/ticdc-open-api-v2#query-whether-a-specific-replication-task-is-completed), which helps you determine whether the upstream data changes received by TiCDC have been synchronized to the downstream system completely [#10289](https://github.com/pingcap/tiflow/issues/10289) @[hongyunyan](https://github.com/hongyunyan) + - Improve the performance of TiCDC replicating data to object storage by increasing parallelism [#10098](https://github.com/pingcap/tiflow/issues/10098) @[CharlesCheung96](https://github.com/CharlesCheung96) + + + TiDB Lightning + + - Improve the performance of `ALTER TABLE` when importing a large number of small tables [#50105](https://github.com/pingcap/tidb/issues/50105) @[D3Hunter](https://github.com/D3Hunter) + +## Bug fixes + ++ TiDB + + - Fix the issue that setting the system variable `tidb_service_scope` does not take effect [#49245](https://github.com/pingcap/tidb/issues/49245) @[ywqzzy](https://github.com/ywqzzy) + - Fix the issue that the communication protocol cannot handle packets larger than or equal to 16 MB when compression is enabled [#47157](https://github.com/pingcap/tidb/issues/47157) [#47161](https://github.com/pingcap/tidb/issues/47161) @[dveeden](https://github.com/dveeden) + - Fix the issue that the `approx_percentile` function might cause TiDB panic [#40463](https://github.com/pingcap/tidb/issues/40463) @[xzhangxian1008](https://github.com/xzhangxian1008) + - Fix the issue that TiDB might implicitly insert the `from_binary` function when the argument of a string function is a `NULL` constant, causing some expressions unable to be pushed down to TiFlash [#49526](https://github.com/pingcap/tidb/issues/49526) @[YangKeao](https://github.com/YangKeao) + - Fix the goroutine leak issue that might occur when the `HashJoin` operator fails to spill to disk [#50841](https://github.com/pingcap/tidb/issues/50841) @[wshwsh12](https://github.com/wshwsh12) + - Fix the issue that `BIT` type columns might cause query errors due to decode failures when they are involved in calculations of some functions [#49566](https://github.com/pingcap/tidb/issues/49566) [#50850](https://github.com/pingcap/tidb/issues/50850) [#50855](https://github.com/pingcap/tidb/issues/50855) @[jiyfhust](https://github.com/jiyfhust) + - Fix the goroutine leak issue that occurs when the memory usage of CTE queries exceed limits [#50337](https://github.com/pingcap/tidb/issues/50337) @[guo-shaoge](https://github.com/guo-shaoge) + - Fix the issue that wrong results might be returned when TiFlash late materialization processes associated columns [#49241](https://github.com/pingcap/tidb/issues/49241) [#51204](https://github.com/pingcap/tidb/issues/51204) @[Lloyd-Pottiger](https://github.com/Lloyd-Pottiger) + - Fix the issue that the background job thread of TiDB might panic when TiDB records historical statistics [#49076](https://github.com/pingcap/tidb/issues/49076) @[hawkingrei](https://github.com/hawkingrei) + - Fix the error that might occur when TiDB merges histograms of global statistics for partitioned tables [#49023](https://github.com/pingcap/tidb/issues/49023) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that the historical statistics of the `stats_meta` table are not updated after a partition is dropped [#49334](https://github.com/pingcap/tidb/issues/49334) @[hi-rustin](https://github.com/hi-rustin) + - Fix the issue of incorrect query results caused by multi-valued indexes mistakenly selected as the `Index Join` probe side [#50382](https://github.com/pingcap/tidb/issues/50382) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that the `USE_INDEX_MERGE` hint does not take effect on multi-valued indexes [#50553](https://github.com/pingcap/tidb/issues/50553) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that users might get errors when querying the `INFORMATION_SCHEMA.ANALYZE_STATUS` system table [#48835](https://github.com/pingcap/tidb/issues/48835) @[hi-rustin](https://github.com/hi-rustin) + - Fix the issue of wrong query results due to TiDB incorrectly eliminating constant values in `group by` [#38756](https://github.com/pingcap/tidb/issues/38756) @[hi-rustin](https://github.com/hi-rustin) + - Fix the issue that the `processed_rows` of the `ANALYZE` task on a table might exceed the total number of rows in that table [#50632](https://github.com/pingcap/tidb/issues/50632) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that TiDB might panic when using the `EXECUTE` statement to execute `PREPARE STMT` after the `tidb_enable_prepared_plan_cache` system variable is enabled and then disabled [#49344](https://github.com/pingcap/tidb/issues/49344) @[qw4990](https://github.com/qw4990) + - Fix the `Column ... in from clause is ambiguous` error that might occur when a query uses `NATURAL JOIN` [#32044](https://github.com/pingcap/tidb/issues/32044) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that using a multi-valued index to access an empty JSON array might return incorrect results [#50125](https://github.com/pingcap/tidb/issues/50125) @[YangKeao](https://github.com/YangKeao) + - Fix the `Can't find column ...` error that might occur when aggregate functions are used for group calculations [#50926](https://github.com/pingcap/tidb/issues/50926) @[qw4990](https://github.com/qw4990) + - Fix the issue that the control of `SET_VAR` for variables of the string type might become invalid [#50507](https://github.com/pingcap/tidb/issues/50507) @[qw4990](https://github.com/qw4990) + - Fix the issue that high CPU usage of TiDB occurs due to long-term memory pressure caused by `tidb_server_memory_limit` [#48741](https://github.com/pingcap/tidb/issues/48741) @[XuHuaiyu](https://github.com/XuHuaiyu) + - Fix the issue that the completion times of two DDL tasks with dependencies are incorrectly sequenced [#49498](https://github.com/pingcap/tidb/issues/49498) @[tangenta](https://github.com/tangenta) + - Fix the issue that illegal optimizer hints might cause valid hints to be ineffective [#49308](https://github.com/pingcap/tidb/issues/49308) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that DDL statements with the `CHECK` constraint are stuck [#47632](https://github.com/pingcap/tidb/issues/47632) @[jiyfhust](https://github.com/jiyfhust) + - Fix the issue that the behavior of the `ENFORCED` option in the `CHECK` constraint is inconsistent with MySQL 8.0 [#47567](https://github.com/pingcap/tidb/issues/47567) [#47631](https://github.com/pingcap/tidb/issues/47631) @[jiyfhust](https://github.com/jiyfhust) + - Fix the issue that CTE queries might report an error `type assertion for CTEStorageMap failed` during the retry process [#46522](https://github.com/pingcap/tidb/issues/46522) @[tiancaiamao](https://github.com/tiancaiamao) + - Fix the issue that the `DELETE` and `UPDATE` statements using index lookup might report an error when `tidb_multi_statement_mode` mode is enabled [#50012](https://github.com/pingcap/tidb/issues/50012) @[tangenta](https://github.com/tangenta) + - Fix the issue that `UPDATE` or `DELETE` statements containing `WITH RECURSIVE` CTEs might produce incorrect results [#48969](https://github.com/pingcap/tidb/issues/48969) @[winoros](https://github.com/winoros) + - Fix the issue that the optimizer incorrectly converts TiFlash selection path to the DUAL table in specific scenarios [#49285](https://github.com/pingcap/tidb/issues/49285) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that the same query plan has different `PLAN_DIGEST` values in some cases [#47634](https://github.com/pingcap/tidb/issues/47634) @[King-Dylan](https://github.com/King-Dylan) + - Fix the issue that after the time window for automatic statistics updates is configured, statistics might still be updated outside that time window [#49552](https://github.com/pingcap/tidb/issues/49552) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that the query result is incorrect when an `ENUM` type column is used as the join key [#48991](https://github.com/pingcap/tidb/issues/48991) @[winoros](https://github.com/winoros) + - Fix the issue that executing `UNIQUE` index lookup with an `ORDER BY` clause might cause an error [#49920](https://github.com/pingcap/tidb/issues/49920) @[jackysp](https://github.com/jackysp) + - Fix the issue that `LIMIT` in multi-level nested `UNION` queries might become ineffective [#49874](https://github.com/pingcap/tidb/issues/49874) @[Defined2014](https://github.com/Defined2014) + - Fix the issue that the result of `COUNT(INT)` calculated by MPP might be incorrect [#48643](https://github.com/pingcap/tidb/issues/48643) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that parsing invalid values of `ENUM` or `SET` types would directly cause SQL statement errors [#49487](https://github.com/pingcap/tidb/issues/49487) @[winoros](https://github.com/winoros) + - Fix the issue that TiDB panics and reports an error `invalid memory address or nil pointer dereference` [#42739](https://github.com/pingcap/tidb/issues/42739) @[CbcWestwolf](https://github.com/CbcWestwolf) + - Fix the issue that executing `UNION ALL` with the DUAL table as the first subnode might cause an error [#48755](https://github.com/pingcap/tidb/issues/48755) @[winoros](https://github.com/winoros) + - Fix the issue that common hints do not take effect in `UNION ALL` statements [#50068](https://github.com/pingcap/tidb/issues/50068) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that TiDB server might panic during graceful shutdown [#36793](https://github.com/pingcap/tidb/issues/36793) @[bb7133](https://github.com/bb7133) + - Fix the issue that Daylight Saving Time is displayed incorrectly in some time zones [#49586](https://github.com/pingcap/tidb/issues/49586) @[overvenus](https://github.com/overvenus) + - Fix the issue that static `CALIBRATE RESOURCE` relies on the Prometheus data [#49174](https://github.com/pingcap/tidb/issues/49174) @[glorv](https://github.com/glorv) + - Fix the issue that hints cannot be used in `REPLACE INTO` statements [#34325](https://github.com/pingcap/tidb/issues/34325) @[YangKeao](https://github.com/YangKeao) + - Fix the issue that executing queries containing the `GROUP_CONCAT(ORDER BY)` syntax might return errors [#49986](https://github.com/pingcap/tidb/issues/49986) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that TiDB server might consume a significant amount of resources when the enterprise plugin for audit logging is used [#49273](https://github.com/pingcap/tidb/issues/49273) @[lcwangchao](https://github.com/lcwangchao) + - Fix the issue that using old interfaces might cause inconsistent metadata for tables [#49751](https://github.com/pingcap/tidb/issues/49751) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that disabling `tidb_enable_collect_execution_info` causes the coprocessor cache to panic [#48212](https://github.com/pingcap/tidb/issues/48212) @[you06](https://github.com/you06) + - Fix the issue that executing `ALTER TABLE ... LAST PARTITION` fails when the partition column type is `DATETIME` [#48814](https://github.com/pingcap/tidb/issues/48814) @[crazycs520](https://github.com/crazycs520) + - Fix the issue that the `COMMIT` or `ROLLBACK` operation executed through `COM_STMT_EXECUTE` fails to terminate transactions that have timed out [#49151](https://github.com/pingcap/tidb/issues/49151) @[zyguan](https://github.com/zyguan) + - Fix the issue that histogram statistics might not be parsed into readable strings when the histogram boundary contains `NULL` [#49823](https://github.com/pingcap/tidb/issues/49823) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that queries containing common table expressions (CTEs) unexpectedly get stuck when the memory limit is exceeded [#49096](https://github.com/pingcap/tidb/issues/49096) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that data is inconsistent under the TiDB Distributed eXecution Framework (DXF) when executing `ADD INDEX` after the DDL Owner is network isolated [#49773](https://github.com/pingcap/tidb/issues/49773) @[tangenta](https://github.com/tangenta) + - Fix the issue that the auto-increment ID allocation reports an error due to concurrent conflicts when using an auto-increment column with `AUTO_ID_CACHE=1` [#50519](https://github.com/pingcap/tidb/issues/50519) @[tiancaiamao](https://github.com/tiancaiamao) + - Fix the issue that TiDB might panic when a query contains the Apply operator and the `fatal error: concurrent map writes` error occurs [#50347](https://github.com/pingcap/tidb/issues/50347) @[SeaRise](https://github.com/SeaRise) + - Fix the TiDB node panic issue that occurs when DDL `jobID` is restored to 0 [#46296](https://github.com/pingcap/tidb/issues/46296) @[jiyfhust](https://github.com/jiyfhust) + - Fix the issue that query results are incorrect due to `STREAM_AGG()` incorrectly handling CI [#49902](https://github.com/pingcap/tidb/issues/49902) @[wshwsh12](https://github.com/wshwsh12) + - Mitigate the issue that TiDB nodes might encounter OOM errors when dealing with a large number of tables or partitions [#50077](https://github.com/pingcap/tidb/issues/50077) @[zimulala](https://github.com/zimulala) + - Fix the issue that the `LEADING` hint does not take effect in `UNION ALL` statements [#50067](https://github.com/pingcap/tidb/issues/50067) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that `LIMIT` and `OPRDERBY` might be invalid in nested `UNION` queries [#49377](https://github.com/pingcap/tidb/issues/49377) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that a query containing the IndexHashJoin operator gets stuck when memory exceeds `tidb_mem_quota_query` [#49033](https://github.com/pingcap/tidb/issues/49033) @[XuHuaiyu](https://github.com/XuHuaiyu) + - Fix the issue that TiDB returns wrong query results when processing `ENUM` or `SET` types by constant propagation [#49440](https://github.com/pingcap/tidb/issues/49440) @[winoros](https://github.com/winoros) + - Fix the issue that executing `SELECT INTO OUTFILE` using the `PREPARE` method incorrectly returns a success message instead of an error [#49166](https://github.com/pingcap/tidb/issues/49166) @[qw4990](https://github.com/qw4990) + - Fix the issue that enforced sorting might become ineffective when a query uses optimizer hints (such as `STREAM_AGG()`) that enforce sorting and its execution plan contains `IndexMerge` [#49605](https://github.com/pingcap/tidb/issues/49605) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that tables with `AUTO_ID_CACHE=1` might lead to gRPC client leaks when there are a large number of tables [#48869](https://github.com/pingcap/tidb/issues/48869) @[tiancaiamao](https://github.com/tiancaiamao) + - Fix the issue that in non-strict mode (`sql_mode = ''`), truncation during executing `INSERT` still reports an error [#49369](https://github.com/pingcap/tidb/issues/49369) @[tiancaiamao](https://github.com/tiancaiamao) + - Fix the issue that using the `_` wildcard in `LIKE` when the data contains trailing spaces can result in incorrect query results [#48983](https://github.com/pingcap/tidb/issues/48983) @[time-and-fate](https://github.com/time-and-fate) + - Fix the issue that executing `ADMIN CHECK` after updating the `tidb_mem_quota_query` system variable returns `ERROR 8175` [#49258](https://github.com/pingcap/tidb/issues/49258) @[tangenta](https://github.com/tangenta) + - Fix the issue of excessive statistical error in constructing statistics caused by Golang's implicit conversion algorithm [#49801](https://github.com/pingcap/tidb/issues/49801) @[qw4990](https://github.com/qw4990) + - Fix the issue that queries containing CTEs report `runtime error: index out of range [32] with length 32` when `tidb_max_chunk_size` is set to a small value [#48808](https://github.com/pingcap/tidb/issues/48808) @[guo-shaoge](https://github.com/guo-shaoge) + ++ TiKV + + - Fix the issue that enabling `tidb_enable_row_level_checksum` might cause TiKV to panic [#16371](https://github.com/tikv/tikv/issues/16371) @[cfzjywxk](https://github.com/cfzjywxk) + - Fix the issue that TiKV might panic when gRPC threads are checking `is_shutdown` [#16236](https://github.com/tikv/tikv/issues/16236) @[pingyu](https://github.com/pingyu) + - Fix the issue that TiKV converts the time zone incorrectly for Brazil and Egypt [#16220](https://github.com/tikv/tikv/issues/16220) @[overvenus](https://github.com/overvenus) + - Fix the issue that `blob-run-mode` in Titan cannot be updated online [#15978](https://github.com/tikv/tikv/issues/15978) @[tonyxuqqi](https://github.com/tonyxuqqi) + - Fix the issue that TiDB and TiKV might produce inconsistent results when processing `DECIMAL` arithmetic multiplication truncation [#16268](https://github.com/tikv/tikv/issues/16268) @[solotzg](https://github.com/solotzg) + - Fix the issue that Flashback might get stuck when encountering `notLeader` or `regionNotFound` [#15712](https://github.com/tikv/tikv/issues/15712) @[HuSharp](https://github.com/HuSharp) + - Fix the issue that damaged SST files might be spread to other TiKV nodes [#15986](https://github.com/tikv/tikv/issues/15986) @[Connor1996](https://github.com/Connor1996) + - Fix the issue that if TiKV runs extremely slowly, it might panic after Region merge [#16111](https://github.com/tikv/tikv/issues/16111) @[overvenus](https://github.com/overvenus) + - Fix the issue that the joint state of DR Auto-Sync might time out when scaling out [#15817](https://github.com/tikv/tikv/issues/15817) @[Connor1996](https://github.com/Connor1996) + - Fix the issue that Resolved TS might be blocked for two hours [#11847](https://github.com/tikv/tikv/issues/11847) [#15520](https://github.com/tikv/tikv/issues/15520) [#39130](https://github.com/pingcap/tidb/issues/39130) @[overvenus](https://github.com/overvenus) + - Fix the issue that `cast_duration_as_time` might return incorrect results [#16211](https://github.com/tikv/tikv/issues/16211) @[gengliqi](https://github.com/gengliqi) + ++ PD + + - Fix the issue that querying resource groups in batch might cause PD to panic [#7206](https://github.com/tikv/pd/issues/7206) @[nolouch](https://github.com/nolouch) + - Fix the issue that PD cannot read resource limitations when it is started with `systemd` [#7628](https://github.com/tikv/pd/issues/7628) @[bufferflies](https://github.com/bufferflies) + - Fix the issue that continuous jitter in PD disk latency might cause PD to fail to select a new leader [#7251](https://github.com/tikv/pd/issues/7251) @[HuSharp](https://github.com/HuSharp) + - Fix the issue that a network partition in PD might cause scheduling not to be started immediately [#7016](https://github.com/tikv/pd/issues/7016) @[HuSharp](https://github.com/HuSharp) + - Fix the issue that the PD monitoring item `learner-peer-count` does not synchronize the old value after a leader switch [#7728](https://github.com/tikv/pd/issues/7728) @[CabinfeverB](https://github.com/CabinfeverB) + - Fix the issue that when PD leader is transferred and there is a network partition between the new leader and the PD client, the PD client fails to update the information of the leader [#7416](https://github.com/tikv/pd/issues/7416) @[CabinfeverB](https://github.com/CabinfeverB) + - Fix some security issues by upgrading the version of Gin Web Framework from v1.8.1 to v1.9.1 [#7438](https://github.com/tikv/pd/issues/7438) @[niubell](https://github.com/niubell) + - Fix the issue that the orphan peer is deleted when the number of replicas does not meet the requirements [#7584](https://github.com/tikv/pd/issues/7584) @[bufferflies](https://github.com/bufferflies) + - Fix the issue that querying a Region without a leader using `pd-ctl` might cause PD to panic [#7630](https://github.com/tikv/pd/issues/7630) @[rleungx](https://github.com/rleungx) + ++ TiFlash + + - Fix the issue that TiFlash might panic due to unstable network connections with PD during replica migration [#8323](https://github.com/pingcap/tiflash/issues/8323) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix the issue that removing and then re-adding TiFlash replicas might lead to data corruption in TiFlash [#8695](https://github.com/pingcap/tiflash/issues/8695) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix a potential issue that `FLASHBACK TABLE` or `RECOVER TABLE` might fail to recover data of some TiFlash replicas if `DROP TABLE` is executed immediately after data insertion [#8395](https://github.com/pingcap/tiflash/issues/8395) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix incorrect display of maximum percentile time for some panels in Grafana [#8076](https://github.com/pingcap/tiflash/issues/8076) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix the issue that TiFlash might crash during remote reads [#8685](https://github.com/pingcap/tiflash/issues/8685) @[guo-shaoge](https://github.com/guo-shaoge) + - Fix the issue that TiFlash incorrectly handles `ENUM` when the `ENUM` value is 0 [#8311](https://github.com/pingcap/tiflash/issues/8311) @[solotzg](https://github.com/solotzg) + - Fix the issue that short queries executed successfully print excessive info logs [#8592](https://github.com/pingcap/tiflash/issues/8592) @[windtalker](https://github.com/windtalker) + - Fix the issue that the memory usage increases significantly due to slow queries [#8564](https://github.com/pingcap/tiflash/issues/8564) @[JinheLin](https://github.com/JinheLin) + - Fix the issue that the `lowerUTF8` and `upperUTF8` functions do not allow characters in different cases to occupy different bytes [#8484](https://github.com/pingcap/tiflash/issues/8484) @[gengliqi](https://github.com/gengliqi) + - Fix the potential OOM issue that might occur when scanning multiple partitioned tables during stream read [#8505](https://github.com/pingcap/tiflash/issues/8505) @[gengliqi](https://github.com/gengliqi) + - Fix the issue of memory leak when TiFlash encounters memory limitation during query [#8447](https://github.com/pingcap/tiflash/issues/8447) @[JinheLin](https://github.com/JinheLin) + - Fix the TiFlash panic issue when TiFlash encounters conflicts during concurrent DDL execution [#8578](https://github.com/pingcap/tiflash/issues/8578) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix the issue that TiFlash panics after executing `ALTER TABLE ... MODIFY COLUMN ... NOT NULL`, which changes nullable columns to non-nullable [#8419](https://github.com/pingcap/tiflash/issues/8419) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix the issue that query results are incorrect when querying with filtering conditions like `ColumnRef in (Literal, Func...)` [#8631](https://github.com/pingcap/tiflash/issues/8631) @[Lloyd-Pottiger](https://github.com/Lloyd-Pottiger) + - Fix the issue that data of TiFlash replicas would still be garbage collected after executing `FLASHBACK DATABASE` [#8450](https://github.com/pingcap/tiflash/issues/8450) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix the issue that TiFlash might not be able to select the GC owner of object storage data under the disaggregated storage and compute architecture [#8519](https://github.com/pingcap/tiflash/issues/8519) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix the random invalid memory access issue that might occur with `GREATEST` or `LEAST` functions containing constant string parameters [#8604](https://github.com/pingcap/tiflash/issues/8604) @[windtalker](https://github.com/windtalker) + - Fix the issue that TiFlash replica data might be accidentally deleted after performing point-in-time recovery (PITR) or executing `FLASHBACK CLUSTER TO`, which might result in data anomalies [#8777](https://github.com/pingcap/tiflash/issues/8777) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix the issue that TiFlash Anti Semi Join might return incorrect results when the join includes non-equivalent conditions [#8791](https://github.com/pingcap/tiflash/issues/8791) @[windtalker](https://github.com/windtalker) ++ Tools + + + Backup & Restore (BR) + + - Fix the issue that data restore is slowed down due to absence of a leader on a TiKV node [#50566](https://github.com/pingcap/tidb/issues/50566) @[Leavrth](https://github.com/Leavrth) + - Fix the issue that full restore still requires the target cluster to be empty after the `--filter` option is specified [#51009](https://github.com/pingcap/tidb/issues/51009) @[3pointer](https://github.com/3pointer) + - Fix the issue that when resuming from a checkpoint after data restore fails, an error `the target cluster is not fresh` occurs [#50232](https://github.com/pingcap/tidb/issues/50232) @[Leavrth](https://github.com/Leavrth) + - Fix the issue that stopping a log backup task causes TiDB to crash [#50839](https://github.com/pingcap/tidb/issues/50839) @[YuJuncen](https://github.com/YuJuncen) + - Fix the issue that the `Unsupported collation` error is reported when you restore data from backups of an old version [#49466](https://github.com/pingcap/tidb/issues/49466) @[3pointer](https://github.com/3pointer) + - Fix the issue that the log backup task can start but does not work properly if failing to connect to PD during task initialization [#16056](https://github.com/tikv/tikv/issues/16056) @[YuJuncen](https://github.com/YuJuncen) + - Fix the issue that BR generates incorrect URIs for external storage files [#48452](https://github.com/pingcap/tidb/issues/48452) @[3AceShowHand](https://github.com/3AceShowHand) + - Fix the issue that log backup gets stuck after changing the TiKV IP address on the same node [#50445](https://github.com/pingcap/tidb/issues/50445) @[3pointer](https://github.com/3pointer) + - Fix the issue that BR cannot retry when encountering an error while reading file content from S3 [#49942](https://github.com/pingcap/tidb/issues/49942) @[Leavrth](https://github.com/Leavrth) + + + TiCDC + + - Fix the issue that the sink module fails to restart correctly after encountering an error when Syncpoint is enabled (`enable-sync-point = true`) [#10091](https://github.com/pingcap/tiflow/issues/10091) @[hicqu](https://github.com/hicqu) + - Fix the issue that the file sequence number generated by the storage service might not increment correctly when using the storage sink [#10352](https://github.com/pingcap/tiflow/issues/10352) @[CharlesCheung96](https://github.com/CharlesCheung96) + - Fix the issue that the Syncpoint table might be incorrectly replicated [#10576](https://github.com/pingcap/tiflow/issues/10576) @[asddongmen](https://github.com/asddongmen) + - Fix the issue that OAuth2.0, TLS, and mTLS cannot be enabled properly when using Apache Pulsar as the downstream [#10602](https://github.com/pingcap/tiflow/issues/10602) @[asddongmen](https://github.com/asddongmen) + - Fix the issue that TiCDC returns the `ErrChangeFeedAlreadyExists` error when concurrently creating multiple changefeeds [#10430](https://github.com/pingcap/tiflow/issues/10430) @[CharlesCheung96](https://github.com/CharlesCheung96) + - Fix the issue that the changefeed `resolved ts` does not advance in extreme cases [#10157](https://github.com/pingcap/tiflow/issues/10157) @[sdojjy](https://github.com/sdojjy) + - Fix the issue that TiCDC mistakenly closes the connection with TiKV in certain special scenarios [#10239](https://github.com/pingcap/tiflow/issues/10239) @[hicqu](https://github.com/hicqu) + - Fix the issue that the TiCDC server might panic when replicating data to an object storage service [#10137](https://github.com/pingcap/tiflow/issues/10137) @[sdojjy](https://github.com/sdojjy) + - Fix the issue that the changefeed reports an error after `TRUNCATE PARTITION` is executed on the upstream table [#10522](https://github.com/pingcap/tiflow/issues/10522) @[sdojjy](https://github.com/sdojjy) + - Fix the issue that after filtering out `add table partition` events is configured in `ignore-event`, TiCDC does not replicate other types of DML changes for related partitions to the downstream [#10524](https://github.com/pingcap/tiflow/issues/10524) @[CharlesCheung96](https://github.com/CharlesCheung96) + - Fix the potential data race issue during `kv-client` initialization [#10095](https://github.com/pingcap/tiflow/issues/10095) @[3AceShowHand](https://github.com/3AceShowHand) + + + TiDB Data Migration (DM) + + - Fix the issue that a migration task error occurs when the downstream table structure contains `shard_row_id_bits` [#10308](https://github.com/pingcap/tiflow/issues/10308) @[GMHDBJD](https://github.com/GMHDBJD) + - Fix the issue that DM encounters "event type truncate not valid" error that causes the upgrade to fail [#10282](https://github.com/pingcap/tiflow/issues/10282) @[GMHDBJD](https://github.com/GMHDBJD) diff --git a/releases/release-notes.md b/releases/release-notes.md index 29b8db0f8b366..5607172aac383 100644 --- a/releases/release-notes.md +++ b/releases/release-notes.md @@ -11,6 +11,7 @@ aliases: ['/docs/dev/releases/release-notes/','/docs/dev/releases/rn/'] ## 7.5 +- [7.5.1](/releases/release-7.5.1.md): 2024-02-29 - [7.5.0](/releases/release-7.5.0.md): 2023-12-01 ## 7.4 diff --git a/releases/release-timeline.md b/releases/release-timeline.md index 736de96273f97..78b8ebd1c71b5 100644 --- a/releases/release-timeline.md +++ b/releases/release-timeline.md @@ -9,6 +9,7 @@ This document shows all the released TiDB versions in reverse chronological orde | Version | Release Date | | :--- | :--- | +| [7.5.1](/releases/release-7.5.1.md) | 2024-02-29 | | [6.5.8](/releases/release-6.5.8.md) | 2024-02-02 | | [7.6.0-DMR](/releases/release-7.6.0.md) | 2024-01-25 | | [6.5.7](/releases/release-6.5.7.md) | 2024-01-08 | From 5c8d5430306ca8a5c2641dff5a103d53332f0847 Mon Sep 17 00:00:00 2001 From: Aolin Date: Thu, 29 Feb 2024 14:53:01 +0800 Subject: [PATCH 12/82] pdf: implement automatic underscore wrapping table cells (#16613) --- templates/template.tex | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/templates/template.tex b/templates/template.tex index cf372e561d9ee..acbf021b06e2f 100644 --- a/templates/template.tex +++ b/templates/template.tex @@ -8,6 +8,8 @@ \usepackage{setspace} \setstretch{$linestretch$} $endif$ +\usepackage{etoolbox} +\usepackage{xstring} \usepackage{amssymb,amsmath} \usepackage{ifxetex,ifluatex} \usepackage{fixltx2e} % provides \textsubscript @@ -68,6 +70,7 @@ \usepackage{xcolor} \usepackage{listings} \lstset{ + literate={_}{\_}1, basicstyle=\ttfamily, keywordstyle=\color[rgb]{0.13,0.29,0.53}\bfseries, stringstyle=\color[rgb]{0.31,0.60,0.02}, @@ -93,6 +96,14 @@ $endif$ $if(tables)$ \usepackage{longtable,booktabs} +% set table to left-aligned +\setlength\LTleft{0pt} +\setlength\LTright{0pt} +% fill the columns to page width +\makeatletter +\patchcmd\LT@array{\tabskip\z@}{\extracolsep{\fill}} +\makeatletter + $endif$ $if(graphics)$ \usepackage{graphicx} @@ -114,8 +125,8 @@ \fi \hypersetup{breaklinks=true, bookmarks=true, - pdfauthor={$author-meta$}, - pdftitle={$title-meta$}, + pdfauthor={$author$}, + pdftitle={$title$}, colorlinks=true, citecolor=$if(citecolor)$$citecolor$$else$blue$endif$, urlcolor=$if(urlcolor)$$urlcolor$$else$blue$endif$, From 30d8ecfe7168ab19bef36b4d687af8c1d7d6b4d1 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Thu, 29 Feb 2024 17:02:20 +0800 Subject: [PATCH 13/82] [skip ci] Update OWNERS file (#16627) skip-checks: true --- OWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OWNERS b/OWNERS index ec95e7e30cb68..928908987c355 100644 --- a/OWNERS +++ b/OWNERS @@ -10,6 +10,7 @@ approvers: - dragonly - en-jin19 - hfxsd + - Icemap - jackysp - kissmydb - lance6716 @@ -40,7 +41,6 @@ reviewers: - ericsyh - glkappe - GMHDBJD - - Icemap - Joyinqin - junlan-zhang - KanShiori From 528dc73dc2cf6ed757bd11348910fb752da1ffc3 Mon Sep 17 00:00:00 2001 From: Aolin Date: Thu, 29 Feb 2024 17:48:31 +0800 Subject: [PATCH 14/82] develop: update env file code examples (#16612) --- develop/dev-guide-sample-application-nodejs-prisma.md | 6 +++--- develop/dev-guide-sample-application-ruby-rails.md | 6 +++--- tidb-cloud/serverless-driver-kysely-example.md | 6 +++--- tidb-cloud/serverless-driver-prisma-example.md | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/develop/dev-guide-sample-application-nodejs-prisma.md b/develop/dev-guide-sample-application-nodejs-prisma.md index d594cc21296fc..e3fe11a0416f7 100644 --- a/develop/dev-guide-sample-application-nodejs-prisma.md +++ b/develop/dev-guide-sample-application-nodejs-prisma.md @@ -101,7 +101,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 6. Edit the `.env` file, set up the environment variable `DATABASE_URL` as follows, and replace the corresponding placeholders `{}` with the connection string in the connection dialog: ```dotenv - DATABASE_URL={connection_string} + DATABASE_URL='{connection_string}' ``` > **Note** @@ -138,7 +138,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 5. Edit the `.env` file, set up the environment variable `DATABASE_URL` as follows, replace the corresponding placeholders `{}` with connection parameters on the connection dialog: ```dotenv - DATABASE_URL=mysql://{user}:{password}@{host}:4000/test?sslaccept=strict&sslcert={downloaded_ssl_ca_path} + DATABASE_URL='mysql://{user}:{password}@{host}:4000/test?sslaccept=strict&sslcert={downloaded_ssl_ca_path}' ``` > **Note** @@ -167,7 +167,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 2. Edit the `.env` file, set up the environment variable `DATABASE_URL` as follows, replace the corresponding placeholders `{}` with connection parameters of your TiDB cluster: ```dotenv - DATABASE_URL=mysql://{user}:{password}@{host}:4000/test + DATABASE_URL='mysql://{user}:{password}@{host}:4000/test' ``` If you are running TiDB locally, the default host address is `127.0.0.1`, and the password is empty. diff --git a/develop/dev-guide-sample-application-ruby-rails.md b/develop/dev-guide-sample-application-ruby-rails.md index 83732dbaa02e2..4d8056af2772e 100644 --- a/develop/dev-guide-sample-application-ruby-rails.md +++ b/develop/dev-guide-sample-application-ruby-rails.md @@ -97,7 +97,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 6. Edit the `.env` file, set up the `DATABASE_URL` environment variable as follows, and copy the connection string from the connection dialog as the variable value. ```dotenv - DATABASE_URL=mysql2://{user}:{password}@{host}:{port}/{database_name}?ssl_mode=verify_identity + DATABASE_URL='mysql2://{user}:{password}@{host}:{port}/{database_name}?ssl_mode=verify_identity' ``` > **Note** @@ -126,7 +126,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 5. Edit the `.env` file, set up the `DATABASE_URL` environment variable as follows, copy the connection string from the connection dialog as the variable value, and set the `sslca` query parameter to the file path of the CA certificate downloaded from the connection dialog: ```dotenv - DATABASE_URL=mysql2://{user}:{password}@{host}:{port}/{database}?ssl_mode=verify_identity&sslca=/path/to/ca.pem + DATABASE_URL='mysql2://{user}:{password}@{host}:{port}/{database}?ssl_mode=verify_identity&sslca=/path/to/ca.pem' ``` > **Note** @@ -149,7 +149,7 @@ Connect to your TiDB cluster depending on the TiDB deployment option you've sele 2. Edit the `.env` file, set up the `DATABASE_URL` environment variable as follows, and replace the `{user}`, `{password}`, `{host}`, `{port}`, and `{database}` with your own TiDB connection information: ```dotenv - DATABASE_URL=mysql2://{user}:{password}@{host}:{port}/{database} + DATABASE_URL='mysql2://{user}:{password}@{host}:{port}/{database}' ``` If you are running TiDB locally, the default host address is `127.0.0.1`, and the password is empty. diff --git a/tidb-cloud/serverless-driver-kysely-example.md b/tidb-cloud/serverless-driver-kysely-example.md index 4278146387652..ded6989ccf6af 100644 --- a/tidb-cloud/serverless-driver-kysely-example.md +++ b/tidb-cloud/serverless-driver-kysely-example.md @@ -82,7 +82,7 @@ To complete this tutorial, you need the following: 2. Set the environment variable `DATABASE_URL` in your local environment. For example, in Linux or macOS, you can run the following command: ```bash - export DATABASE_URL=mysql://[username]:[password]@[host]/[database] + export DATABASE_URL='mysql://[username]:[password]@[host]/[database]' ``` ### Step 3. Use Kysely to query data @@ -275,7 +275,7 @@ mysql://[username]:[password]@[host]/[database] 3. Test your code locally: ``` - export DATABASE_URL=mysql://[username]:[password]@[host]/[database] + export DATABASE_URL='mysql://[username]:[password]@[host]/[database]' next dev ``` @@ -286,7 +286,7 @@ mysql://[username]:[password]@[host]/[database] 1. Deploy your code to Vercel with the `DATABASE_URL` environment variable: ``` - vercel -e DATABASE_URL=mysql://[username]:[password]@[host]/[database] --prod + vercel -e DATABASE_URL='mysql://[username]:[password]@[host]/[database]' --prod ``` After the deployment is complete, you will get the URL of your project. diff --git a/tidb-cloud/serverless-driver-prisma-example.md b/tidb-cloud/serverless-driver-prisma-example.md index c266fadf26455..49b3ffd9a7c88 100644 --- a/tidb-cloud/serverless-driver-prisma-example.md +++ b/tidb-cloud/serverless-driver-prisma-example.md @@ -68,7 +68,7 @@ To complete this tutorial, you need the following: 2. In the root directory of your project, create a file named `.env`, define an environment variable named `DATABASE_URL` as follows, and then replace the placeholders `[]` in this variable with the corresponding parameters in the connection string. ```dotenv - DATABASE_URL="mysql://[username]:[password]@[host]:4000/[database]?sslaccept=strict" + DATABASE_URL='mysql://[username]:[password]@[host]:4000/[database]?sslaccept=strict' ``` > **Note:** From a8648ba2406ee9a1b56b330b9e758223ca125eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Eeden?= Date: Thu, 29 Feb 2024 15:51:31 +0100 Subject: [PATCH 15/82] status-variables: Add conditional status that are not available with unistore (#15918) --- status-variables.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/status-variables.md b/status-variables.md index 4ecdf114fd93e..ec577d88c6173 100644 --- a/status-variables.md +++ b/status-variables.md @@ -90,3 +90,33 @@ Additionally, the [FLUSH STATUS](/sql-statements/sql-statement-flush-status.md) - Scope: SESSION | GLOBAL - Type: String - The UUID of the server. + +### tidb_gc_last_run_time + +- Scope: SESSION | GLOBAL +- Type: String +- The timestamp of the last run of [GC](/garbage-collection-overview.md). + +### tidb_gc_leader_desc + +- Scope: SESSION | GLOBAL +- Type: String +- Information about [GC](/garbage-collection-overview.md) leader, including the hostname and process id (pid). + +### tidb_gc_leader_lease + +- Scope: SESSION | GLOBAL +- Type: String +- The timestamp of the [GC](/garbage-collection-overview.md) lease. + +### tidb_gc_leader_uuid + +- Scope: SESSION | GLOBAL +- Type: String +- The UUID of the [GC](/garbage-collection-overview.md) leader. + +### tidb_gc_safe_point + +- Scope: SESSION | GLOBAL +- Type: String +- The timestamp of the [GC](/garbage-collection-overview.md) safe point. From de815dc10da0a851af83e1e3d27f5b0dea350b27 Mon Sep 17 00:00:00 2001 From: CbcWestwolf <1004626265@qq.com> Date: Fri, 1 Mar 2024 09:50:01 +0800 Subject: [PATCH 16/82] Add description for `tidb_auth_token` authentication (#15979) --- basic-features.md | 2 +- security-compatibility-with-mysql.md | 123 +++++++++++++++++++- sql-statements/sql-statement-alter-user.md | 6 + sql-statements/sql-statement-create-user.md | 6 + system-variables.md | 1 - tidb-configuration-file.md | 12 +- 6 files changed, 136 insertions(+), 14 deletions(-) diff --git a/basic-features.md b/basic-features.md index 909567ef55057..ed54778107a00 100644 --- a/basic-features.md +++ b/basic-features.md @@ -194,7 +194,7 @@ You can try out TiDB features on [TiDB Playground](https://play.tidbcloud.com/?u | [Certificate-based authentication](/certificate-authentication.md) | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | | [`caching_sha2_password` authentication](/system-variables.md#default_authentication_plugin) | Y | Y | Y | Y | Y | Y | Y | Y | N | N | N | | [`tidb_sm3_password` authentication](/system-variables.md#default_authentication_plugin) | Y | Y | Y | Y | N | N | N | N | N | N | N | -| [`tidb_auth_token` authentication](/system-variables.md#default_authentication_plugin) | Y | Y | Y | Y | N | N | N | N | N | N | N | +| [`tidb_auth_token` authentication](/security-compatibility-with-mysql.md#tidb_auth_token) | Y | Y | Y | Y | N | N | N | N | N | N | N | | [`authentication_ldap_sasl` authentication](/system-variables.md#default_authentication_plugin) | Y | Y | N | N | N | N | N | N | N | N | | [`authentication_ldap_simple` authentication](/system-variables.md#default_authentication_plugin) | Y | Y | Y | N | N | N | N | N | N | N | N | | [Password management](/password-management.md) | Y | Y | Y | Y | N | N | N | N | N | N | N | diff --git a/security-compatibility-with-mysql.md b/security-compatibility-with-mysql.md index e96c74c830afa..ba6a5b0972cc8 100644 --- a/security-compatibility-with-mysql.md +++ b/security-compatibility-with-mysql.md @@ -108,9 +108,9 @@ The implementation mechanisms are consistent between TiDB and MySQL. Both use th ## Authentication plugin status -TiDB supports multiple authentication methods. These methods can be specified on a per user basis using [`CREATE USER`](/sql-statements/sql-statement-create-user.md) and [`ALTER USER`](/sql-statements/sql-statement-create-user.md). These methods are compatible with the authentication methods of MySQL with the same names. +TiDB supports multiple authentication methods. These methods can be specified on a per user basis using [`CREATE USER`](/sql-statements/sql-statement-create-user.md) and [`ALTER USER`](/sql-statements/sql-statement-alter-user.md). These methods are compatible with the authentication methods of MySQL with the same names. -You can use one of the following supported authentication methods in the table. To specify a default method that the server advertises when the client-server connection is being established, set the [`default_authentication_plugin`](/system-variables.md#default_authentication_plugin) variable. `tidb_sm3_password` is the SM3 authentication method only supported in TiDB. Therefore, to authenticate using this method, you must connect to TiDB using [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3). `tidb_auth_token` is a JSON Web Token (JWT) based authentication method used only in TiDB Cloud. +You can use one of the following supported authentication methods in the table. To specify a default method that the server advertises when the client-server connection is being established, set the [`default_authentication_plugin`](/system-variables.md#default_authentication_plugin) variable. `tidb_sm3_password` is the SM3 authentication method only supported in TiDB. Therefore, to authenticate using this method, you must connect to TiDB using [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3). `tidb_auth_token` is a JSON Web Token (JWT)-based authentication method used in TiDB Cloud, and you can also configure it for use in TiDB Self-Hosted. @@ -140,3 +140,122 @@ The support for TLS authentication is configured differently. For detailed infor | ed25519 (MariaDB) | No | | GSSAPI (MariaDB) | No | | FIDO | No | + +### `tidb_auth_token` + +`tidb_auth_token` is a passwordless authentication method based on [JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519). In v6.4.0, `tidb_auth_token` is only used for user authentication in TiDB Cloud. Starting from v6.5.0, you can also configure `tidb_auth_token` as a user authentication method for TiDB Self-Hosted. Different from password-based authentication methods such as `mysql_native_passsword` and `caching_sha2_password`, when you create users using `tidb_auth_token`, there is no need to set or store custom passwords. To log into TiDB, users only need to use a signed token instead of a password, which simplifies the authentication process and improves security. + +#### JWT + +JWT consists of three parts: Header, Payload, and Signature. After being encoded using base64, they are concatenated into a string separated by dots (`.`) for transmission between the client and server. + +The Header describes the metadata of the JWT, including 3 parameters: + +* `alg`: the algorithm for signature, which is `RS256` by default. +* `typ`: the type of token, which is `JWT`. +* `kid`: the key ID for generating token signature. + +Here is an example for Header: + +```json +{ + "alg": "RS256", + "kid": "the-key-id-0", + "typ": "JWT" +} +``` + +Payload is the main part of JWT, which stores the user information. Each field in the Payload is called a claim. The claims required for TiDB user authentication are as follows: + +* `iss`: if `TOKEN_ISSUER` is not specified or set to empty when [`CREATE USER`](/sql-statements/sql-statement-create-user.md), this claim is not required; otherwise, `iss` should use the same value as `TOKEN_ISSUER`. +* `sub`: this claim is required to be the same as the username to be authenticated. +* `iat`: it means `issued at`, the timestamp when the token is issued. In TiDB, this value must not be later than the authentication time or earlier than 15 minutes before authentication. +* `exp`: the timestamp when the token expires. If it is earlier than the time of authentication, the authentication fails. +* `email`: the email can be specified when creating a user by `ATTRIBUTE '{"email": "xxxx@pingcap.com"}`. If no email is specified when a user is created, this claim must be set as an empty string; otherwise, this claim must be the same as the specified value when the user is created. + +Here is an example for Payload: + +```json +{ + "email": "user@pingcap.com", + "exp": 1703305494, + "iat": 1703304594, + "iss": "issuer-abc", + "sub": "user@pingcap.com" +} +``` + +Signature is used to sign the Header and Payload data. + +> **Warning:** +> +> - The encoding of the Header and Payload in base64 is reversible. Do **Not** attach any sensitive information to them. +> - The `tidb_auth_token` authentication method requires clients to support the [`mysql_clear_password`](https://dev.mysql.com/doc/refman/8.0/en/cleartext-pluggable-authentication.html) plugin to send the token to TiDB in plain text. Therefore, you need to [enale TLS between clients and servers](/enable-tls-between-clients-and-servers.md) before using `tidb_auth_token`. + +#### Usage + +To configure and use `tidb_auth_token` as the authentication method for TiDB Self-Hosted users, take the following steps: + +1. Configure [`auth-token-jwks`](/tidb-configuration-file.md#auth-token-jwks-new-in-v640) and [`auth-token-refresh-interval`](/tidb-configuration-file.md#auth-token-refresh-interval-new-in-v640) in the TiDB configuration file. + + For example, you can get an example JWKS using the following command: + + ```bash + wget https://raw.githubusercontent.com/CbcWestwolf/generate_jwt/master/JWKS.json + ``` + + Then, configure the path of the example JWKS in `config.toml`: + + ```toml + [security] + auth-token-jwks = "JWKS.json" + ``` + +2. Start `tidb-server` and periodically update and save the JWKS to the path specified by `auth-token-jwks`. + +3. Create a user with `tidb_auth_token`, and specify `iss` and `email` as needed using `REQUIRE TOKEN_ISSUER` and `ATTRIBUTE '{"email": "xxxx@pingcap.com"}`. + + For example, create a user `user@pingcap.com` with `tidb_auth_token`: + + ```sql + CREATE USER 'user@pingcap.com' IDENTIFIED WITH 'tidb_auth_token' REQUIRE TOKEN_ISSUER 'issuer-abc' ATTRIBUTE '{"email": "user@pingcap.com"}'; + ``` + +4. Generate and sign a token for authentication, and authenticate using the `mysql_clear_text` plugin of the MySQL client. + + Install the JWT generation tool via `go install github.com/cbcwestwolf/generate_jwt` (this tool is only used for testing `tidb_auth_token`). For example: + + ```text + generate_jwt --kid "the-key-id-0" --sub "user@pingcap.com" --email "user@pingcap.com" --iss "issuer-abc" + ``` + + It prints the public key and token as follows: + + ```text + -----BEGIN PUBLIC KEY----- + MIIBCgKCAQEAq8G5n9XBidxmBMVJKLOBsmdOHrCqGf17y9+VUXingwDUZxRp2Xbu + LZLbJtLgcln1lC0L9BsogrWf7+pDhAzWovO6Ai4Aybu00tJ2u0g4j1aLiDdsy0gy + vSb5FBoL08jFIH7t/JzMt4JpF487AjzvITwZZcnsrB9a9sdn2E5B/aZmpDGi2+Is + f5osnlw0zvveTwiMo9ba416VIzjntAVEvqMFHK7vyHqXbfqUPAyhjLO+iee99Tg5 + AlGfjo1s6FjeML4xX7sAMGEy8FVBWNfpRU7ryTWoSn2adzyA/FVmtBvJNQBCMrrA + hXDTMJ5FNi8zHhvzyBKHU0kBTS1UNUbP9wIDAQAB + -----END PUBLIC KEY----- + + eyJhbGciOiJSUzI1NiIsImtpZCI6InRoZS1rZXktaWQtMCIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJAcGluZ2NhcC5jb20iLCJleHAiOjE3MDMzMDU0OTQsImlhdCI6MTcwMzMwNDU5NCwiaXNzIjoiaXNzdWVyLWFiYyIsInN1YiI6InVzZXJAcGluZ2NhcC5jb20ifQ.T4QPh2hTB5on5xCuvtWiZiDTuuKvckggNHtNaovm1F4RvwUv15GyOqj9yMstE-wSoV5eLEcPC2HgE6eN1C6yH_f4CU-A6n3dm9F1w-oLbjts7aYCl8OHycVYnq609fNnb8JLsQAmd1Zn9C0JW899-WSOQtvjLqVSPe9prH-cWaBVDQXzUJKxwywQzk9v-Z1Njt9H3Rn9vvwwJEEPI16VnaNK38I7YG-1LN4fAG9jZ6Zwvz7vb_s4TW7xccFf3dIhWTEwOQ5jDPCeYkwraRXU8NC6DPF_duSrYJc7d7Nu9Z2cr-E4i1Rt_IiRTuIIzzKlcQGg7jd9AGEfGe_SowsA-w + ``` + + Copy the preceding token in the last line for login: + + ```Shell + mycli -h 127.0.0.1 -P 4000 -u 'user@pingcap.com' -p '' + ``` + + Ensure that the MySQL client here supports the `mysql_clear_password` plugin. [mycli](https://www.mycli.net/) supports and enables this plugin by default. If you are using the [mysql command-line client](https://dev.mysql.com/doc/refman/8.0/en/mysql.html), you need to use the `--enable-cleartext-plugin` option to enable this plugin: + + ```Shell + mysql -h 127.0.0.1 -P 4000 -u 'user@pingcap.com' -p'' --enable-cleartext-plugin + ``` + + If an incorrect `--sub` is specified when the token is generated (such as `--sub "wronguser@pingcap.com"`), the authentication using this token would fail. + +You can encode and decode a token using the debugger provided by [jwt.io](https://jwt.io/). \ No newline at end of file diff --git a/sql-statements/sql-statement-alter-user.md b/sql-statements/sql-statement-alter-user.md index f4ff2a33454e1..3adddf1d8af80 100644 --- a/sql-statements/sql-statement-alter-user.md +++ b/sql-statements/sql-statement-alter-user.md @@ -20,6 +20,12 @@ UserSpecList ::= UserSpec ::= Username AuthOption +RequireClauseOpt ::= + ( 'REQUIRE' 'NONE' | 'REQUIRE' 'SSL' | 'REQUIRE' 'X509' | 'REQUIRE' RequireList )? + +RequireList ::= + ( "ISSUER" stringLit | "SUBJECT" stringLit | "CIPHER" stringLit | "SAN" stringLit | "TOKEN_ISSUER" stringLit )* + Username ::= StringName ('@' StringName | singleAtIdentifier)? | 'CURRENT_USER' OptionalBraces diff --git a/sql-statements/sql-statement-create-user.md b/sql-statements/sql-statement-create-user.md index 00345c11bf7a3..39ef112943a66 100644 --- a/sql-statements/sql-statement-create-user.md +++ b/sql-statements/sql-statement-create-user.md @@ -20,6 +20,12 @@ IfNotExists ::= UserSpecList ::= UserSpec ( ',' UserSpec )* +RequireClauseOpt ::= + ( 'REQUIRE' 'NONE' | 'REQUIRE' 'SSL' | 'REQUIRE' 'X509' | 'REQUIRE' RequireList )? + +RequireList ::= + ( "ISSUER" stringLit | "SUBJECT" stringLit | "CIPHER" stringLit | "SAN" stringLit | "TOKEN_ISSUER" stringLit )* + UserSpec ::= Username AuthOption diff --git a/system-variables.md b/system-variables.md index f27cb58b8f76e..01e26e42449c3 100644 --- a/system-variables.md +++ b/system-variables.md @@ -443,7 +443,6 @@ mysql> SELECT * FROM t1; - Type: Enumeration - Default value: `mysql_native_password` - Possible values: `mysql_native_password`, `caching_sha2_password`, `tidb_sm3_password`, `tidb_auth_token`, `authentication_ldap_sasl`, and `authentication_ldap_simple`. -- The `tidb_auth_token` authentication method is used only for the internal operation of TiDB Cloud. **DO NOT** set the variable to this value. - This variable sets the authentication method that the server advertises when the server-client connection is being established. - To authenticate using the `tidb_sm3_password` method, you can connect to TiDB using [TiDB-JDBC](https://github.com/pingcap/mysql-connector-j/tree/release/8.0-sm3). diff --git a/tidb-configuration-file.md b/tidb-configuration-file.md index 35ec304fd08a3..c2101b164902b 100644 --- a/tidb-configuration-file.md +++ b/tidb-configuration-file.md @@ -423,20 +423,12 @@ Configuration items related to security. ### `auth-token-jwks` New in v6.4.0 -> **Warning:** -> -> The `tidb_auth_token` authentication method is used only for the internal operation of TiDB Cloud. **DO NOT** change the value of this configuration. - -- Set the local file path of the JSON Web Key Sets (JWKS) for the `tidb_auth_token` authentication method. +- Set the local file path of the JSON Web Key Sets (JWKS) for the [`tidb_auth_token`](/security-compatibility-with-mysql.md#tidb_auth_token) authentication method. - Default value: `""` ### `auth-token-refresh-interval` New in v6.4.0 -> **Warning:** -> -> The `tidb_auth_token` authentication method is used only for the internal operation of TiDB Cloud. **DO NOT** change the value of this configuration. - -- Set the JWKS refresh interval for the `tidb_auth_token` authentication method. +- Set the JWKS refresh interval for the [`tidb_auth_token`](/security-compatibility-with-mysql.md#tidb_auth_token) authentication method. - Default value: `1h` ### `disconnect-on-expired-password` New in v6.5.0 From d63b23543254de01b3c9da0438da34d1b0f1b207 Mon Sep 17 00:00:00 2001 From: Aolin Date: Fri, 1 Mar 2024 10:08:04 +0800 Subject: [PATCH 17/82] *: add a restriction for smooth-upgrade-tidb (#16628) --- smooth-upgrade-tidb.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/smooth-upgrade-tidb.md b/smooth-upgrade-tidb.md index 3901bc018e8dd..c6fb1facc6559 100644 --- a/smooth-upgrade-tidb.md +++ b/smooth-upgrade-tidb.md @@ -75,7 +75,10 @@ When using the smooth upgrade feature, note the following limitations. ### Limitations on user operations -* Before the upgrade, if there is a canceling DDL job in the cluster, that is, an ongoing DDL job is being canceled by a user, because the job in the canceling state cannot be paused, TiDB will retry canceling the job. If the retry fails, an error is reported and the upgrade is exited. +* Before the upgrade, consider the following restrictions: + + * If there is a canceling DDL job in the cluster, that is, an ongoing DDL job is being canceled by a user, because the job in the canceling state cannot be paused, TiDB will retry canceling the job. If the retry fails, an error is reported and the upgrade is exited. + * If the TiDB Distributed eXecution Framework (DXF) is enabled, disable it by setting [`tidb_enable_dist_task`](/system-variables.md#tidb_enable_dist_task-new-in-v710) to `OFF` (its default value). Make sure that all ongoing distributed `ADD INDEX` and `IMPORT INTO` tasks are completed. Alternatively, you can cancel these tasks and wait until the upgrade is complete to restart them. Otherwise, the `ADD INDEX` operations during the upgrade might cause data index inconsistency. * In scenarios of using TiUP to upgrade TiDB, because TiUP upgrade has a timeout period, if the cluster has a large number of DDL jobs (more than 300) waiting in queues before the upgrade, the upgrade might fail. From bc26767d9c3e19d695ed1d06dc4c7dce5c23a349 Mon Sep 17 00:00:00 2001 From: Frank945946 <108602632+Frank945946@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:41:02 +0800 Subject: [PATCH 18/82] Update dumpling-overview.md (#16620) --- dumpling-overview.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dumpling-overview.md b/dumpling-overview.md index 61944d0c25edb..df2d02a47f7d8 100644 --- a/dumpling-overview.md +++ b/dumpling-overview.md @@ -404,6 +404,7 @@ SET GLOBAL tidb_gc_life_time = '10m'; | `--csv-separator` | Separator of each value in CSV files. It is not recommended to use the default ','. It is recommended to use '\|+\|' or other uncommon character combinations| ',' | ',' | | `--csv-null-value` | Representation of null values in CSV files | "\\N" | | `--csv-line-terminator` | The terminator at the end of a line for CSV files. When exporting data to a CSV file, you can specify the desired terminator with this option. This option supports "\\r\\n" and "\\n". The default value is "\\r\\n", which is consistent with the earlier versions. Because quotes in bash have different escaping rules, if you want to specify LF (linefeed) as a terminator, you can use a syntax similar to `--csv-line-terminator $'\n'`. | "\\r\\n" | +| `--csv-output-dialect` | Indicates that the source data can be exported to a CSV file in a specific required format for the database. The option value can be `""`, `"snowflake"`, `"redshift"`, or `"bigquery"`. The default value is `""`, which means to encode and export the source data according to UTF-8. If you set the option to `"snowflake"` or `"redshift"`, the binary data type in the source data will be converted to hexadecimal, but the `0x` prefix will be removed. For example, `0x61` will be represented as `61`. If you set the option to `"bigquery"`, the binary data type will be encoded using base64. In some cases, the binary strings might contain garbled characters. | `""` | | `--escape-backslash` | Use backslash (`\`) to escape special characters in the export file | true | | `--output-filename-template` | The filename templates represented in the format of [golang template](https://golang.org/pkg/text/template/#hdr-Arguments)
Support the `{{.DB}}`, `{{.Table}}`, and `{{.Index}}` arguments
The three arguments represent the database name, table name, and chunk ID of the data file | `{{.DB}}.{{.Table}}.{{.Index}}` | | `--status-addr` | Dumpling's service address, including the address for Prometheus to pull metrics and pprof debugging | ":8281" | From 6902ccc92417d7631ba3c00a675b271e7f58a147 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Fri, 1 Mar 2024 14:18:31 +0800 Subject: [PATCH 19/82] contribution guide: add EBNF preview and CustomContent instructions (#16610) --- CONTRIBUTING.md | 62 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 188dcbce0c819..3d9ccc98b1ad2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,14 +4,7 @@ Welcome to [TiDB](https://github.com/pingcap/tidb) documentation! We are excited ## What you can contribute -🚀 To provide you with better TiDB documentation, we sincerely invite you to participate in the [2024 TiDB Docs Dash](https://www.pingcap.com/event/tidb-docs-dash/). In this event, you'll have a chance to work with other members of the community while making a meaningful impact on [TiDB documentation](https://docs.pingcap.com/tidb/stable/) and [TiDB Cloud documentation](https://docs.pingcap.com/tidbcloud/). - -- **Dates/Time:** January 9 at 08:00 UTC ([your local time](https://www.timeanddate.com/worldclock/fixedtime.html?msg=TiDB+Docs+Dash+2024%3A+Start&iso=20240109T08&p1=1440)) – January 12 at 07:59 UTC ([your local time](https://www.timeanddate.com/worldclock/fixedtime.html?msg=TiDB+Docs+Dash+2024%3A+End&iso=20240112T0759&p1=1440)) -- **Event details**: -- **Issue list**: -- **Participation introduction**: - -In addition to the issues and tasks in the event, you can also start from any one of the following items to help improve [TiDB Docs at the PingCAP website](https://docs.pingcap.com/tidb/stable): +You can start from any one of the following items to help improve [TiDB documentation at the PingCAP website](https://docs.pingcap.com/tidb/stable): - Fix typos or format (punctuation, space, indentation, code block, etc.) - Fix or update inappropriate or outdated descriptions @@ -161,6 +154,59 @@ If your change fits one of the following situations, **CHOOSE THE AFFECTED RELEA - Fixes format to resolve a display error - Fixes broken links +## Guideline for contributing to TiDB Cloud documentation + +Currently, the [TiDB Cloud documentation](https://docs.pingcap.com/tidbcloud/) is available only in English, and it is stored in the [release-7.5](https://github.com/pingcap/docs/tree/release-7.5/tidb-cloud) branch of this repository for reusing SQL documents and development documents of TiDB v7.5. Hence, to create a pull request for TiDB Cloud documentation, make sure that your PR is based on the [release-7.5](https://github.com/pingcap/docs/tree/release-7.5) branch. + +> **Tip:** +> +> To learn which TiDB document is reused by TiDB Cloud, check the [TOC file of TiDB Cloud documentation](https://github.com/pingcap/docs/blob/release-7.5/TOC-tidb-cloud.md?plain=1). +> +> - If the path of a document in this file starts with `/tidb-cloud/`, it means that this document is only for TiDB Cloud. +> - If the path of a document in this file does not start with `/tidb-cloud/`, it means that this TiDB document is reused by TiDB Cloud. + +In some TiDB documents that are reused by TiDB Cloud, you might notice `CustomContent` tags. These `CustomContent` tags are used to show the dedicated content of TiDB or TiDB Cloud. + +For example: + +```Markdown +## Restrictions + + + +* The TiDB memory limit on the `INSERT INTO SELECT` statement can be adjusted using the system variable [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query). Starting from v6.5.0, it is not recommended to use [`txn-total-size-limit`](/tidb-configuration-file.md#txn-total-size-limit) to control transaction memory size. + + For more information, see [TiDB memory control](/configure-memory-usage.md). + + + + + +* The TiDB memory limit on the `INSERT INTO SELECT` statement can be adjusted using the system variable [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query). Starting from v6.5.0, it is not recommended to use [`txn-total-size-limit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#txn-total-size-limit) to control transaction memory size. + + For more information, see [TiDB memory control](https://docs.pingcap.com/tidb/stable/configure-memory-usage). + + + +* TiDB has no hard limit on the concurrency of the `INSERT INTO SELECT` statement, but it is recommended to consider the following practices: + + * When a "write transaction" is large, such as close to 1 GiB, it is recommended to control concurrency to no more than 10. + * When a "write transaction" is small, such as less than 100 MiB, it is recommended to control concurrency to no more than 30. + * Determine the concurrency based on testing results and specific circumstances. +``` + +In the example: + +- The content within the `` tag is only applicable to TiDB and will not be displayed on the [TiDB Cloud documentation](https://docs.pingcap.com/tidbcloud/) website. +- The content within the ``tag is only applicable to TiDB Cloud and will not be displayed on the [TiDB documentation](https://docs.pingcap.com/tidb/stable) website. +- The content that are not wrapped by `` tag are applicable to both TiDB and TiDB Cloud and will be displayed on both documentation websites. + +## Guideline for previewing EBNF diagrams + +[TiDB documentation](https://docs.pingcap.com/tidb/stable) provides a lot of SQL synopsis diagrams to help users understand the SQL syntax. For example, you can find the synopsis diagrams for the `ALTER INDEX` statement [here](https://docs.pingcap.com/tidb/stable/sql-statement-alter-index#synopsis). + +The source of these synopsis diagrams is written using [extended Backus–Naur form (EBNF)](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form). When preparing the EBNF code for a SQL statement, you can easily preview the EBNF diagram by copying the code to and clicking **Render**. + ## Contact Join [Discord](https://discord.gg/DQZ2dy3cuc?utm_source=doc) for discussion. From 312f207a92a62e2f6a97b8933b3ff735eacc4fb9 Mon Sep 17 00:00:00 2001 From: Yuqing Bai Date: Fri, 1 Mar 2024 14:23:02 +0800 Subject: [PATCH 20/82] Update limited-sql-features about serverless (#16204) --- sql-statements/sql-statement-create-table.md | 2 +- tidb-cloud/limited-sql-features.md | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/sql-statements/sql-statement-create-table.md b/sql-statements/sql-statement-create-table.md index b9651433d6b09..cc0106328bf86 100644 --- a/sql-statements/sql-statement-create-table.md +++ b/sql-statements/sql-statement-create-table.md @@ -133,7 +133,7 @@ The following *table_options* are supported. Other options such as `AVG_ROW_LENG | `AUTO_INCREMENT` | The initial value of the increment field | `AUTO_INCREMENT` = 5 | | [`SHARD_ROW_ID_BITS`](/shard-row-id-bits.md)| To set the number of bits for the implicit `_tidb_rowid` shards |`SHARD_ROW_ID_BITS` = 4| |`PRE_SPLIT_REGIONS`| To pre-split `2^(PRE_SPLIT_REGIONS)` Regions when creating a table |`PRE_SPLIT_REGIONS` = 4| -|`AUTO_ID_CACHE`| To set the auto ID cache size in a TiDB instance. By default, TiDB automatically changes this size according to allocation speed of auto ID |`AUTO_ID_CACHE` = 200. Note that this option is not available on [TiDB Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-serverless) clusters.| +|`AUTO_ID_CACHE`| To set the auto ID cache size in a TiDB instance. By default, TiDB automatically changes this size according to allocation speed of auto ID |`AUTO_ID_CACHE` = 200 | |`AUTO_RANDOM_BASE`| To set the initial incremental part value of auto_random. This option can be considered as a part of the internal interface. Users can ignore this parameter |`AUTO_RANDOM_BASE` = 0| | `CHARACTER SET` | To specify the [character set](/character-set-and-collation.md) for the table | `CHARACTER SET` = 'utf8mb4' | | `COMMENT` | The comment information | `COMMENT` = 'comment info' | diff --git a/tidb-cloud/limited-sql-features.md b/tidb-cloud/limited-sql-features.md index 3ec5f7402f443..e5b521bd3b427 100644 --- a/tidb-cloud/limited-sql-features.md +++ b/tidb-cloud/limited-sql-features.md @@ -60,7 +60,6 @@ TiDB Cloud works with almost all workloads that TiDB supports, but there are som | `SHOW PLUGINS` | Supported | Not supported [^8] | | `SHOW PUMP STATUS` | Not supported [^7] | Not supported [^7] | | `SHUTDOWN` | Not supported [^4] | Not supported [^4] | -| `CREATE TABLE ... AUTO_ID_CACHE` | Supported | Not supported [^12] | ## Functions and operators @@ -134,7 +133,7 @@ TiDB Cloud works with almost all workloads that TiDB supports, but there are som | `max_allowed_packet` | No limitation | Read-only [^11] | | `plugin_dir` | No limitation | Not supported [^8] | | `plugin_load` | No limitation | Not supported [^8] | -| `require_secure_transport` | Not supported [^13] | Read-only [^11] | +| `require_secure_transport` | Not supported [^12] | Read-only [^11] | | `skip_name_resolve` | No limitation | Read-only [^11] | | `sql_log_bin` | No limitation | Read-only [^11] | | `tidb_cdc_write_source` | No limitation | Read-only [^11] | @@ -246,6 +245,4 @@ TiDB Cloud works with almost all workloads that TiDB supports, but there are som [^11]: The variable is read-only on TiDB Serverless. -[^12]: Customizing cache size using [`AUTO_ID_CACHE`](/auto-increment.md#cache-size-control) is temporarily unavailable on TiDB Serverless. - -[^13]: Not supported. Enabling `require_secure_transport` for TiDB Dedicated clusters will result in SQL client connection failures. +[^12]: Not supported. Enabling `require_secure_transport` for TiDB Dedicated clusters will result in SQL client connection failures. From 5f3a210d15bf0cc87ec7b80cd9dcf0d9b2f677ad Mon Sep 17 00:00:00 2001 From: Aolin Date: Fri, 1 Mar 2024 17:45:31 +0800 Subject: [PATCH 21/82] ticdc: add ticdc_changefeed_failed alert rule (#16380) --- ticdc/ticdc-alert-rules.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/ticdc/ticdc-alert-rules.md b/ticdc/ticdc-alert-rules.md index 91c4c8c54870d..10e9f0235271a 100644 --- a/ticdc/ticdc-alert-rules.md +++ b/ticdc/ticdc-alert-rules.md @@ -16,7 +16,7 @@ For critical alerts, you need to pay close attention to abnormal monitoring metr - Alert rule: - (time() - ticdc_owner_checkpoint_ts / 1000) > 600 + `(time() - ticdc_owner_checkpoint_ts / 1000) > 600` - Description: @@ -24,13 +24,13 @@ For critical alerts, you need to pay close attention to abnormal monitoring metr - Solution: - See [TiCDC Handle Replication Interruption](/ticdc/troubleshoot-ticdc.md#how-do-i-handle-replication-interruptions). + See [TiCDC Handles Replication Interruption](/ticdc/troubleshoot-ticdc.md#how-do-i-handle-replication-interruptions). ### `cdc_resolvedts_high_delay` - Alert rule: - (time() - ticdc_owner_resolved_ts / 1000) > 300 + `(time() - ticdc_owner_resolved_ts / 1000) > 300` - Description: @@ -38,7 +38,21 @@ For critical alerts, you need to pay close attention to abnormal monitoring metr - Solution: - See [TiCDC Handle Replication Interruption](/ticdc/troubleshoot-ticdc.md#how-do-i-handle-replication-interruptions). + See [TiCDC Handles Replication Interruption](/ticdc/troubleshoot-ticdc.md#how-do-i-handle-replication-interruptions). + +### `ticdc_changefeed_failed` + +- Alert rule: + + `(max_over_time(ticdc_owner_status[1m]) == 2) > 0` + +- Description: + + A replication task encounters an unrecoverable error and enters the failed state. + +- Solution: + + This alert is similar to replication interruption. See [TiCDC Handles Replication Interruption](/ticdc/troubleshoot-ticdc.md#how-do-i-handle-replication-interruptions). ### `ticdc_processor_exit_with_error_count` @@ -52,7 +66,7 @@ For critical alerts, you need to pay close attention to abnormal monitoring metr - Solution: - See [TiCDC Handle Replication Interruption](/ticdc/troubleshoot-ticdc.md#how-do-i-handle-replication-interruptions). + See [TiCDC Handles Replication Interruption](/ticdc/troubleshoot-ticdc.md#how-do-i-handle-replication-interruptions). ## Warning alerts @@ -98,7 +112,7 @@ Warning alerts are a reminder for an issue or error. - Solution: - See [TiCDC Handle Replication Interruption](/ticdc/troubleshoot-ticdc.md#how-do-i-handle-replication-interruptions). + See [TiCDC Handles Replication Interruption](/ticdc/troubleshoot-ticdc.md#how-do-i-handle-replication-interruptions). ### `ticdc_puller_entry_sorter_sort_bucket` @@ -132,7 +146,7 @@ Warning alerts are a reminder for an issue or error. - Alert rule: - `changes(tikv_cdc_min_resolved_ts[1m]) < 1 and ON (instance) tikv_cdc_region_resolve_status{status="resolved"} > 0` + `changes(tikv_cdc_min_resolved_ts[1m]) < 1 and ON (instance) tikv_cdc_region_resolve_status{status="resolved"} > 0 and ON (instance) tikv_cdc_captured_region_total > 0` - Description: From 3a8a16824a232bf007b0ab2633ef0d1c0bd6ec8b Mon Sep 17 00:00:00 2001 From: xixirangrang Date: Mon, 4 Mar 2024 18:12:34 +0800 Subject: [PATCH 22/82] HAProxy: update the recommended hardware configuration for HAProxy (#16674) --- best-practices/haproxy-best-practices.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/best-practices/haproxy-best-practices.md b/best-practices/haproxy-best-practices.md index 1b476f29d05e8..061a2bdac305c 100644 --- a/best-practices/haproxy-best-practices.md +++ b/best-practices/haproxy-best-practices.md @@ -35,12 +35,12 @@ Before you deploy HAProxy, make sure that you meet the hardware and software req ### Hardware requirements -For your server, it is recommended to meet the following hardware requirements. You can also improve server specifications according to the load balancing environment. +According to the [HAProxy documentation](https://www.haproxy.com/documentation/haproxy-enterprise/getting-started/installation/linux/), the minimum hardware configuration for HAProxy is shown in the following table. Under the Sysbench `oltp_read_write` workload, the maximum QPS for this configuration is about 50K. You can increase the server configuration according to your load balancing environment. | Hardware resource | Minimum specification | | :--------------------- | :-------------------- | | CPU | 2 cores, 3.5 GHz | -| Memory | 16 GB | +| Memory | 4 GB | | Storage | 50 GB (SATA) | | Network Interface Card | 10G Network Card | From d65b2caeb9985d8a3bb76dbe5064ba30d9eae686 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Tue, 5 Mar 2024 12:30:34 +0800 Subject: [PATCH 23/82] use cluster_tidb_trx for lock troubleshooting (#16619) --- troubleshoot-lock-conflicts.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/troubleshoot-lock-conflicts.md b/troubleshoot-lock-conflicts.md index 7e6a978d0ca74..fc1399896168c 100644 --- a/troubleshoot-lock-conflicts.md +++ b/troubleshoot-lock-conflicts.md @@ -86,13 +86,14 @@ For example, to filter transactions with a long lock-waiting time using the `whe {{< copyable "sql" >}} ```sql -select trx.* from information_schema.data_lock_waits as l left join information_schema.tidb_trx as trx on l.trx_id = trx.id where l.key = "7480000000000000415F728000000000000001"\G +select trx.* from information_schema.data_lock_waits as l left join information_schema.cluster_tidb_trx as trx on l.trx_id = trx.id where l.key = "7480000000000000415F728000000000000001"\G ``` The following is an example output: ```sql *************************** 1. row *************************** + INSTANCE: 127.0.0.1:10080 ID: 426831815660273668 START_TIME: 2021-08-06 07:16:00.081000 CURRENT_SQL_DIGEST: 06da614b93e62713bd282d4685fc5b88d688337f36e88fe55871726ce0eb80d7 @@ -106,6 +107,7 @@ CURRENT_SQL_DIGEST_TEXT: update `t` set `v` = `v` + ? where `id` = ? ; DB: test ALL_SQL_DIGESTS: ["0fdc781f19da1c6078c9de7eadef8a307889c001e05f107847bee4cfc8f3cdf3","06da614b93e62713bd282d4685fc5b88d688337f36e88fe55871726ce0eb80d7"] *************************** 2. row *************************** + INSTANCE: 127.0.0.1:10080 ID: 426831818019569665 START_TIME: 2021-08-06 07:16:09.081000 CURRENT_SQL_DIGEST: 06da614b93e62713bd282d4685fc5b88d688337f36e88fe55871726ce0eb80d7 From 6554d9c44f5df2f396633d8809c113f377ff5753 Mon Sep 17 00:00:00 2001 From: Yasuo Honda Date: Tue, 5 Mar 2024 16:53:04 +0900 Subject: [PATCH 24/82] tidb: "PD server timeout" error message as lowercase (#16661) --- error-codes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/error-codes.md b/error-codes.md index 08252447127c5..1bba32e0a314b 100644 --- a/error-codes.md +++ b/error-codes.md @@ -532,7 +532,7 @@ TiDB is compatible with the error codes in MySQL, and in most cases returns the * Error Number: 9001 - The complete error message: `ERROR 9001 (HY000): PD Server Timeout` + The complete error message: `ERROR 9001 (HY000): PD server timeout` The PD request timed out. @@ -540,7 +540,7 @@ TiDB is compatible with the error codes in MySQL, and in most cases returns the * Error Number: 9002 - The complete error message: `ERROR 9002 (HY000): TiKV Server Timeout` + The complete error message: `ERROR 9002 (HY000): TiKV server timeout` The TiKV request timed out. From cc160ed6b37ffa6731d4ee678dcfcfa7400be136 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 6 Mar 2024 10:50:05 +0800 Subject: [PATCH 25/82] release notes: fix incorrect issue numbers (#16688) --- releases/release-5.2.4.md | 4 ++-- releases/release-5.3.1.md | 2 +- releases/release-5.3.2.md | 2 +- releases/release-5.4.1.md | 2 +- releases/release-5.4.3.md | 2 +- releases/release-6.0.0-dmr.md | 2 +- releases/release-6.1.0.md | 4 ++-- releases/release-6.2.0.md | 2 +- releases/release-6.5.2.md | 2 +- releases/release-6.5.5.md | 2 +- releases/release-6.5.6.md | 2 +- releases/release-6.5.8.md | 2 +- releases/release-6.6.0.md | 4 ++-- releases/release-7.1.2.md | 4 ++-- releases/release-7.1.3.md | 2 +- releases/release-7.2.0.md | 2 +- releases/release-7.4.0.md | 2 +- 17 files changed, 21 insertions(+), 21 deletions(-) diff --git a/releases/release-5.2.4.md b/releases/release-5.2.4.md index 039dd7944d8cb..4064c23c9a7fe 100644 --- a/releases/release-5.2.4.md +++ b/releases/release-5.2.4.md @@ -88,7 +88,7 @@ TiDB version: 5.2.4 - Fix the issue that the system variable `max_allowed_packet` does not take effect [#31422](https://github.com/pingcap/tidb/issues/31422) - Fix the issue that the `REPLACE` statement incorrectly changes other rows when the auto ID is out of range [#29483](https://github.com/pingcap/tidb/issues/29483) - Fix the issue that the slow query log cannot output log normally and might consume too much memory [#32656](https://github.com/pingcap/tidb/issues/32656) - - Fix the issue that the result of NATURAL JOIN might include unexpected columns [#24981](https://github.com/pingcap/tidb/issues/29481) + - Fix the issue that the result of NATURAL JOIN might include unexpected columns [#29481](https://github.com/pingcap/tidb/issues/29481) - Fix the issue that using `ORDER BY` and `LIMIT` together in one statement might output wrong results if a prefix-column index is used to query data [#29711](https://github.com/pingcap/tidb/issues/29711) - Fix the issue that the DOUBLE type auto-increment column might be changed when the optimistic transaction retries [#29892](https://github.com/pingcap/tidb/issues/29892) - Fix the issue that the STR_TO_DATE function cannot handle the preceding zero of the microsecond part correctly [#30078](https://github.com/pingcap/tidb/issues/30078) @@ -165,7 +165,7 @@ TiDB version: 5.2.4 + TiCDC - Fix the issue that default values cannot be replicated [#3793](https://github.com/pingcap/tiflow/issues/3793) - - Fix a bug that sequence is incorrectly replicated in some cases [#4563](https://github.com/pingcap/tiflow/issues/4552) + - Fix a bug that sequence is incorrectly replicated in some cases [#4552](https://github.com/pingcap/tiflow/issues/4552) - Fix a bug that a TiCDC node exits abnormally when a PD leader is killed [#4248](https://github.com/pingcap/tiflow/issues/4248) - Fix a bug that MySQL sink generates duplicated `replace` SQL statements when `batch-replace-enable` is disabled [#4501](https://github.com/pingcap/tiflow/issues/4501) - Fix the issue of panic and data inconsistency that occurs when outputting the default column value [#3929](https://github.com/pingcap/tiflow/issues/3929) diff --git a/releases/release-5.3.1.md b/releases/release-5.3.1.md index 09b3c1cf7b342..8f1a1da8e4974 100644 --- a/releases/release-5.3.1.md +++ b/releases/release-5.3.1.md @@ -20,7 +20,7 @@ TiDB version: 5.3.1 - TiDB - - Optimize the mapping logic of user login mode to make the logging more MySQL-compatible [#30450](https://github.com/pingcap/tidb/issues/32648) + - Optimize the mapping logic of user login mode to make the logging more MySQL-compatible [#32648](https://github.com/pingcap/tidb/issues/32648) - TiKV diff --git a/releases/release-5.3.2.md b/releases/release-5.3.2.md index bc1d7ce8aa835..2cfe4d3f85c8c 100644 --- a/releases/release-5.3.2.md +++ b/releases/release-5.3.2.md @@ -145,7 +145,7 @@ TiDB version: 5.3.2 - Fix the issue that TiCDC fails to start when the first PD set in `--pd` is not available after TLS is enabled [#4777](https://github.com/pingcap/tiflow/issues/4777) - Fix a bug that querying status through open API may be blocked when the PD node is abnormal [#4778](https://github.com/pingcap/tiflow/issues/4778) - Fix a stability problem in workerpool used by Unified Sorter [#4447](https://github.com/pingcap/tiflow/issues/4447) - - Fix a bug that sequence is incorrectly replicated in some cases [#4563](https://github.com/pingcap/tiflow/issues/4552) + - Fix a bug that sequence is incorrectly replicated in some cases [#4552](https://github.com/pingcap/tiflow/issues/4552) + TiDB Data Migration (DM) diff --git a/releases/release-5.4.1.md b/releases/release-5.4.1.md index 259be6362a7e5..6d14a10ccc17e 100644 --- a/releases/release-5.4.1.md +++ b/releases/release-5.4.1.md @@ -145,7 +145,7 @@ TiDB v5.4.1 does not introduce any compatibility changes in product design. But - Fix incorrect metrics caused by owner changes [#4774](https://github.com/pingcap/tiflow/issues/4774) - Fix the TiCDC panic issue that might occur because `Canal-JSON` does not support nil [#4736](https://github.com/pingcap/tiflow/issues/4736) - Fix a stability problem in workerpool used by Unified Sorter [#4447](https://github.com/pingcap/tiflow/issues/4447) - - Fix a bug that sequence is incorrectly replicated in some cases [#4563](https://github.com/pingcap/tiflow/issues/4552) + - Fix a bug that sequence is incorrectly replicated in some cases [#4552](https://github.com/pingcap/tiflow/issues/4552) - Fix the TiCDC panic issue that might occur when `Canal-JSON` incorrectly handles `string` [#4635](https://github.com/pingcap/tiflow/issues/4635) - Fix a bug that a TiCDC node exits abnormally when a PD leader is killed [#4248](https://github.com/pingcap/tiflow/issues/4248) - Fix a bug that MySQL sink generates duplicated `replace` SQL statements when `batch-replace-enable` is disabled [#4501](https://github.com/pingcap/tiflow/issues/4501) diff --git a/releases/release-5.4.3.md b/releases/release-5.4.3.md index e71ac559742f5..01dd37d348833 100644 --- a/releases/release-5.4.3.md +++ b/releases/release-5.4.3.md @@ -75,7 +75,7 @@ TiDB version: 5.4.3 + TiDB Lightning - - Fix the issue that an auto-increment column of the `BIGINT` type might be out of range [#27397](https://github.com/pingcap/tidb/issues/27937) + - Fix the issue that an auto-increment column of the `BIGINT` type might be out of range [#27937](https://github.com/pingcap/tidb/issues/27937) - Fix the issue that de-duplication might cause TiDB Lightning to panic in extreme cases [#34163](https://github.com/pingcap/tidb/issues/34163) - Fix the issue that TiDB Lightning does not support columns starting with slash, number, or non-ascii characters in Parquet files [#36980](https://github.com/pingcap/tidb/issues/36980) - Fix the issue that TiDB Lightning fails to connect to TiDB when TiDB uses an IPv6 host [#35880](https://github.com/pingcap/tidb/issues/35880) diff --git a/releases/release-6.0.0-dmr.md b/releases/release-6.0.0-dmr.md index 73198ae4f28a6..826bed2523789 100644 --- a/releases/release-6.0.0-dmr.md +++ b/releases/release-6.0.0-dmr.md @@ -764,7 +764,7 @@ TiDB v6.0.0 is a DMR, and its version is 6.0.0-DMR. - Fix a bug that a TiCDC node exits abnormally when a PD leader is killed [#4248](https://github.com/pingcap/tiflow/issues/4248) - Fix the error `Unknown system variable 'transaction_isolation'` for some MySQL versions [#4504](https://github.com/pingcap/tiflow/issues/4504) - Fix the TiCDC panic issue that might occur when `Canal-JSON` incorrectly handles `string` [#4635](https://github.com/pingcap/tiflow/issues/4635) - - Fix a bug that sequence is incorrectly replicated in some cases [#4563](https://github.com/pingcap/tiflow/issues/4552) + - Fix a bug that sequence is incorrectly replicated in some cases [#4552](https://github.com/pingcap/tiflow/issues/4552) - Fix the TiCDC panic issue that might occur because `Canal-JSON` does not support nil [#4736](https://github.com/pingcap/tiflow/issues/4736) - Fix the wrong data mapping for avro codec of type `Enum/Set` and `TinyText/MediumText/Text/LongText` [#4454](https://github.com/pingcap/tiflow/issues/4454) - Fix a bug that Avro converts a `NOT NULL` column to a nullable field [#4818](https://github.com/pingcap/tiflow/issues/4818) diff --git a/releases/release-6.1.0.md b/releases/release-6.1.0.md index 0ff55dd92562f..7f58ad1021752 100644 --- a/releases/release-6.1.0.md +++ b/releases/release-6.1.0.md @@ -418,7 +418,7 @@ In 6.1.0, the key new features or improvements are as follows: + TiDB Data Migration (DM) - - Fix the `start-time` time zone issue and change DM behavior from using the downstream time zone to using the upstream time zone [#5271](https://github.com/pingcap/tiflow/issues/5471) + - Fix the `start-time` time zone issue and change DM behavior from using the downstream time zone to using the upstream time zone [#5471](https://github.com/pingcap/tiflow/issues/5471) - Fix the issue that DM occupies more disk space after the task automatically resumes [#3734](https://github.com/pingcap/tiflow/issues/3734) [#5344](https://github.com/pingcap/tiflow/issues/5344) - Fix the problem that checkpoint flush may cause the data of failed rows to be skipped [#5279](https://github.com/pingcap/tiflow/issues/5279) - Fix the issue that in some cases manually executing the filtered DDL in the downstream might cause task resumption failure [#5272](https://github.com/pingcap/tiflow/issues/5272) @@ -434,5 +434,5 @@ In 6.1.0, the key new features or improvements are as follows: - Fix the issue that the precheck does not check local disk resources and cluster availability [#34213](https://github.com/pingcap/tidb/issues/34213) - Fix the issue of incorrect routing for schemas [#33381](https://github.com/pingcap/tidb/issues/33381) - Fix the issue that the PD configuration is not restored correctly when TiDB Lightning panics [#31733](https://github.com/pingcap/tidb/issues/31733) - - Fix the issue of Local-backend import failure caused by out-of-bounds data in the `auto_increment` column [#29737](https://github.com/pingcap/tidb/issues/27937) + - Fix the issue of Local-backend import failure caused by out-of-bounds data in the `auto_increment` column [#27937](https://github.com/pingcap/tidb/issues/27937) - Fix the issue of local backend import failure when the `auto_random` or `auto_increment` column is null [#34208](https://github.com/pingcap/tidb/issues/34208) diff --git a/releases/release-6.2.0.md b/releases/release-6.2.0.md index 73893616d5c4a..37ca32dd9c3f4 100644 --- a/releases/release-6.2.0.md +++ b/releases/release-6.2.0.md @@ -328,7 +328,7 @@ Since TiDB v6.2.0, backing up and restoring RawKV using BR is deprecated. - Support the `SHOW COUNT(*) WARNINGS` and `SHOW COUNT(*) ERRORS` statements [#25068](https://github.com/pingcap/tidb/issues/25068) @[likzn](https://github.com/likzn) - Add validation check for some system variables [#35048](https://github.com/pingcap/tidb/issues/35048) @[morgo](https://github.com/morgo) - - Optimize the error messages for some type conversions [#32447](https://github.com/pingcap/tidb/issues/32744) @[fanrenhoo](https://github.com/fanrenhoo) + - Optimize the error messages for some type conversions [#32744](https://github.com/pingcap/tidb/issues/32744) @[fanrenhoo](https://github.com/fanrenhoo) - The `KILL` command now supports DDL operations [#24144](https://github.com/pingcap/tidb/issues/24144) @[morgo](https://github.com/morgo) - Make the output of `SHOW TABLES/DATABASES LIKE …` more MySQL-compatible. The column names in the output contain the `LIKE` value [#35116](https://github.com/pingcap/tidb/issues/35116) @[likzn](https://github.com/likzn) - Improve the performance of JSON-related functions [#35859](https://github.com/pingcap/tidb/issues/35859) @[wjhuang2016](https://github.com/wjhuang2016) diff --git a/releases/release-6.5.2.md b/releases/release-6.5.2.md index 53a6eded2e74a..9bab3dacafb18 100644 --- a/releases/release-6.5.2.md +++ b/releases/release-6.5.2.md @@ -65,7 +65,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v6.5/quick-start-with- - Fix the issue that full index scans might cause errors when prepared plan cache is enabled [#42150](https://github.com/pingcap/tidb/issues/42150) @[fzzf678](https://github.com/fzzf678) - Fix the issue that IndexMerge might produce incorrect results when prepare plan cache is enabled [#41828](https://github.com/pingcap/tidb/issues/41828) @[qw4990](https://github.com/qw4990) - Fix the issue that the configuration of `max_prepared_stmt_count` does not take effect [#39735](https://github.com/pingcap/tidb/issues/39735) @[xuyifangreeneyes](https://github.com/xuyifangreeneyes) - - Fix the issue that IndexMerge might produce incorrect results when prepare plan cache is enabled [#41828](https://github.com/pingcap/tidb/issues/41828) @[qw4990](https://github.com/qw4990) @[XuHuaiyu](https://github.com/XuHuaiyu) + - Fix the issue that global memory control might incorrectly kill SQL statements with memory usage less than `tidb_server_memory_limit_sess_min_size` [#42662](https://github.com/pingcap/tidb/issues/42662) @[XuHuaiyu](https://github.com/XuHuaiyu) - Fix the issue that Index Join might cause panic in dynamic trimming mode of partition tables [#40596](https://github.com/pingcap/tidb/issues/40596) @[tiancaiamao](https://github.com/tiancaiamao) + TiKV diff --git a/releases/release-6.5.5.md b/releases/release-6.5.5.md index 35a7bef961e7e..16246a2af6c76 100644 --- a/releases/release-6.5.5.md +++ b/releases/release-6.5.5.md @@ -56,7 +56,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v6.5/quick-start-with- - Fix the issue that restoring implicit primary keys by PITR might lead to conflicts [#46520](https://github.com/pingcap/tidb/issues/46520) @[3pointer](https://github.com/3pointer) - Fix the issue that an error occurs when PITR recovers the meta-kv [#46578](https://github.com/pingcap/tidb/issues/46578) @[Leavrth](https://github.com/Leavrth) - - Fix an error in BR integration test cases [#45561](https://github.com/pingcap/tidb/issues/46561) @[purelind](https://github.com/purelind) + - Fix an error in BR integration test cases [#46561](https://github.com/pingcap/tidb/issues/46561) @[purelind](https://github.com/purelind) - Fix the issue that PITR fails to restore data from GCS [#47022](https://github.com/pingcap/tidb/issues/47022) @[Leavrth](https://github.com/Leavrth) + TiCDC diff --git a/releases/release-6.5.6.md b/releases/release-6.5.6.md index 560445846dc73..12913b3af00ed 100644 --- a/releases/release-6.5.6.md +++ b/releases/release-6.5.6.md @@ -141,7 +141,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v6.5/quick-start-with- - Fix the issue that the log backup might get stuck in some scenarios when backing up large wide tables [#15714](https://github.com/tikv/tikv/issues/15714) @[YuJuncen](https://github.com/YuJuncen) - Fix the issue that frequent flushes cause log backup to get stuck [#15602](https://github.com/tikv/tikv/issues/15602) @[3pointer](https://github.com/3pointer) - - Fix the issue that the retry after an EC2 metadata connection reset cause degraded backup and restore performance [#46750](https://github.com/pingcap/tidb/issues/47650) @[Leavrth](https://github.com/Leavrth) + - Fix the issue that the retry after an EC2 metadata connection reset cause degraded backup and restore performance [#47650](https://github.com/pingcap/tidb/issues/47650) @[Leavrth](https://github.com/Leavrth) - Fix the issue that running PITR multiple times within 1 minute might cause data loss [#15483](https://github.com/tikv/tikv/issues/15483) @[YuJuncen](https://github.com/YuJuncen) - Fix the issue that the default values for BR SQL commands and CLI are different, which might cause OOM issues [#48000](https://github.com/pingcap/tidb/issues/48000) @[YuJuncen](https://github.com/YuJuncen) - Fix the issue that log backup might panic when the PD owner is transferred [#47533](https://github.com/pingcap/tidb/issues/47533) @[YuJuncen](https://github.com/YuJuncen) diff --git a/releases/release-6.5.8.md b/releases/release-6.5.8.md index 9d9b74cb4557e..4724e94b804a1 100644 --- a/releases/release-6.5.8.md +++ b/releases/release-6.5.8.md @@ -39,7 +39,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v6.5/quick-start-with- - Fix the issue that histogram statistics might not be parsed into readable strings when the histogram boundary contains `NULL` [#49823](https://github.com/pingcap/tidb/issues/49823) @[AilinKid](https://github.com/AilinKid) - Fix the issue that hints cannot be used in `REPLACE INTO` statements [#34325](https://github.com/pingcap/tidb/issues/34325) @[YangKeao](https://github.com/YangKeao) - Fix the issue that query results are incorrect due to `STREAM_AGG()` incorrectly handling CI [#49902](https://github.com/pingcap/tidb/issues/49902) @[wshwsh12](https://github.com/wshwsh12) - - Fix the issue that the query result of a range partitioned table is incorrect in some cases due to wrong partition pruning [#50082](https://github.com/pingcap/tidb/issues/49823) @[Defined2014](https://github.com/Defined2014) + - Fix the issue that the query result of a range partitioned table is incorrect in some cases due to wrong partition pruning [#50082](https://github.com/pingcap/tidb/issues/50082) @[Defined2014](https://github.com/Defined2014) - Fix the issue that the auto-increment ID allocation reports an error due to concurrent conflicts when using an auto-increment column with `AUTO_ID_CACHE=1` [#50519](https://github.com/pingcap/tidb/issues/50519) @[tiancaiamao](https://github.com/tiancaiamao) - Mitigate the issue that TiDB nodes might encounter OOM errors when dealing with a large number of tables or partitions [#50077](https://github.com/pingcap/tidb/issues/50077) @[zimulala](https://github.com/zimulala) - Fix the issue that data is inconsistent under the TiDB Distributed eXecution Framework (DXF) when executing `ADD INDEX` after the DDL Owner is network isolated [#49773](https://github.com/pingcap/tidb/issues/49773) @[tangenta](https://github.com/tangenta) diff --git a/releases/release-6.6.0.md b/releases/release-6.6.0.md index 8a48bd5586cb8..3791470727703 100644 --- a/releases/release-6.6.0.md +++ b/releases/release-6.6.0.md @@ -168,7 +168,7 @@ In v6.6.0-DMR, the key new features and improvements are as follows: For more information, see [documentation](/placement-rules-in-sql.md#specify-survival-preferences). -* Support rolling back DDL operations via the `FLASHBACK CLUSTER TO TIMESTAMP` statement [#14088](https://github.com/tikv/tikv/pull/14088) @[Defined2014](https://github.com/Defined2014) @[JmPotato](https://github.com/JmPotato) +* Support rolling back DDL operations via the `FLASHBACK CLUSTER TO TIMESTAMP` statement [#14045](https://github.com/tikv/tikv/issues/14045) @[Defined2014](https://github.com/Defined2014) @[JmPotato](https://github.com/JmPotato) The [`FLASHBACK CLUSTER TO TIMESTAMP`](/sql-statements/sql-statement-flashback-cluster.md) statement supports restoring the entire cluster to a specified point in time within the Garbage Collection (GC) lifetime. In TiDB v6.6.0, this feature adds support for rolling back DDL operations. This can be used to quickly undo a DML or DDL misoperation on a cluster, roll back a cluster within minutes, and roll back a cluster multiple times on the timeline to determine when specific data changes occurred. @@ -318,7 +318,7 @@ In v6.6.0-DMR, the key new features and improvements are as follows: For more information, see [documentation](/enable-tls-between-components.md). -* TiDB Lightning supports accessing Amazon S3 data via AWS IAM role keys and session tokens [#4075](https://github.com/pingcap/tidb/issues/40750) @[okJiang](https://github.com/okJiang) +* TiDB Lightning supports accessing Amazon S3 data via AWS IAM role keys and session tokens [#40750](https://github.com/pingcap/tidb/issues/40750) @[okJiang](https://github.com/okJiang) Before v6.6.0, TiDB Lightning only supports accessing S3 data via AWS IAM **user's access keys** (each access key consists of an access key ID and a secret access key) so you cannot use a temporary session token to access S3 data. Starting from v6.6.0, TiDB Lightning supports accessing S3 data via AWS IAM **role's access keys + session tokens** as well to improve the data security. diff --git a/releases/release-7.1.2.md b/releases/release-7.1.2.md index 755ddda1d6e0d..02d3ba937f0f8 100644 --- a/releases/release-7.1.2.md +++ b/releases/release-7.1.2.md @@ -104,7 +104,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.1/quick-start-with- - Fix the issue that inserting data into a partitioned table might fail after exchanging partitions between the partition table and a table with placement policies [#45791](https://github.com/pingcap/tidb/issues/45791) @[mjonss](https://github.com/mjonss) - Fix the issue of encoding time fields with incorrect timezone information [#46033](https://github.com/pingcap/tidb/issues/46033) @[tangenta](https://github.com/tangenta) - Fix the issue that DDL statements that fast add indexes would get stuck when the `tmp` directory does not exist [#45456](https://github.com/pingcap/tidb/issues/45456) @[tangenta](https://github.com/tangenta) - - Fix the issue that upgrading multiple TiDB instances simultaneously might block the upgrade process [#46288](https://github.com/pingcap/tidb/issues/46228) @[zimulala](https://github.com/zimulala) + - Fix the issue that upgrading multiple TiDB instances simultaneously might block the upgrade process [#46228](https://github.com/pingcap/tidb/issues/46228) @[zimulala](https://github.com/zimulala) - Fix the issue of uneven Region scattering caused by incorrect parameters used in splitting Regions [#46135](https://github.com/pingcap/tidb/issues/46135) @[zimulala](https://github.com/zimulala) - Fix the issue that DDL operations might get stuck after TiDB is restarted [#46751](https://github.com/pingcap/tidb/issues/46751) @[wjhuang2016](https://github.com/wjhuang2016) - Prohibit split table operations on non-integer clustered indexes [#47350](https://github.com/pingcap/tidb/issues/47350) @[tangenta](https://github.com/tangenta) @@ -165,7 +165,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.1/quick-start-with- - Fix the issue that PITR fails to recover data from GCS [#47022](https://github.com/pingcap/tidb/issues/47022) @[Leavrth](https://github.com/Leavrth) - Fix the potential error in fine-grained backup phase in RawKV mode [#37085](https://github.com/pingcap/tidb/issues/37085) @[pingyu](https://github.com/pingyu) - Fix the issue that recovering meta-kv using PITR might cause errors [#46578](https://github.com/pingcap/tidb/issues/46578) @[Leavrth](https://github.com/Leavrth) - - Fix the errors in BR integration test cases [#45561](https://github.com/pingcap/tidb/issues/46561) @[purelind](https://github.com/purelind) + - Fix the errors in BR integration test cases [#46561](https://github.com/pingcap/tidb/issues/46561) @[purelind](https://github.com/purelind) - Fix the issue of restore failures by increasing the default values of the global parameters `TableColumnCountLimit` and `IndexLimit` used by BR to their maximum values [#45793](https://github.com/pingcap/tidb/issues/45793) @[Leavrth](https://github.com/Leavrth) - Fix the issue that the br CLI client gets stuck when scanning restored data [#45476](https://github.com/pingcap/tidb/issues/45476) @[3pointer](https://github.com/3pointer) - Fix the issue that PITR might skip restoring the `CREATE INDEX` DDL statement [#47482](https://github.com/pingcap/tidb/issues/47482) @[Leavrth](https://github.com/Leavrth) diff --git a/releases/release-7.1.3.md b/releases/release-7.1.3.md index 9f89eb7361901..e76716decfff2 100644 --- a/releases/release-7.1.3.md +++ b/releases/release-7.1.3.md @@ -135,7 +135,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.1/quick-start-with- - Fix the issue that the default values for BR SQL commands and CLI are different, which might cause OOM issues [#48000](https://github.com/pingcap/tidb/issues/48000) @[YuJuncen](https://github.com/YuJuncen) - Fix the issue that the log backup might get stuck in some scenarios when backing up large wide tables [#15714](https://github.com/tikv/tikv/issues/15714) @[YuJuncen](https://github.com/YuJuncen) - Fix the issue that BR generates incorrect URIs for external storage files [#48452](https://github.com/pingcap/tidb/issues/48452) @[3AceShowHand](https://github.com/3AceShowHand) - - Fix the issue that the retry after an EC2 metadata connection reset causes degraded backup and restore performance [#46750](https://github.com/pingcap/tidb/issues/47650) @[Leavrth](https://github.com/Leavrth) + - Fix the issue that the retry after an EC2 metadata connection reset causes degraded backup and restore performance [#47650](https://github.com/pingcap/tidb/issues/47650) @[Leavrth](https://github.com/Leavrth) - Fix the issue that the log backup task can start but does not work properly if failing to connect to PD during task initialization [#16056](https://github.com/tikv/tikv/issues/16056) @[YuJuncen](https://github.com/YuJuncen) + TiCDC diff --git a/releases/release-7.2.0.md b/releases/release-7.2.0.md index b41bb0363ca23..ea85bb347a999 100644 --- a/releases/release-7.2.0.md +++ b/releases/release-7.2.0.md @@ -245,7 +245,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.2/quick-start-with- + TiDB Lightning - - Optimize the retry mechanism during import to avoid errors caused by leader switching [#44478](https://github.com/pingcap/tidb/pull/44478) @[lance6716](https://github.com/lance6716) + - Optimize the retry mechanism during import to avoid errors caused by leader switching [#44263](https://github.com/pingcap/tidb/issues/44263) @[lance6716](https://github.com/lance6716) - Verify checksum through SQL after the import to improve stability of verification [#41941](https://github.com/pingcap/tidb/issues/41941) @[GMHDBJD](https://github.com/GMHDBJD) - Optimize TiDB Lightning OOM issues when importing wide tables [#43853](https://github.com/pingcap/tidb/issues/43853) @[D3Hunter](https://github.com/D3Hunter) diff --git a/releases/release-7.4.0.md b/releases/release-7.4.0.md index 269e71620ff3c..cfe015548dcdc 100644 --- a/releases/release-7.4.0.md +++ b/releases/release-7.4.0.md @@ -447,7 +447,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.4/quick-start-with- - Fix an issue that the misleading error message `resolve lock timeout` covers up the actual error when backup fails [#43236](https://github.com/pingcap/tidb/issues/43236) @[YuJuncen](https://github.com/YuJuncen) - Fix the issue that recovering implicit primary keys using PITR might cause conflicts [#46520](https://github.com/pingcap/tidb/issues/46520) @[3pointer](https://github.com/3pointer) - Fix the issue that recovering meta-kv using PITR might cause errors [#46578](https://github.com/pingcap/tidb/issues/46578) @[Leavrth](https://github.com/Leavrth) - - Fix the errors in BR integration test cases [#45561](https://github.com/pingcap/tidb/issues/46561) @[purelind](https://github.com/purelind) + - Fix the errors in BR integration test cases [#46561](https://github.com/pingcap/tidb/issues/46561) @[purelind](https://github.com/purelind) + TiCDC From bbbec7519341fcd87ab256cd790358cad72b0abe Mon Sep 17 00:00:00 2001 From: joey-yez <104608045+joey-yez@users.noreply.github.com> Date: Thu, 7 Mar 2024 10:14:05 +0800 Subject: [PATCH 26/82] add function pushdown list (#16697) --- functions-and-operators/expressions-pushed-down.md | 2 +- tiflash/tiflash-supported-pushdown-calculations.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/functions-and-operators/expressions-pushed-down.md b/functions-and-operators/expressions-pushed-down.md index e114bfc300856..0d6f0a388cf3f 100644 --- a/functions-and-operators/expressions-pushed-down.md +++ b/functions-and-operators/expressions-pushed-down.md @@ -21,7 +21,7 @@ TiFlash also supports pushdown for the functions and operators [listed on this p | [Control flow functions](/functions-and-operators/control-flow-functions.md) | [CASE](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#operator_case), [IF()](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_if), [IFNULL()](https://dev.mysql.com/doc/refman/8.0/en/flow-control-functions.html#function_ifnull) | | [JSON functions](/functions-and-operators/json-functions.md) | [JSON_ARRAY([val[, val] ...])](https://dev.mysql.com/doc/refman/8.0/en/json-creation-functions.html#function_json-array),
[JSON_CONTAINS(target, candidate[, path])](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-contains),
[JSON_EXTRACT(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-extract),
[JSON_INSERT(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-insert),
[JSON_LENGTH(json_doc[, path])](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-length),
[JSON_MERGE(json_doc, json_doc[, json_doc] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-merge),
[JSON_OBJECT([key, val[, key, val] ...])](https://dev.mysql.com/doc/refman/8.0/en/json-creation-functions.html#function_json-object),
[JSON_REMOVE(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-remove),
[JSON_REPLACE(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-replace),
[JSON_SET(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-set),
[JSON_TYPE(json_val)](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-type),
[JSON_UNQUOTE(json_val)](https://dev.mysql.com/doc/refman/8.0/en/json-modification-functions.html#function_json-unquote),
[JSON_VALID(val)](https://dev.mysql.com/doc/refman/8.0/en/json-attribute-functions.html#function_json-valid),
[value MEMBER OF(json_array)](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#operator_member-of) | | [Date and time functions](/functions-and-operators/date-and-time-functions.md) | [DATE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date), [DATE_FORMAT()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format), [DATEDIFF()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_datediff), [DAYOFMONTH()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofmonth), [DAYOFWEEK()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofweek), [DAYOFYEAR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofyear), [FROM_DAYS()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_from-days), [HOUR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_hour), [MAKEDATE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_makedate), [MAKETIME()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_maketime), [MICROSECOND()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_microsecond), [MINUTE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_minute), [MONTH()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_month), [MONTHNAME()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_monthname), [PERIOD_ADD()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_period-add), [PERIOD_DIFF()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_period-diff), [SEC_TO_TIME()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_sec-to-time), [SECOND()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_second), [SYSDATE()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_sysdate), [TIME_TO_SEC()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_time-to-sec), [TIMEDIFF()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_timediff), [WEEK()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_week), [WEEKOFYEAR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_weekofyear), [YEAR()](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_year) | -| [String functions](/functions-and-operators/string-functions.md) | [ASCII()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ascii), [BIT_LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_bit-length), [CHAR()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_char), [CHAR_LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_char-length), [CONCAT()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_concat), [CONCAT_WS()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_concat-ws), [ELT()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_elt), [FIELD()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_field), [HEX()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_hex), [LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_length), [LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like), [LOWER()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_lower), [LTRIM()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ltrim), [MID()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_mid), [NOT LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_not-like), [NOT REGEXP](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_not-regexp), [REGEXP](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp), [REPLACE()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_replace), [REVERSE()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_reverse), [RIGHT()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_right), [RTRIM()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_rtrim), [SPACE()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_space), [STRCMP()](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#function_strcmp), [SUBSTR()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_substr), [SUBSTRING()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_substring), [UPPER()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_upper) | +| [String functions](/functions-and-operators/string-functions.md) | [ASCII()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ascii), [BIT_LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_bit-length), [CHAR()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_char), [CHAR_LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_char-length), [CONCAT()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_concat), [CONCAT_WS()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_concat-ws), [ELT()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_elt), [FIELD()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_field), [HEX()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_hex), [LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_length), [LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_like), [LOWER()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_lower), [LTRIM()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_ltrim), [MID()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_mid), [NOT LIKE](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#operator_not-like), [NOT REGEXP](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_not-regexp), [REGEXP](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp), [REGEXP_INSTR()](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-instr), [REGEXP_LIKE()](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-like), [REGEXP_REPLACE()](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-replace), [REGEXP_SUBSTR()](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#function_regexp-substr), [REPLACE()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_replace), [REVERSE()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_reverse), [RIGHT()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_right), [RLIKE](https://dev.mysql.com/doc/refman/8.0/en/regexp.html#operator_regexp), [RTRIM()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_rtrim), [SPACE()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_space), [STRCMP()](https://dev.mysql.com/doc/refman/8.0/en/string-comparison-functions.html#function_strcmp), [SUBSTR()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_substr), [SUBSTRING()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_substring), [UPPER()](https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_upper) | | [Aggregation functions](/functions-and-operators/aggregate-group-by-functions.md#aggregate-group-by-functions) | [COUNT()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count), [COUNT(DISTINCT)](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_count-distinct), [SUM()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_sum), [AVG()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_avg), [MAX()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_max), [MIN()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_min), [VARIANCE()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_variance), [VAR_POP()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_var-pop), [STD()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_std), [STDDEV()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev), [STDDEV_POP](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev-pop), [VAR_SAMP()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_var-samp), [STDDEV_SAMP()](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_stddev-samp), [JSON_ARRAYAGG(key)](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_json-arrayagg), [JSON_OBJECTAGG(key, value)](https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_json-objectagg) | | [Encryption and compression functions](/functions-and-operators/encryption-and-compression-functions.md#encryption-and-compression-functions) | [MD5()](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_md5), [SHA1(), SHA()](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_sha1), [UNCOMPRESSED_LENGTH()](https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_uncompressed-length) | | [Cast functions and operators](/functions-and-operators/cast-functions-and-operators.md#cast-functions-and-operators) | [CAST()](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_cast), [CONVERT()](https://dev.mysql.com/doc/refman/8.0/en/cast-functions.html#function_convert) | diff --git a/tiflash/tiflash-supported-pushdown-calculations.md b/tiflash/tiflash-supported-pushdown-calculations.md index e24b6967e2b2b..0374ccdd64ca2 100644 --- a/tiflash/tiflash-supported-pushdown-calculations.md +++ b/tiflash/tiflash-supported-pushdown-calculations.md @@ -39,7 +39,7 @@ TiFlash supports the following push-down expressions: | [Logical functions](/functions-and-operators/control-flow-functions.md) and [operators](/functions-and-operators/operators.md) | `AND`, `OR`, `NOT`, `CASE WHEN`, `IF()`, `IFNULL()`, `ISNULL()`, `IN`, `LIKE`, `ILIKE`, `COALESCE`, `IS` | | [Bitwise operations](/functions-and-operators/bit-functions-and-operators.md) | `&` (bitand), \| (bitor), `~` (bitneg), `^` (bitxor) | | [String functions](/functions-and-operators/string-functions.md) | `SUBSTR()`, `CHAR_LENGTH()`, `REPLACE()`, `CONCAT()`, `CONCAT_WS()`, `LEFT()`, `RIGHT()`, `ASCII()`, `LENGTH()`, `TRIM()`, `LTRIM()`, `RTRIM()`, `POSITION()`, `FORMAT()`, `LOWER()`, `UCASE()`, `UPPER()`, `SUBSTRING_INDEX()`, `LPAD()`, `RPAD()`, `STRCMP()` | -| [Regular expression functions and operators](/functions-and-operators/string-functions.md) | `REGEXP`, `REGEXP_LIKE()`, `REGEXP_INSTR()`, `REGEXP_SUBSTR()`, `REGEXP_REPLACE()` | +| [Regular expression functions and operators](/functions-and-operators/string-functions.md) | `REGEXP`, `REGEXP_LIKE()`, `REGEXP_INSTR()`, `REGEXP_SUBSTR()`, `REGEXP_REPLACE()`, `RLIKE` | | [Date functions](/functions-and-operators/date-and-time-functions.md) | `DATE_FORMAT()`, `TIMESTAMPDIFF()`, `FROM_UNIXTIME()`, `UNIX_TIMESTAMP(int)`, `UNIX_TIMESTAMP(decimal)`, `STR_TO_DATE(date)`, `STR_TO_DATE(datetime)`, `DATEDIFF()`, `YEAR()`, `MONTH()`, `DAY()`, `EXTRACT(datetime)`, `DATE()`, `HOUR()`, `MICROSECOND()`, `MINUTE()`, `SECOND()`, `SYSDATE()`, `DATE_ADD/ADDDATE(datetime, int)`, `DATE_ADD/ADDDATE(string, int/real)`, `DATE_SUB/SUBDATE(datetime, int)`, `DATE_SUB/SUBDATE(string, int/real)`, `QUARTER()`, `DAYNAME()`, `DAYOFMONTH()`, `DAYOFWEEK()`, `DAYOFYEAR()`, `LAST_DAY()`, `MONTHNAME()`, `TO_SECONDS()`, `TO_DAYS()`, `FROM_DAYS()`, `WEEKOFYEAR()` | | [JSON function](/functions-and-operators/json-functions.md) | `JSON_LENGTH()`, `->`, `->>`, `JSON_EXTRACT()`, `JSON_ARRAY()`, `JSON_DEPTH()`, `JSON_VALID()`, `JSON_KEYS()`, `JSON_CONTAINS_PATH()`, `JSON_UNQUOTE()` | | [Conversion functions](/functions-and-operators/cast-functions-and-operators.md) | `CAST(int AS DOUBLE), CAST(int AS DECIMAL)`, `CAST(int AS STRING)`, `CAST(int AS TIME)`, `CAST(double AS INT)`, `CAST(double AS DECIMAL)`, `CAST(double AS STRING)`, `CAST(double AS TIME)`, `CAST(string AS INT)`, `CAST(string AS DOUBLE), CAST(string AS DECIMAL)`, `CAST(string AS TIME)`, `CAST(decimal AS INT)`, `CAST(decimal AS STRING)`, `CAST(decimal AS TIME)`, `CAST(time AS INT)`, `CAST(time AS DECIMAL)`, `CAST(time AS STRING)`, `CAST(time AS REAL)`, `CAST(json AS JSON)`, `CAST(json AS STRING)`, `CAST(int AS JSON)`, `CAST(real AS JSON)`, `CAST(decimal AS JSON)`, `CAST(string AS JSON)`, `CAST(time AS JSON)`, `CAST(duration AS JSON)` | From f2f39bd26c161734ac7eb3035c1424da74f8b9c5 Mon Sep 17 00:00:00 2001 From: hongyunyan <649330952@qq.com> Date: Fri, 8 Mar 2024 08:59:06 +0800 Subject: [PATCH 27/82] cdc: Remove useless code in filter (#16190) --- ticdc/ticdc-open-api-v2.md | 58 -------------------------------------- 1 file changed, 58 deletions(-) diff --git a/ticdc/ticdc-open-api-v2.md b/ticdc/ticdc-open-api-v2.md index b464167b45be4..bdc1b4f41e57e 100644 --- a/ticdc/ticdc-open-api-v2.md +++ b/ticdc/ticdc-open-api-v2.md @@ -158,15 +158,6 @@ This interface is used to submit a replication task to TiCDC. If the request is "enable_old_value": true, "enable_sync_point": true, "filter": { - "do_dbs": [ - "string" - ], - "do_tables": [ - { - "database_name": "string", - "table_name": "string" - } - ], "event_filters": [ { "ignore_delete_value_expr": "string", @@ -184,15 +175,6 @@ This interface is used to submit a replication task to TiCDC. If the request is ] } ], - "ignore_dbs": [ - "string" - ], - "ignore_tables": [ - { - "database_name": "string", - "table_name": "string" - } - ], "ignore_txn_start_ts": [ 0 ], @@ -297,10 +279,6 @@ The `filter` parameters are described as follows: | Parameter name | Description | |:-----------------|:---------------------------------------| -| `do_dbs` | `STRING ARRAY` type. The databases to be replicated. (Optional) | -| `do_tables` | The tables to be replicated. (Optional) | -| `ignore_dbs` | `STRING ARRAY` type. The databases to be ignored. (Optional) | -| `ignore_tables` | The tables to be ignored. (Optional) | | `event_filters` | The configuration to filter events. (Optional) | | `ignore_txn_start_ts` | `UINT64 ARRAY` type. Specifying this will ignore transactions that specify `start_ts`, such as `[1, 2]`. (Optional) | | `rules` | `STRING ARRAY` type. The rules for table schema filtering, such as `['foo*.*', 'bar*.*']`. For more information, see [Table Filter](/table-filter.md). (Optional) | @@ -412,15 +390,6 @@ If the request is successful, `200 OK` is returned. If the request fails, an err "enable_old_value": true, "enable_sync_point": true, "filter": { - "do_dbs": [ - "string" - ], - "do_tables": [ - { - "database_name": "string", - "table_name": "string" - } - ], "event_filters": [ { "ignore_delete_value_expr": "string", @@ -438,15 +407,6 @@ If the request is successful, `200 OK` is returned. If the request fails, an err ] } ], - "ignore_dbs": [ - "string" - ], - "ignore_tables": [ - { - "database_name": "string", - "table_name": "string" - } - ], "ignore_txn_start_ts": [ 0 ], @@ -616,15 +576,6 @@ To modify the changefeed configuration, follow the steps of `pause the replicati "enable_old_value": true, "enable_sync_point": true, "filter": { - "do_dbs": [ - "string" - ], - "do_tables": [ - { - "database_name": "string", - "table_name": "string" - } - ], "event_filters": [ { "ignore_delete_value_expr": "string", @@ -642,15 +593,6 @@ To modify the changefeed configuration, follow the steps of `pause the replicati ] } ], - "ignore_dbs": [ - "string" - ], - "ignore_tables": [ - { - "database_name": "string", - "table_name": "string" - } - ], "ignore_txn_start_ts": [ 0 ], From c87b412f4d8303616b6ab2c44a2d9504bcfe5608 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Mon, 11 Mar 2024 11:08:08 +0800 Subject: [PATCH 28/82] include description about extending timeout of TiUP when force-init-stats is ON (#16707) --- upgrade-tidb-using-tiup.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/upgrade-tidb-using-tiup.md b/upgrade-tidb-using-tiup.md index 9b0ce992c17e7..7bdb7fbce7205 100644 --- a/upgrade-tidb-using-tiup.md +++ b/upgrade-tidb-using-tiup.md @@ -26,6 +26,31 @@ This document is targeted for the following upgrade paths: > - If your cluster to be upgraded is v3.1 or an earlier version (v3.0 or v2.1), the direct upgrade to v7.6.0 is not supported. You need to upgrade your cluster first to v4.0 and then to v7.6.0. > - If your cluster to be upgraded is earlier than v6.2, the upgrade might get stuck when you upgrade the cluster to v6.2 or later versions in some scenarios. You can refer to [How to fix the issue](#how-to-fix-the-issue-that-the-upgrade-gets-stuck-when-upgrading-to-v620-or-later-versions). > - TiDB nodes use the value of the [`server-version`](/tidb-configuration-file.md#server-version) configuration item to verify the current TiDB version. Therefore, to avoid unexpected behaviors, before upgrading the TiDB cluster, you need to set the value of `server-version` to empty or the real version of the current TiDB cluster. +> - Setting the [`performance.force-init-stats`](/tidb-configuration-file.md#force-init-stats-new-in-v657-and-v710) configuration item to `ON` prolongs the TiDB startup time, which might cause startup timeouts and upgrade failures. To avoid this issue, it is recommended to set a longer waiting timeout for TiUP. +> - Scenarios that might be affected: +> - The original cluster version is earlier than v6.5.7 and v7.1.0 (which does not support `performance.force-init-stats` yet), and the target version is v7.2.0 or later. +> - The original cluster version is equal to or later than v6.5.7 and v7.1.0, and the `performance.force-init-stats` configuration item is set to `ON`. +> +> - Check the value of the `performance.force-init-stats` configuration item: +> +> ``` +> SHOW CONFIG WHERE type = 'tidb' AND name = 'performance.force-init-stats'; +> ``` +> +> - You can increase the TiUP waiting timeout by adding the command-line option [`--wait-timeout`](/tiup/tiup-component-cluster.md#--wait-timeout). For example, execute the following command to set the waiting timeout to 1200 seconds (20 minutes). +> +> ```shell +> tiup update cluster --wait-timeout 1200 [other options] +> ``` +> +> Generally, a 20-minute waiting timeout is sufficient for most scenarios. For a more precise estimate, search for `init stats info time` in the TiDB log to get the statistics loading time during the previous startup as a reference. For example: +> +> ``` +> [domain.go:2271] ["init stats info time"] [lite=true] ["take time"=2.151333ms] +> ``` +> +> If the original cluster is v7.1.0 or earlier, when upgrading to v7.2.0 or later, because of the introduction of [`performance.lite-init-stats`](/tidb-configuration-file.md#lite-init-stats-new-in-v710), the statistics loading time is greatly reduced. In this case, the `init stats info time` before the upgrade is longer than the loading time after the upgrade. +> - If you want to shorten the rolling upgrade duration of TiDB and the potential performance impact of missing initial statistical information during the upgrade is acceptable for your cluster, you can set `performance.force-init-stats` to `OFF` before the upgrade by [modifying the configuration of the target instance with TiUP](/maintain-tidb-using-tiup.md#modify-the-configuration). After the upgrade is completed, you can reassess and revert this setting if necessary. ## Upgrade caveat From 14ddfd0769644a4b576b12809063a60398d1af12 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Mon, 11 Mar 2024 12:00:39 +0800 Subject: [PATCH 29/82] v7.1.4: tikv configuration doc: add gc thread number (#16671) (#16711) --- releases/release-7.6.0.md | 2 +- tikv-configuration-file.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/release-7.6.0.md b/releases/release-7.6.0.md index 62499af3452a4..0cac1432d7e3f 100644 --- a/releases/release-7.6.0.md +++ b/releases/release-7.6.0.md @@ -284,7 +284,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.6/quick-start-with- | TiKV | [`blob-file-compression`](/tikv-configuration-file.md#blob-file-compression) | Modified | The algorithm used for compressing values in Titan, which takes value as the unit. Starting from TiDB v7.6.0, the default compression algorithm is `zstd`. | | TiKV | [`rocksdb.defaultcf.titan.min-blob-size`](/tikv-configuration-file.md#min-blob-size) | Modified | Starting from TiDB v7.6.0, the default value for new clusters is `32KB`. For existing clusters upgrading to v7.6.0, the default value `1KB` remains unchanged. | | TiKV | [`rocksdb.titan.enabled`](/tikv-configuration-file.md#enabled) | Modified | Enables or disables Titan. For v7.5.0 and earlier versions, the default value is `false`. Starting from v7.6.0, the default value is `true` for only new clusters. Existing clusters upgraded to v7.6.0 or later versions will retain the original configuration. | -| TiKV | [`gc.num-threads`](/tikv-configuration-file.md#num-threads-new-in-v658-v751-and-v760) | Newly added | When `enable-compaction-filter` is set to `false`, this parameter controls the number of GC threads. The default value is `1`. | +| TiKV | [`gc.num-threads`](/tikv-configuration-file.md#num-threads-new-in-v658-v714-v751-and-v760) | Newly added | When `enable-compaction-filter` is set to `false`, this parameter controls the number of GC threads. The default value is `1`. | | TiKV | [`raftstore.periodic-full-compact-start-times`](/tikv-configuration-file.md#periodic-full-compact-start-times-new-in-v760) | Newly added | Sets the specific times that TiKV initiates periodic full compaction. The default value `[]` means periodic full compaction is disabled. | | TiKV | [`raftstore.periodic-full-compact-start-max-cpu`](/tikv-configuration-file.md#periodic-full-compact-start-max-cpu-new-in-v760) | Newly added | Limits the maximum CPU usage rate for TiKV periodic full compaction. The default value is `0.1`. | | TiKV | [`zstd-dict-size`](/tikv-configuration-file.md#zstd-dict-size) | Newly added | Specifies the `zstd` dictionary compression size. The default value is `"0KB"`, which means to disable the `zstd` dictionary compression. | diff --git a/tikv-configuration-file.md b/tikv-configuration-file.md index 4707e3b5caa4e..85dd3e89bfa87 100644 --- a/tikv-configuration-file.md +++ b/tikv-configuration-file.md @@ -2066,7 +2066,7 @@ Configuration items related to TiDB Lightning import and BR restore. + The garbage ratio threshold to trigger GC. + Default value: `1.1` -### `num-threads` New in v6.5.8, v7.5.1, and v7.6.0 +### `num-threads` New in v6.5.8, v7.1.4, v7.5.1, and v7.6.0 + The number of GC threads when `enable-compaction-filter` is `false`. + Default value: `1` From b944c67fd264e27bef6409a5f226aaad0dd53519 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Mon, 11 Mar 2024 15:36:37 +0800 Subject: [PATCH 30/82] add release notes for v7.1.4 (#16683) --- TOC.md | 1 + releases/release-7.1.4.md | 184 +++++++++++++++++++++++++++++++++++ releases/release-notes.md | 1 + releases/release-timeline.md | 1 + 4 files changed, 187 insertions(+) create mode 100644 releases/release-7.1.4.md diff --git a/TOC.md b/TOC.md index ea68b1097f752..416cf6c99bba4 100644 --- a/TOC.md +++ b/TOC.md @@ -1044,6 +1044,7 @@ - v7.2 - [7.2.0-DMR](/releases/release-7.2.0.md) - v7.1 + - [7.1.4](/releases/release-7.1.4.md) - [7.1.3](/releases/release-7.1.3.md) - [7.1.2](/releases/release-7.1.2.md) - [7.1.1](/releases/release-7.1.1.md) diff --git a/releases/release-7.1.4.md b/releases/release-7.1.4.md new file mode 100644 index 0000000000000..1189244d47691 --- /dev/null +++ b/releases/release-7.1.4.md @@ -0,0 +1,184 @@ +--- +title: TiDB 7.1.4 Release Notes +summary: Learn about the compatibility changes, improvements, and bug fixes in TiDB 7.1.4. +--- + +# TiDB 7.1.4 Release Notes + +Release date: March 11, 2024 + +TiDB version: 7.1.4 + +Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.1/quick-start-with-tidb) | [Production deployment](https://docs.pingcap.com/tidb/v7.1/production-deployment-using-tiup) | [Installation packages](https://www.pingcap.com/download/?version=v7.1.4#version-list) + +## Compatibility changes + +- To reduce the overhead of log printing, TiFlash changes the default value of `logger.level` from `"debug"` to `"info"` [#8641](https://github.com/pingcap/tiflash/issues/8641) @[JaySon-Huang](https://github.com/JaySon-Huang) +- Introduce the TiKV configuration item [`gc.num-threads`](https://docs.pingcap.com/tidb/v6.5/tikv-configuration-file#num-threads-new-in-v658) to set the number of GC threads when `enable-compaction-filter` is `false` [#16101](https://github.com/tikv/tikv/issues/16101) @[tonyxuqqi](https://github.com/tonyxuqqi) + +## Improvements + ++ TiDB + + - Enhance the ability to convert `OUTER JOIN` to `INNER JOIN` in specific scenarios [#49616](https://github.com/pingcap/tidb/issues/49616) @[qw4990](https://github.com/qw4990) + - When `force-init-stats` is set to `true`, TiDB waits for statistics initialization to finish before providing services during TiDB startup. This setting no longer blocks the startup of HTTP servers, which enables users to continue monitoring [#50854](https://github.com/pingcap/tidb/issues/50854) @[hawkingrei](https://github.com/hawkingrei) + ++ TiKV + + - When TiKV detects the existence of corrupted SST files, it logs the specific reasons for the corruption [#16308](https://github.com/tikv/tikv/issues/16308) @[overvenus](https://github.com/overvenus) + ++ PD + + - Improve the speed of PD automatically updating cluster status when the backup cluster is disconnected [#6883](https://github.com/tikv/pd/issues/6883) @[disksing](https://github.com/disksing) + ++ TiFlash + + - Reduce the impact of background GC tasks on read and write task latency [#8650](https://github.com/pingcap/tiflash/issues/8650) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Reduce the impact of disk performance jitter on read latency [#8583](https://github.com/pingcap/tiflash/issues/8583) @[JaySon-Huang](https://github.com/JaySon-Huang) + ++ Tools + + + Backup & Restore (BR) + + - Support creating databases in batch during data restore [#50767](https://github.com/pingcap/tidb/issues/50767) @[Leavrth](https://github.com/Leavrth) + - Improve the table creation performance of the `RESTORE` statement in scenarios with large datasets [#48301](https://github.com/pingcap/tidb/issues/48301) @[Leavrth](https://github.com/Leavrth) + - Improve the speed of merging SST files during data restore by using a more efficient algorithm [#50613](https://github.com/pingcap/tidb/issues/50613) @[Leavrth](https://github.com/Leavrth) + - Support ingesting SST files in batch during data restore [#16267](https://github.com/tikv/tikv/issues/16267) @[3pointer](https://github.com/3pointer) + - Print the information of the slowest Region that affects global checkpoint advancement in logs and metrics during log backups [#51046](https://github.com/pingcap/tidb/issues/51046) @[YuJuncen](https://github.com/YuJuncen) + - Remove an outdated compatibility check when using Google Cloud Storage (GCS) as the external storage [#50533](https://github.com/pingcap/tidb/issues/50533) @[lance6716](https://github.com/lance6716) + - Implement a lock mechanism to avoid executing multiple log backup truncation tasks (`br log truncate`) simultaneously [#49414](https://github.com/pingcap/tidb/issues/49414) @[YuJuncen](https://github.com/YuJuncen) + + + TiCDC + + - When the downstream is Kafka, the topic expression allows `schema` to be optional and supports specifying a topic name directly [#9763](https://github.com/pingcap/tiflow/issues/9763) @[3AceShowHand](https://github.com/3AceShowHand) + - Support [querying the downstream synchronization status of a changefeed](https://docs.pingcap.com/tidb/v7.1/ticdc-open-api-v2#query-whether-a-specific-replication-task-is-completed), which helps you determine whether the upstream data changes received by TiCDC have been synchronized to the downstream system completely [#10289](https://github.com/pingcap/tiflow/issues/10289) @[hongyunyan](https://github.com/hongyunyan) + - Support searching TiCDC logs in the TiDB Dashboard [#10263](https://github.com/pingcap/tiflow/issues/10263) @[CharlesCheung96](https://github.com/CharlesCheung96) + + + TiDB Lightning + + - Improve the performance in scenarios where multiple tables are imported by removing the lock operation when executing `ALTER TABLE` [#50105](https://github.com/pingcap/tidb/issues/50105) @[D3Hunter](https://github.com/D3Hunter) + +## Bug fixes + ++ TiDB + + - Fix the issue that the `DELETE` and `UPDATE` statements using index lookup might report an error when `tidb_multi_statement_mode` mode is enabled [#50012](https://github.com/pingcap/tidb/issues/50012) @[tangenta](https://github.com/tangenta) + - Fix the issue that CTE queries might report an error `type assertion for CTEStorageMap failed` during the retry process [#46522](https://github.com/pingcap/tidb/issues/46522) @[tiancaiamao](https://github.com/tiancaiamao) + - Fix the issue of excessive statistical error in constructing statistics caused by Golang's implicit conversion algorithm [#49801](https://github.com/pingcap/tidb/issues/49801) @[qw4990](https://github.com/qw4990) + - Fix the issue that errors might be returned during the concurrent merging of global statistics for partitioned tables [#48713](https://github.com/pingcap/tidb/issues/48713) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue of wrong query results due to TiDB incorrectly eliminating constant values in `group by` [#38756](https://github.com/pingcap/tidb/issues/38756) @[hi-rustin](https://github.com/hi-rustin) + - Fix the issue that `BIT` type columns might cause query errors due to decode failures when they are involved in calculations of some functions [#49566](https://github.com/pingcap/tidb/issues/49566) [#50850](https://github.com/pingcap/tidb/issues/50850) [#50855](https://github.com/pingcap/tidb/issues/50855) @[jiyfhust](https://github.com/jiyfhust) + - Fix the issue that `LIMIT` in multi-level nested `UNION` queries might become ineffective [#49874](https://github.com/pingcap/tidb/issues/49874) @[Defined2014](https://github.com/Defined2014) + - Fix the issue that the auto-increment ID allocation reports an error due to concurrent conflicts when using an auto-increment column with `AUTO_ID_CACHE=1` [#50519](https://github.com/pingcap/tidb/issues/50519) @[tiancaiamao](https://github.com/tiancaiamao) + - Fix the `Column ... in from clause is ambiguous` error that might occur when a query uses `NATURAL JOIN` [#32044](https://github.com/pingcap/tidb/issues/32044) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that enforced sorting might become ineffective when a query uses optimizer hints (such as `STREAM_AGG()`) that enforce sorting and its execution plan contains `IndexMerge` [#49605](https://github.com/pingcap/tidb/issues/49605) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that query results are incorrect due to `STREAM_AGG()` incorrectly handling CI [#49902](https://github.com/pingcap/tidb/issues/49902) @[wshwsh12](https://github.com/wshwsh12) + - Fix the goroutine leak issue that might occur when the `HashJoin` operator fails to spill to disk [#50841](https://github.com/pingcap/tidb/issues/50841) @[wshwsh12](https://github.com/wshwsh12) + - Fix the issue that hints cannot be used in `REPLACE INTO` statements [#34325](https://github.com/pingcap/tidb/issues/34325) @[YangKeao](https://github.com/YangKeao) + - Fix the issue that executing queries containing the `GROUP_CONCAT(ORDER BY)` syntax might return errors [#49986](https://github.com/pingcap/tidb/issues/49986) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that using a multi-valued index to access an empty JSON array might return incorrect results [#50125](https://github.com/pingcap/tidb/issues/50125) @[YangKeao](https://github.com/YangKeao) + - Fix the goroutine leak issue that occurs when the memory usage of CTE queries exceeds limits [#50337](https://github.com/pingcap/tidb/issues/50337) @[guo-shaoge](https://github.com/guo-shaoge) + - Fix the issue that using old interfaces might cause inconsistent metadata for tables [#49751](https://github.com/pingcap/tidb/issues/49751) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that executing `UNIQUE` index lookup with an `ORDER BY` clause might cause an error [#49920](https://github.com/pingcap/tidb/issues/49920) @[jackysp](https://github.com/jackysp) + - Fix the issue that common hints do not take effect in `UNION ALL` statements [#50068](https://github.com/pingcap/tidb/issues/50068) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that a query containing the IndexHashJoin operator gets stuck when memory exceeds `tidb_mem_quota_query` [#49033](https://github.com/pingcap/tidb/issues/49033) @[XuHuaiyu](https://github.com/XuHuaiyu) + - Fix the issue that `UPDATE` or `DELETE` statements containing `WITH RECURSIVE` CTEs might produce incorrect results [#48969](https://github.com/pingcap/tidb/issues/48969) @[winoros](https://github.com/winoros) + - Fix the issue that histogram statistics might not be parsed into readable strings when the histogram boundary contains `NULL` [#49823](https://github.com/pingcap/tidb/issues/49823) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that TiDB might panic when a query contains the Apply operator and the `fatal error: concurrent map writes` error occurs [#50347](https://github.com/pingcap/tidb/issues/50347) @[SeaRise](https://github.com/SeaRise) + - Fix the `Can't find column ...` error that might occur when aggregate functions are used for group calculations [#50926](https://github.com/pingcap/tidb/issues/50926) @[qw4990](https://github.com/qw4990) + - Fix the issue that TiDB returns wrong query results when processing `ENUM` or `SET` types by constant propagation [#49440](https://github.com/pingcap/tidb/issues/49440) @[winoros](https://github.com/winoros) + - Fix the issue that the completion times of two DDL tasks with dependencies are incorrectly sequenced [#49498](https://github.com/pingcap/tidb/issues/49498) @[tangenta](https://github.com/tangenta) + - Fix the issue that TiDB might panic when using the `EXECUTE` statement to execute `PREPARE STMT` after the `tidb_enable_prepared_plan_cache` system variable is enabled and then disabled [#49344](https://github.com/pingcap/tidb/issues/49344) @[qw4990](https://github.com/qw4990) + - Fix the issue that `LIMIT` and `OPRDERBY` might be invalid in nested `UNION` queries [#49377](https://github.com/pingcap/tidb/issues/49377) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that the `LEADING` hint does not take effect in `UNION ALL` statements [#50067](https://github.com/pingcap/tidb/issues/50067) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that the `COMMIT` or `ROLLBACK` operation executed through `COM_STMT_EXECUTE` fails to terminate transactions that have timed out [#49151](https://github.com/pingcap/tidb/issues/49151) @[zyguan](https://github.com/zyguan) + - Fix the issue that illegal optimizer hints might cause valid hints to be ineffective [#49308](https://github.com/pingcap/tidb/issues/49308) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that Daylight Saving Time is displayed incorrectly in some time zones [#49586](https://github.com/pingcap/tidb/issues/49586) @[overvenus](https://github.com/overvenus) + - Fix the issue that executing `SELECT INTO OUTFILE` using the `PREPARE` method incorrectly returns a success message instead of an error [#49166](https://github.com/pingcap/tidb/issues/49166) @[qw4990](https://github.com/qw4990) + - Fix the issue that TiDB might panic when performing a rolling upgrade using `tiup cluster upgrade/start` due to an interaction issue with PD [#50152](https://github.com/pingcap/tidb/issues/50152) @[zimulala](https://github.com/zimulala) + - Fix the issue that the expected optimization does not take effect when adding an index to an empty table [#49682](https://github.com/pingcap/tidb/issues/49682) @[zimulala](https://github.com/zimulala) + - Fix the issue that TiDB might OOM when a large number of tables or partitions are created [#50077](https://github.com/pingcap/tidb/issues/50077) @[zimulala](https://github.com/zimulala) + - Fix the issue that adding an index might cause inconsistent index data when the network is unstable [#49773](https://github.com/pingcap/tidb/issues/49773) @[tangenta](https://github.com/tangenta) + - Fix the execution order of DDL jobs to prevent TiCDC from receiving out-of-order DDLs [#49498](https://github.com/pingcap/tidb/issues/49498) @[tangenta](https://github.com/tangenta) + - Fix the issue that the `tidb_gogc_tuner_threshold` system variable is not adjusted accordingly after the `tidb_server_memory_limit` variable is modified [#48180](https://github.com/pingcap/tidb/issues/48180) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that the query result of a range partitioned table is incorrect in some cases due to wrong partition pruning [#50082](https://github.com/pingcap/tidb/issues/50082) @[Defined2014](https://github.com/Defined2014) + - Fix the issue that DDL operations such as renaming tables are stuck when the `CREATE TABLE` statement contains specific partitions or constraints [#50972](https://github.com/pingcap/tidb/issues/50972) @[lcwangchao](https://github.com/lcwangchao) + - Fix the issue that getting the default value of a column returns an error if the column default value is dropped [#50043](https://github.com/pingcap/tidb/issues/50043) [#51324](https://github.com/pingcap/tidb/issues/51324) @[crazycs520](https://github.com/crazycs520) + - Fix the issue that the monitoring metric `tidb_statistics_auto_analyze_total` on Grafana is not displayed as an integer [#51051](https://github.com/pingcap/tidb/issues/51051) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that the `tidb_merge_partition_stats_concurrency` variable does not take effect when `auto analyze` is processing partitioned tables [#47594](https://github.com/pingcap/tidb/issues/47594) @[hawkingrei](https://github.com/hawkingrei) + - Fix the issue that the `index out of range` error might occur when a query involves JOIN operations [#42588](https://github.com/pingcap/tidb/issues/42588) @[AilinKid](https://github.com/AilinKid) + - Fix the issue that wrong results might be returned when TiFlash late materialization processes associated columns [#49241](https://github.com/pingcap/tidb/issues/49241) [#51204](https://github.com/pingcap/tidb/issues/51204) @[Lloyd-Pottiger](https://github.com/Lloyd-Pottiger) + ++ TiKV + + - Fix the issue that hibernated Regions are not promptly awakened in exceptional circumstances [#16368](https://github.com/tikv/tikv/issues/16368) @[LykxSassinator](https://github.com/LykxSassinator) + - Fix the issue that the entire Region becomes unavailable when one replica is offline, by checking the last heartbeat time of all replicas of the Region before taking a node offline [#16465](https://github.com/tikv/tikv/issues/16465) @[tonyxuqqi](https://github.com/tonyxuqqi) + - Fix the issue that table properties stored in RocksDB might be inaccurate when Titan is enabled [#16319](https://github.com/tikv/tikv/issues/16319) @[hicqu](https://github.com/hicqu) + - Fix the issue that executing `tikv-ctl compact-cluster` fails when a cluster has TiFlash nodes [#16189](https://github.com/tikv/tikv/issues/16189) @[frew](https://github.com/frew) + - Fix the issue that TiKV might panic when gRPC threads are checking `is_shutdown` [#16236](https://github.com/tikv/tikv/issues/16236) @[pingyu](https://github.com/pingyu) + - Fix the issue that TiDB and TiKV might produce inconsistent results when processing `DECIMAL` arithmetic multiplication truncation [#16268](https://github.com/tikv/tikv/issues/16268) @[solotzg](https://github.com/solotzg) + - Fix the issue that `cast_duration_as_time` might return incorrect results [#16211](https://github.com/tikv/tikv/issues/16211) @[gengliqi](https://github.com/gengliqi) + - Fix the issue that TiKV converts the time zone incorrectly for Brazil and Egypt [#16220](https://github.com/tikv/tikv/issues/16220) @[overvenus](https://github.com/overvenus) + - Fix the issue that JSON integers greater than the maximum `INT64` value but less than the maximum `UINT64` value are parsed as `FLOAT64` by TiKV, resulting in inconsistency with TiDB [#16512](https://github.com/tikv/tikv/issues/16512) @[YangKeao](https://github.com/YangKeao) + ++ PD + + - Fix the issue that slots are not fully deleted in a resource group client, which causes the number of the allocated tokens to be less than the specified value [#7346](https://github.com/tikv/pd/issues/7346) @[guo-shaoge](https://github.com/guo-shaoge) + - Fix the issue that some TSO logs do not print the error cause [#7496](https://github.com/tikv/pd/issues/7496) @[CabinfeverB](https://github.com/CabinfeverB) + - Fix the issue that the default resource group accumulates unnecessary tokens when `BURSTABLE` is enabled [#7206](https://github.com/tikv/pd/issues/7206) @[CabinfeverB](https://github.com/CabinfeverB) + - Fix the issue that there is no output when the `evict-leader-scheduler` interface is called [#7672](https://github.com/tikv/pd/issues/7672) @[CabinfeverB](https://github.com/CabinfeverB) + - Fix the memory leak issue that occurs when `watch etcd` is not turned off correctly [#7807](https://github.com/tikv/pd/issues/7807) @[rleungx](https://github.com/rleungx) + - Fix the issue that data race occurs when the `MergeLabels` function is called [#7535](https://github.com/tikv/pd/issues/7535) @[lhy1024](https://github.com/lhy1024) + - Fix the issue that TiDB Dashboard fails to get the TiKV profile when TLS is enabled [#7561](https://github.com/tikv/pd/issues/7561) @[Connor1996](https://github.com/Connor1996) + - Fix the issue that the orphan peer is deleted when the number of replicas does not meet the requirements [#7584](https://github.com/tikv/pd/issues/7584) @[bufferflies](https://github.com/bufferflies) + - Fix the issue that `available_stores` is calculated incorrectly for clusters adopting the Data Replication Auto Synchronous (DR Auto-Sync) mode [#7221](https://github.com/tikv/pd/issues/7221) @[disksing](https://github.com/disksing) + - Fix the issue that `canSync` and `hasMajority` might be calculated incorrectly for clusters adopting the Data Replication Auto Synchronous (DR Auto-Sync) mode when the configuration of Placement Rules is complex [#7201](https://github.com/tikv/pd/issues/7201) @[disksing](https://github.com/disksing) + - Fix the issue that the primary AZ cannot add TiKV nodes when the secondary AZ is down for clusters adopting the Data Replication Auto Synchronous (DR Auto-Sync) mode [#7218](https://github.com/tikv/pd/issues/7218) @[disksing](https://github.com/disksing) + - Fix the issue that querying resource groups in batch might cause PD to panic [#7206](https://github.com/tikv/pd/issues/7206) @[nolouch](https://github.com/nolouch) + - Fix the issue that querying a Region without a leader using `pd-ctl` might cause PD to panic [#7630](https://github.com/tikv/pd/issues/7630) @[rleungx](https://github.com/rleungx) + - Fix the issue that the PD monitoring item `learner-peer-count` does not synchronize the old value after a leader switch [#7728](https://github.com/tikv/pd/issues/7728) @[CabinfeverB](https://github.com/CabinfeverB) + - Fix the issue that PD cannot read resource limitations when it is started with `systemd` [#7628](https://github.com/tikv/pd/issues/7628) @[bufferflies](https://github.com/bufferflies) + ++ TiFlash + + - Fix the issue that TiFlash might panic due to unstable network connections with PD during replica migration [#8323](https://github.com/pingcap/tiflash/issues/8323) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix the issue that TiFlash incorrectly handles `ENUM` when the `ENUM` value is 0 [#8311](https://github.com/pingcap/tiflash/issues/8311) @[solotzg](https://github.com/solotzg) + - Fix the random invalid memory access issue that might occur with `GREATEST` or `LEAST` functions containing constant string parameters [#8604](https://github.com/pingcap/tiflash/issues/8604) @[windtalker](https://github.com/windtalker) + - Fix the issue that the `lowerUTF8` and `upperUTF8` functions do not allow characters in different cases to occupy different bytes [#8484](https://github.com/pingcap/tiflash/issues/8484) @[gengliqi](https://github.com/gengliqi) + - Fix the issue that short queries executed successfully print excessive info logs [#8592](https://github.com/pingcap/tiflash/issues/8592) @[windtalker](https://github.com/windtalker) + - Fix the issue that the memory usage increases significantly due to slow queries [#8564](https://github.com/pingcap/tiflash/issues/8564) @[JinheLin](https://github.com/JinheLin) + - Fix the issue that TiFlash panics after executing `ALTER TABLE ... MODIFY COLUMN ... NOT NULL`, which changes nullable columns to non-nullable [#8419](https://github.com/pingcap/tiflash/issues/8419) @[JaySon-Huang](https://github.com/JaySon-Huang) + - Fix the issue that after terminating a query, TiFlash crashes due to concurrent data conflicts when a large number of tasks on TiFlash are canceled at the same time [#7432](https://github.com/pingcap/tiflash/issues/7432) @[SeaRise](https://github.com/SeaRise) + - Fix the issue that TiFlash might crash during remote reads [#8685](https://github.com/pingcap/tiflash/issues/8685) @[zanmato1984](https://github.com/zanmato1984) + - Fix the issue that TiFlash Anti Semi Join might return incorrect results when the join includes non-equivalent conditions [#8791](https://github.com/pingcap/tiflash/issues/8791) @[windtalker](https://github.com/windtalker) + ++ Tools + + + Backup & Restore (BR) + + - Fix the issue that stopping a log backup task causes TiDB to crash [#50839](https://github.com/pingcap/tidb/issues/50839) @[YuJuncen](https://github.com/YuJuncen) + - Fix the issue that data restore is slowed down due to absence of a leader on a TiKV node [#50566](https://github.com/pingcap/tidb/issues/50566) @[Leavrth](https://github.com/Leavrth) + - Fix the issue that log backup gets stuck after changing the TiKV IP address on the same node [#50445](https://github.com/pingcap/tidb/issues/50445) @[3pointer](https://github.com/3pointer) + - Fix the issue that BR cannot retry when encountering an error while reading file content from S3 [#49942](https://github.com/pingcap/tidb/issues/49942) @[Leavrth](https://github.com/Leavrth) + - Fix the issue that the `Unsupported collation` error is reported when you restore data from backups of an old version [#49466](https://github.com/pingcap/tidb/issues/49466) @[3pointer](https://github.com/3pointer) + + + TiCDC + + - Fix the issue that the changefeed reports an error after `TRUNCATE PARTITION` is executed on the upstream table [#10522](https://github.com/pingcap/tiflow/issues/10522) @[sdojjy](https://github.com/sdojjy) + - Fix the issue that the changefeed `resolved ts` does not advance in extreme cases [#10157](https://github.com/pingcap/tiflow/issues/10157) @[sdojjy](https://github.com/sdojjy) + - Fix the issue that the Syncpoint table might be incorrectly replicated [#10576](https://github.com/pingcap/tiflow/issues/10576) @[asddongmen](https://github.com/asddongmen) + - Fix the issue that after filtering out `add table partition` events is configured in `ignore-event`, TiCDC does not replicate other types of DML changes for related partitions to the downstream [#10524](https://github.com/pingcap/tiflow/issues/10524) @[CharlesCheung96](https://github.com/CharlesCheung96) + - Fix the issue that the file sequence number generated by the storage service might not increment correctly when using the storage sink [#10352](https://github.com/pingcap/tiflow/issues/10352) @[CharlesCheung96](https://github.com/CharlesCheung96) + - Fix the issue that TiCDC returns the `ErrChangeFeedAlreadyExists` error when concurrently creating multiple changefeeds [#10430](https://github.com/pingcap/tiflow/issues/10430) @[CharlesCheung96](https://github.com/CharlesCheung96) + - Fix the issue that `snapshot lost caused by GC` is not reported in time when resuming a changefeed and the `checkpoint-ts` of the changefeed is smaller than the GC safepoint of TiDB [#10463](https://github.com/pingcap/tiflow/issues/10463) @[sdojjy](https://github.com/sdojjy) + - Fix the issue that TiCDC fails to validate `TIMESTAMP` type checksum due to time zone mismatch after data integrity validation for single-row data is enabled [#10573](https://github.com/pingcap/tiflow/issues/10573) @[3AceShowHand](https://github.com/3AceShowHand) + + + TiDB Data Migration (DM) + + - Fix the issue that a wrong binlog event type in the task configuration causes upgrade failures [#10282](https://github.com/pingcap/tiflow/issues/10282) @[GMHDBJD](https://github.com/GMHDBJD) + - Fix the issue that a table with `shard_row_id_bits` causes the schema tracker to fail to initialize [#10308](https://github.com/pingcap/tiflow/issues/10308) @[GMHDBJD](https://github.com/GMHDBJD) + + + TiDB Lightning + + - Fix the issue that TiDB Lightning reports an error when encountering invalid symbolic link files during file scanning [#49423](https://github.com/pingcap/tidb/issues/49423) @[lance6716](https://github.com/lance6716) + - Fix the issue that TiDB Lightning fails to correctly parse date values containing `0` when `NO_ZERO_IN_DATE` is not included in `sql_mode` [#50757](https://github.com/pingcap/tidb/issues/50757) @[GMHDBJD](https://github.com/GMHDBJD) diff --git a/releases/release-notes.md b/releases/release-notes.md index 5607172aac383..0d18efd07d047 100644 --- a/releases/release-notes.md +++ b/releases/release-notes.md @@ -28,6 +28,7 @@ aliases: ['/docs/dev/releases/release-notes/','/docs/dev/releases/rn/'] ## 7.1 +- [7.1.4](/releases/release-7.1.4.md): 2024-03-11 - [7.1.3](/releases/release-7.1.3.md): 2023-12-21 - [7.1.2](/releases/release-7.1.2.md): 2023-10-25 - [7.1.1](/releases/release-7.1.1.md): 2023-07-24 diff --git a/releases/release-timeline.md b/releases/release-timeline.md index 78b8ebd1c71b5..32ef079de9802 100644 --- a/releases/release-timeline.md +++ b/releases/release-timeline.md @@ -9,6 +9,7 @@ This document shows all the released TiDB versions in reverse chronological orde | Version | Release Date | | :--- | :--- | +| [7.1.4](/releases/release-7.1.4.md) | 2024-03-11 | | [7.5.1](/releases/release-7.5.1.md) | 2024-02-29 | | [6.5.8](/releases/release-6.5.8.md) | 2024-02-02 | | [7.6.0-DMR](/releases/release-7.6.0.md) | 2024-01-25 | From 6131925045ef15f961c9de62c02f195e4a5c3df2 Mon Sep 17 00:00:00 2001 From: guo-shaoge Date: Tue, 12 Mar 2024 14:36:38 +0800 Subject: [PATCH 31/82] update hardware requirement for disaggregated tiflash (#16642) --- hardware-and-software-requirements.md | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/hardware-and-software-requirements.md b/hardware-and-software-requirements.md index 8896807aa8663..b345b4fbadf3d 100644 --- a/hardware-and-software-requirements.md +++ b/hardware-and-software-requirements.md @@ -267,3 +267,32 @@ As an open-source distributed SQL database, TiDB requires the following network ## Web browser requirements TiDB relies on [Grafana](https://grafana.com/) to provide visualization of database metrics. A recent version of Microsoft Edge, Safari, Chrome or Firefox with Javascript enabled is sufficient. + +## Hardware and software requirements for TiFlash disaggregated storage and compute architecture + +The preceding TiFlash software and hardware requirements are for the coupled storage and compute architecture. Starting from v7.0.0, TiFlash supports the [disaggregated storage and compute architecture](/tiflash/tiflash-disaggregated-and-s3.md). In this architecture, TiFlash is divided into two types of nodes: the Write Node and the Compute Node. The requirements for these nodes are as follows: + +- Software: remain the same as the coupled storage and compute architecture, see [OS and platform requirements](#os-and-platform-requirements). +- Network port: remain the same as the coupled storage and compute architecture, see [Network](#network-requirements). +- Disk space: + - TiFlash Write Node: it is recommended to configure at least 200 GB of disk space, which is used as a local buffer when adding TiFlash replicas and migrating Region replicas before uploading data to Amazon S3. In addition, an object storage compatible with Amazon S3 is required. + - TiFlash Compute Node: it is recommended to configure at least 100 GB of disk space, which is mainly used to cache the data read from the Write Node to improve performance. The cache of the Compute Node might be fully used, which is normal. +- CPU and memory requirements are described in the following sections. + +### Development and test environments + +| Component | CPU | Memory | Local Storage | Network | Number of Instances (Minimum Requirement) | +| --- | --- | --- | --- | --- | --- | +| TiFlash Write Node | 16 cores+ | 32 GB+ | SSD, 200 GB+ | Gigabit Ethernet | 1 | +| TiFlash Compute Node | 16 cores+ | 32 GB+ | SSD, 100 GB+ | Gigabit Ethernet | 0 (see the following note) | + +### Production environment + +| Component | CPU | Memory | Disk Type | Network | Number of Instances (Minimum Requirement) | +| --- | --- | --- | --- | --- | --- | +| TiFlash Write Node | 32 cores+ | 64 GB+ | 1 or more SSDs | 10 Gigabit Ethernet (2 recommended) | 1 | +| TiFlash Compute Node | 32 cores+ | 64 GB+ | 1 or more SSDs | 10 Gigabit Ethernet (2 recommended) | 0 (see the following note) | + +> **Note:** +> +> You can use deployment tools such as TiUP to quickly scale in or out the TiFlash Compute Node, within the range of `[0, +inf]`. From 75cca15f2dd1ea028306769922c199968411866e Mon Sep 17 00:00:00 2001 From: xixirangrang Date: Wed, 13 Mar 2024 14:21:40 +0800 Subject: [PATCH 32/82] ticdc: Add kafka eof troubleshooting (#16723) --- ticdc/ticdc-changefeed-config.md | 2 +- ticdc/ticdc-sink-to-pulsar.md | 2 +- ticdc/troubleshoot-ticdc.md | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ticdc/ticdc-changefeed-config.md b/ticdc/ticdc-changefeed-config.md index 8bf5671154d39..1e6215af3d754 100644 --- a/ticdc/ticdc-changefeed-config.md +++ b/ticdc/ticdc-changefeed-config.md @@ -161,7 +161,7 @@ delete-only-output-handle-key-columns = false # encoder-concurrency = 32 # Specifies whether to enable kafka-sink-v2 that uses the kafka-go sink library. -# Note: This configuration item only takes effect if the downstream is MQ. +# Note: This configuration item is experimental, and only takes effect if the downstream is MQ. # The default value is false. # enable-kafka-sink-v2 = false diff --git a/ticdc/ticdc-sink-to-pulsar.md b/ticdc/ticdc-sink-to-pulsar.md index d23e2db81dbe8..5f008e369faff 100644 --- a/ticdc/ticdc-sink-to-pulsar.md +++ b/ticdc/ticdc-sink-to-pulsar.md @@ -23,7 +23,7 @@ cdc cli changefeed create \ Create changefeed successfully! ID: simple-replication-task -Info: {"upstream_id":7277814241002263370,"namespace":"default","id":"simple-replication-task","sink_uri":"pulsar://127.0.0.1:6650/consumer-test?protocol=canal-json","create_time":"2024-01-25T14:42:32.000904+08:00","start_ts":444203257406423044,"config":{"memory_quota":1073741824,"case_sensitive":false,"force_replicate":false,"ignore_ineligible_table":false,"check_gc_safe_point":true,"enable_sync_point":false,"bdr_mode":false,"sync_point_interval":600000000000,"sync_point_retention":86400000000000,"filter":{"rules":["pulsar_test.*"]},"mounter":{"worker_num":16},"sink":{"protocol":"canal-json","csv":{"delimiter":",","quote":"\"","null":"\\N","include_commit_ts":false,"binary_encoding_method":"base64"},"dispatchers":[{"matcher":["pulsar_test.*"],"partition":"","topic":"test_{schema}_{table}"}],"encoder_concurrency":16,"terminator":"\r\n","date_separator":"day","enable_partition_separator":true,"enable_kafka_sink_v2":false,"only_output_updated_columns":false,"delete_only_output_handle_key_columns":false,"pulsar_config":{"connection-timeout":30,"operation-timeout":30,"batching-max-messages":1000,"batching-max-publish-delay":10,"send-timeout":30},"advance_timeout":150},"consistent":{"level":"none","max_log_size":64,"flush_interval":2000,"use_file_backend":false},"scheduler":{"enable_table_across_nodes":false,"region_threshold":100000,"write_key_threshold":0},"integrity":{"integrity_check_level":"none","corruption_handle_level":"warn"}},"state":"normal","creator_version":"v7.6.0","resolved_ts":444203257406423044,"checkpoint_ts":444203257406423044,"checkpoint_time":"2024-01-25 14:42:31.410"} +Info: {"upstream_id":7277814241002263370,"namespace":"default","id":"simple-replication-task","sink_uri":"pulsar://127.0.0.1:6650/consumer-test?protocol=canal-json","create_time":"2024-01-25T14:42:32.000904+08:00","start_ts":444203257406423044,"config":{"memory_quota":1073741824,"case_sensitive":false,"force_replicate":false,"ignore_ineligible_table":false,"check_gc_safe_point":true,"enable_sync_point":false,"bdr_mode":false,"sync_point_interval":600000000000,"sync_point_retention":86400000000000,"filter":{"rules":["pulsar_test.*"]},"mounter":{"worker_num":16},"sink":{"protocol":"canal-json","csv":{"delimiter":",","quote":"\"","null":"\\N","include_commit_ts":false,"binary_encoding_method":"base64"},"dispatchers":[{"matcher":["pulsar_test.*"],"partition":"","topic":"test_{schema}_{table}"}],"encoder_concurrency":16,"terminator":"\r\n","date_separator":"day","enable_partition_separator":true,"only_output_updated_columns":false,"delete_only_output_handle_key_columns":false,"pulsar_config":{"connection-timeout":30,"operation-timeout":30,"batching-max-messages":1000,"batching-max-publish-delay":10,"send-timeout":30},"advance_timeout":150},"consistent":{"level":"none","max_log_size":64,"flush_interval":2000,"use_file_backend":false},"scheduler":{"enable_table_across_nodes":false,"region_threshold":100000,"write_key_threshold":0},"integrity":{"integrity_check_level":"none","corruption_handle_level":"warn"}},"state":"normal","creator_version":"v7.6.0","resolved_ts":444203257406423044,"checkpoint_ts":444203257406423044,"checkpoint_time":"2024-01-25 14:42:31.410"} ``` The meaning of each parameter is as follows: diff --git a/ticdc/troubleshoot-ticdc.md b/ticdc/troubleshoot-ticdc.md index ccd46bd654e6a..569d29da9f794 100644 --- a/ticdc/troubleshoot-ticdc.md +++ b/ticdc/troubleshoot-ticdc.md @@ -137,3 +137,11 @@ If you want to skip this DDL statement that goes wrong, set the start-ts of the cdc cli changefeed remove --server=http://127.0.0.1:8300 --changefeed-id simple-replication-task cdc cli changefeed create --server=http://127.0.0.1:8300 --sink-uri="mysql://root:123456@127.0.0.1:3306/" --changefeed-id="simple-replication-task" --sort-engine="unified" --start-ts 415241823337054210 ``` + +## The `Kafka: client has run out of available brokers to talk to: EOF` error is reported when I use TiCDC to replicate messages to Kafka. What should I do? + +This error is typically caused by the connection failure between TiCDC and the Kafka cluster. To troubleshoot, you can check the Kafka logs and network status. One possible reason is that you did not specify the correct `kafka-version` parameter when creating the replication task, causing the Kafka client inside TiCDC to use the wrong Kafka API version when accessing the Kafka server. You can fix this issue by specifying the correct `kafka-version` parameter in the [`--sink-uri`](/ticdc/ticdc-sink-to-kafka.md#configure-sink-uri-for-kafka) configuration. For example: + +```shell +cdc cli changefeed create --server=http://127.0.0.1:8300 --sink-uri "kafka://127.0.0.1:9092/test?topic=test&protocol=open-protocol&kafka-version=2.4.0" +``` From a5d863886556a6c939563259c3feeef36092039d Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Wed, 13 Mar 2024 15:51:40 +0800 Subject: [PATCH 33/82] faq: update an outdated sentence (#16739) --- faq/sql-faq.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/faq/sql-faq.md b/faq/sql-faq.md index 34b83fed00e70..967cea5adaea1 100644 --- a/faq/sql-faq.md +++ b/faq/sql-faq.md @@ -229,9 +229,11 @@ You can combine the above two parameters with the DML of TiDB to use them. For e ## What's the trigger strategy for `auto analyze` in TiDB? -When the number of rows in a new table reaches 1000, and the ratio (the number of modified rows / the current total number of rows) is larger than `tidb_auto_analyze_ratio`, the [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) statement is automatically triggered. The default value of `tidb_auto_analyze_ratio` is `0.5`, indicating that this feature is enabled by default. To ensure safety, its minimum value is `0.3` when the feature is enabled, and it must be smaller than `pseudo-estimate-ratio` whose default value is `0.8`; otherwise pseudo statistics will be used for a period of time. It is recommended to set `tidb_auto_analyze_ratio` to `0.5`. +When the number of rows in a table or a single partition of a partitioned table reaches 1000, and the ratio (the number of modified rows / the current total number of rows) of the table or partition is larger than [`tidb_auto_analyze_ratio`](/system-variables.md#tidb_auto_analyze_ratio), the [`ANALYZE`](/sql-statements/sql-statement-analyze-table.md) statement is automatically triggered. -To disable `auto analyze`, use the system variable `tidb_enable_auto_analyze`. +The default value of the `tidb_auto_analyze_ratio` system variable is `0.5`, indicating that this feature is enabled by default. It is not recommended to set the value of `tidb_auto_analyze_ratio` to be larger than or equal to [`pseudo-estimate-ratio`](/tidb-configuration-file.md#pseudo-estimate-ratio) (the default value is `0.8`), otherwise the optimizer might use pseudo statistics. TiDB v5.3.0 introduces the [`tidb_enable_pseudo_for_outdated_stats`](/system-variables.md#tidb_enable_pseudo_for_outdated_stats-new-in-v530) variable, and when you set it to `OFF`, pseudo statistics are not used even if the statistics are outdated. + +To disable `auto analyze`, use the system variable [`tidb_enable_auto_analyze`](/system-variables.md#tidb_enable_auto_analyze-new-in-v610). ## Can I use optimizer hints to override the optimizer behavior? From 90fa767ef4c0d463b8be96ab738ca4c6e23594e4 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 13 Mar 2024 16:15:40 +0800 Subject: [PATCH 34/82] *: add notice on flashback cluster usage (#16738) --- sql-statements/sql-statement-flashback-cluster.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql-statements/sql-statement-flashback-cluster.md b/sql-statements/sql-statement-flashback-cluster.md index 4bf8cca95c3c2..e57553f1a6b20 100644 --- a/sql-statements/sql-statement-flashback-cluster.md +++ b/sql-statements/sql-statement-flashback-cluster.md @@ -14,6 +14,10 @@ Starting from v6.5.6, v7.1.3, v7.5.1, and v7.6.0, TiDB introduces the `FLASHBACK > > The `FLASHBACK CLUSTER TO [TIMESTAMP|TSO]` syntax is not applicable to [TiDB Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-serverless) clusters. To avoid unexpected results, do not execute this statement on TiDB Serverless clusters. +> **Warning:** +> +> When specifying a recovery point in time, make sure to check the validity of your target timestamp or TSO and avoid specifying a future time that exceeds the maximum TSO currently allocated by PD (see `Current TSO` on the Grafana PD panel). Otherwise, concurrent processing linear consistency and transaction isolation levels might be violated, leading to serious data correctness issues. + > **Warning:** From 87aff487d536847304737feaacaa49b12b006982 Mon Sep 17 00:00:00 2001 From: Aolin Date: Thu, 14 Mar 2024 17:24:42 +0800 Subject: [PATCH 35/82] ticdc: update worker-number to worker-count (#16662) --- ticdc/ticdc-manage-changefeed.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ticdc/ticdc-manage-changefeed.md b/ticdc/ticdc-manage-changefeed.md index a53d99f6b967a..d3dc7ce9bf5b8 100644 --- a/ticdc/ticdc-manage-changefeed.md +++ b/ticdc/ticdc-manage-changefeed.md @@ -81,7 +81,7 @@ cdc cli changefeed query --server=http://10.0.10.25:8300 --changefeed-id=simple- ```shell { "info": { - "sink-uri": "mysql://127.0.0.1:3306/?max-txn-row=20\u0026worker-number=4", + "sink-uri": "mysql://127.0.0.1:3306/?max-txn-row=20\u0026worker-count=4", "opts": {}, "create-time": "2020-08-27T10:33:41.687983832+08:00", "start-ts": 419036036249681921, @@ -196,7 +196,7 @@ TiCDC supports modifying the configuration of the replication task (not dynamica ```shell cdc cli changefeed pause -c test-cf --server=http://10.0.10.25:8300 -cdc cli changefeed update -c test-cf --server=http://10.0.10.25:8300 --sink-uri="mysql://127.0.0.1:3306/?max-txn-row=20&worker-number=8" --config=changefeed.toml +cdc cli changefeed update -c test-cf --server=http://10.0.10.25:8300 --sink-uri="mysql://127.0.0.1:3306/?max-txn-row=20&worker-count=8" --config=changefeed.toml cdc cli changefeed resume -c test-cf --server=http://10.0.10.25:8300 ``` From eaf582495daffd2b26d3b8e7e2caea300b0d3ed9 Mon Sep 17 00:00:00 2001 From: ShuNing Date: Mon, 18 Mar 2024 12:23:14 +0800 Subject: [PATCH 36/82] resource-control: reduce misunderstandings (#16778) --- tidb-resource-control.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tidb-resource-control.md b/tidb-resource-control.md index 18396aea2a034..63c8dc9cae67d 100644 --- a/tidb-resource-control.md +++ b/tidb-resource-control.md @@ -87,7 +87,7 @@ Request Unit (RU) is a unified abstraction unit in TiDB for system resources, wh 1 KiB write request payload consumes 1 RU - SQL CPU + CPU 3 ms consumes 1 RU From d64b4784c1dd8d6d18281fb33ac3fa59ba5cdf84 Mon Sep 17 00:00:00 2001 From: Jianjun Liao <36503113+Leavrth@users.noreply.github.com> Date: Mon, 18 Mar 2024 14:48:42 +0800 Subject: [PATCH 37/82] br: add faq - why oom when restore stats (#16781) --- faq/backup-and-restore-faq.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/faq/backup-and-restore-faq.md b/faq/backup-and-restore-faq.md index f76327604fc6f..de4efdfc1cda6 100644 --- a/faq/backup-and-restore-faq.md +++ b/faq/backup-and-restore-faq.md @@ -321,3 +321,9 @@ No, it is not necessary. Starting from v7.1.0, BR supports resuming data from a ## After the recovery is complete, can I delete a specific table and then recover it again? Yes, after deleting a specific table, you can recover it again. But note that, you can only recover tables that are deleted using the `DROP TABLE` or `TRUNCATE TABLE` statement, not the `DELETE FROM` statement. This is because `DELETE FROM` only updates the MVCC version to mark the data to be deleted, and the actual data deletion occurs after GC. + +### Why does BR take a lot of memory when restoring statistics information? + +Before v7.6.0, the statistics data backed up by BR is stored together with the table information and loaded into memory during recovery. Therefore, when the backup statistics data is very large, BR needs to occupy a large amount of memory. + +Starting from v7.6.0, the backup statistics is stored in a specific file separately. BR does not load statistic data of any table until BR starts to restore the table, which saves memory. From af411df1846b3bf51022551478185f7ca6da8d97 Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Mon, 18 Mar 2024 16:23:14 +0800 Subject: [PATCH 38/82] *: update storage unit in system variables and config file (#16775) --- system-variables.md | 14 +- tikv-configuration-file.md | 264 ++++++++++++++++++------------------- 2 files changed, 139 insertions(+), 139 deletions(-) diff --git a/system-variables.md b/system-variables.md index 01e26e42449c3..e9013c43dc510 100644 --- a/system-variables.md +++ b/system-variables.md @@ -4582,8 +4582,8 @@ SHOW WARNINGS; - Scope: SESSION | GLOBAL - Persists to cluster: Yes - Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes -- Default value: `2097152` (which is 2 MB) -- Range: `[0, 9223372036854775807]`, in bytes. The memory format with the units "KB|MB|GB|TB" is also supported. `0` means no limit. +- Default value: `2097152` (which is 2 MiB) +- Range: `[0, 9223372036854775807]`, in bytes. The memory format with the units "KiB|MiB|GiB|TiB" is also supported. `0` means no limit. - This variable controls the maximum size of a plan that can be cached in prepared or non-prepared plan cache. If the size of a plan exceeds this value, the plan will not be cached. For more details, see [Memory management of prepared plan cache](/sql-prepared-plan-cache.md#memory-management-of-prepared-plan-cache) and [Non-prepared plan cache](/sql-plan-management.md#usage). ### tidb_pprof_sql_cpu New in v4.0 @@ -4888,8 +4888,8 @@ SHOW WARNINGS; - Default value: `80%` - Range: - You can set the value in the percentage format, which means the percentage of the memory usage relative to the total memory. The value range is `[1%, 99%]`. - - You can also set the value in memory size. The value range is `0` and `[536870912, 9223372036854775807]` in bytes. The memory format with the units "KB|MB|GB|TB" is supported. `0` means no memory limit. - - If this variable is set to a memory size that is less than 512 MB but not `0`, TiDB uses 512 MB as the actual size. + - You can also set the value in memory size. The value range is `0` and `[536870912, 9223372036854775807]` in bytes. The memory format with the units "KiB|MiB|GiB|TiB" is supported. `0` means no memory limit. + - If this variable is set to a memory size that is less than 512 MiB but not `0`, TiDB uses 512 MiB as the actual size. - This variable specifies the memory limit for a TiDB instance. When the memory usage of TiDB reaches the limit, TiDB cancels the currently running SQL statement with the highest memory usage. After the SQL statement is successfully canceled, TiDB tries to call Golang GC to immediately reclaim memory to relieve memory stress as soon as possible. - Only the SQL statements with more memory usage than the [`tidb_server_memory_limit_sess_min_size`](/system-variables.md#tidb_server_memory_limit_sess_min_size-new-in-v640) limit are selected as the SQL statements to be canceled first. - Currently, TiDB cancels only one SQL statement at a time. After TiDB completely cancels a SQL statement and recovers resources, if the memory usage is still greater than the limit set by this variable, TiDB starts the next cancel operation. @@ -4916,8 +4916,8 @@ SHOW WARNINGS; - Scope: GLOBAL - Persists to cluster: Yes - Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No -- Default value: `134217728` (which is 128 MB) -- Range: `[128, 9223372036854775807]`, in bytes. The memory format with the units "KB|MB|GB|TB" is also supported. +- Default value: `134217728` (which is 128 MiB) +- Range: `[128, 9223372036854775807]`, in bytes. The memory format with the units "KiB|MiB|GiB|TiB" is also supported. - After you enable the memory limit, TiDB will terminate the SQL statement with the highest memory usage on the current instance. This variable specifies the minimum memory usage of the SQL statement to be terminated. If the memory usage of a TiDB instance that exceeds the limit is caused by too many sessions with low memory usage, you can properly lower the value of this variable to allow more sessions to be canceled. ### tidb_service_scope New in v7.4.0 @@ -5682,7 +5682,7 @@ For details, see [Identify Slow Queries](/identify-slow-queries.md). -- This variable is used to control the batch size of transaction commit requests that TiDB sends to TiKV. If most of the transactions in the application workload have a large number of write operations, adjusting this variable to a larger value can improve the performance of batch processing. However, if this variable is set to too large a value and exceeds the limit of TiKV's maximum size of a single log (which is 8 MB by default), the commits might fail. +- This variable is used to control the batch size of transaction commit requests that TiDB sends to TiKV. If most of the transactions in the application workload have a large number of write operations, adjusting this variable to a larger value can improve the performance of batch processing. However, if this variable is set to too large a value and exceeds the limit of TiKV's maximum size of a single log (which is 8 MiB by default), the commits might fail. diff --git a/tikv-configuration-file.md b/tikv-configuration-file.md index 85dd3e89bfa87..e3c1d4e321a35 100644 --- a/tikv-configuration-file.md +++ b/tikv-configuration-file.md @@ -177,9 +177,9 @@ This document only describes the parameters that are not included in command-lin ### `grpc-stream-initial-window-size` + The window size of the gRPC stream -+ Default value: `2MB` -+ Unit: KB|MB|GB -+ Minimum value: `"1KB"` ++ Default value: `2MiB` ++ Unit: KiB|MiB|GiB ++ Minimum value: `"1KiB"` ### `grpc-keepalive-time` @@ -220,9 +220,9 @@ This document only describes the parameters that are not included in command-lin ### `snap-io-max-bytes-per-sec` + The maximum allowable disk bandwidth when processing snapshots -+ Default value: `"100MB"` -+ Unit: KB|MB|GB -+ Minimum value: `"1KB"` ++ Default value: `"100MiB"` ++ Unit: KiB|MiB|GiB ++ Minimum value: `"1KiB"` ### `enable-request-batch` @@ -283,9 +283,9 @@ Configuration items related to the single thread pool serving read requests. Thi + The stack size of the threads in the unified thread pool + Type: Integer + Unit -+ Default value: `"10MB"` -+ Unit: KB|MB|GB -+ Minimum value: `"2MB"` ++ Default value: `"10MiB"` ++ Unit: KiB|MiB|GiB ++ Minimum value: `"2MiB"` + Maximum value: The number of Kbytes output in the result of the `ulimit -sH` command executed in the system. ### `max-tasks-per-worker` @@ -348,9 +348,9 @@ Configuration items related to storage thread pool. + The stack size of threads in the Storage read thread pool + Type: Integer + Unit -+ Default value: `"10MB"` -+ Unit: KB|MB|GB -+ Minimum value: `"2MB"` ++ Default value: `"10MiB"` ++ Unit: KiB|MiB|GiB ++ Minimum value: `"2MiB"` + Maximum value: The number of Kbytes output in the result of the `ulimit -sH` command executed in the system. ## `readpool.coprocessor` @@ -402,9 +402,9 @@ Configuration items related to the Coprocessor thread pool. + The stack size of the thread in the Coprocessor thread pool + Type: Integer + Unit -+ Default value: `"10MB"` -+ Unit: KB|MB|GB -+ Minimum value: `"2MB"` ++ Default value: `"10MiB"` ++ Unit: KiB|MiB|GiB ++ Minimum value: `"2MiB"` + Maximum value: The number of Kbytes output in the result of the `ulimit -sH` command executed in the system. ## storage @@ -444,8 +444,8 @@ Configuration items related to storage. ### `scheduler-pending-write-threshold` + The maximum size of the write queue. A `Server Is Busy` error is returned for a new write to TiKV when this value is exceeded. -+ Default value: `"100MB"` -+ Unit: MB|GB ++ Default value: `"100MiB"` ++ Unit: MiB|GiB ### `enable-async-apply-prewrite` @@ -456,9 +456,9 @@ Configuration items related to storage. + When TiKV is started, some space is reserved on the disk as disk protection. When the remaining disk space is less than the reserved space, TiKV restricts some write operations. The reserved space is divided into two parts: 80% of the reserved space is used as the extra disk space required for operations when the disk space is insufficient, and the other 20% is used to store the temporary file. In the process of reclaiming space, if the storage is exhausted by using too much extra disk space, this temporary file serves as the last protection for restoring services. + The name of the temporary file is `space_placeholder_file`, located in the `storage.data-dir` directory. When TiKV goes offline because its disk space ran out, if you restart TiKV, the temporary file is automatically deleted and TiKV tries to reclaim the space. -+ When the remaining space is insufficient, TiKV does not create the temporary file. The effectiveness of the protection is related to the size of the reserved space. The size of the reserved space is the larger value between 5% of the disk capacity and this configuration value. When the value of this configuration item is `"0MB"`, TiKV disables this disk protection feature. -+ Default value: `"5GB"` -+ Unit: MB|GB ++ When the remaining space is insufficient, TiKV does not create the temporary file. The effectiveness of the protection is related to the size of the reserved space. The size of the reserved space is the larger value between 5% of the disk capacity and this configuration value. When the value of this configuration item is `"0MiB"`, TiKV disables this disk protection feature. ++ Default value: `"5GiB"` ++ Unit: MiB|GiB ### `enable-ttl` @@ -514,7 +514,7 @@ Configuration items related to the sharing of block cache among multiple RocksDB + When `storage.engine="raft-kv"`, the default value is 45% of the size of total system memory. + When `storage.engine="partitioned-raft-kv"`, the default value is 30% of the size of total system memory. -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ## storage.flow-control @@ -538,12 +538,12 @@ Configuration items related to the flow control mechanism in TiKV. This mechanis ### `soft-pending-compaction-bytes-limit` + When the pending compaction bytes in KvDB reach this threshold, the flow control mechanism starts to reject some write requests and reports the `ServerIsBusy` error. When `enable` is set to `true`, this configuration item overrides `rocksdb.(defaultcf|writecf|lockcf).soft-pending-compaction-bytes-limit`. -+ Default value: `"192GB"` ++ Default value: `"192GiB"` ### `hard-pending-compaction-bytes-limit` + When the pending compaction bytes in KvDB reach this threshold, the flow control mechanism rejects all write requests and reports the `ServerIsBusy` error. When `enable` is set to `true`, this configuration item overrides `rocksdb.(defaultcf|writecf|lockcf).hard-pending-compaction-bytes-limit`. -+ Default value: `"1024GB"` ++ Default value: `"1024GiB"` ## storage.io-rate-limit @@ -552,7 +552,7 @@ Configuration items related to the I/O rate limiter. ### `max-bytes-per-sec` + Limits the maximum I/O bytes that a server can write to or read from the disk (determined by the `mode` configuration item below) in one second. When this limit is reached, TiKV prefers throttling background operations over foreground ones. The value of this configuration item should be set to the disk's optimal I/O bandwidth, for example, the maximum I/O bandwidth specified by your cloud disk vendor. When this configuration value is set to zero, disk I/O operations are not limited. -+ Default value: `"0MB"` ++ Default value: `"0MiB"` ### `mode` @@ -604,7 +604,7 @@ Configuration items related to Raftstore. + The storage capacity, which is the maximum size allowed to store data. If `capacity` is left unspecified, the capacity of the current disk prevails. To deploy multiple TiKV instances on the same physical disk, add this parameter to the TiKV configuration. For details, see [Key parameters of the hybrid deployment](/hybrid-deployment-topology.md#key-parameters). + Default value: `0` -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ### `raftdb-path` @@ -668,10 +668,10 @@ Configuration items related to Raftstore. > This configuration item cannot be queried via SQL statements but can be configured in the configuration file. + The soft limit on the size of a single message packet -+ Default value: `"1MB"` ++ Default value: `"1MiB"` + Minimum value: greater than `0` -+ Maximum value: `3GB` -+ Unit: KB|MB|GB ++ Maximum value: `3GiB` ++ Unit: KiB|MiB|GiB ### `raft-max-inflight-msgs` @@ -687,9 +687,9 @@ Configuration items related to Raftstore. ### `raft-entry-max-size` + The hard limit on the maximum size of a single log -+ Default value: `"8MB"` ++ Default value: `"8MiB"` + Minimum value: `0` -+ Unit: MB|GB ++ Unit: MiB|GiB ### `raft-log-compact-sync-interval` New in v5.3 @@ -712,7 +712,7 @@ Configuration items related to Raftstore. ### `raft-log-gc-count-limit` + The hard limit on the allowable number of residual Raft logs -+ Default value: the log number that can be accommodated in the 3/4 Region size (calculated as 1MB for each log) ++ Default value: the log number that can be accommodated in the 3/4 Region size (calculated as 1MiB for each log) + Minimum value: `0` ### `raft-log-gc-size-limit` @@ -845,9 +845,9 @@ Configuration items related to Raftstore. ### `lock-cf-compact-bytes-threshold` + The size out of which TiKV triggers a manual compaction for the Lock Column Family -+ Default value: `"256MB"` ++ Default value: `"256MiB"` + Minimum value: `0` -+ Unit: MB ++ Unit: MiB ### `notify-capacity` @@ -900,9 +900,9 @@ Configuration items related to Raftstore. ### `snap-apply-batch-size` + The memory cache size required when the imported snapshot file is written into the disk -+ Default value: `"10MB"` ++ Default value: `"10MiB"` + Minimum value: `0` -+ Unit: MB ++ Unit: MiB ### `consistency-check-interval` @@ -1014,7 +1014,7 @@ Configuration items related to Raftstore. ### `raft-write-size-limit` New in v5.3.0 + Determines the threshold at which Raft data is written into the disk. If the data size is larger than the value of this configuration item, the data is written to the disk. When the value of `store-io-pool-size` is `0`, this configuration item does not take effect. -+ Default value: `1MB` ++ Default value: `1MiB` + Minimum value: `0` ### `report-min-resolved-ts-interval` New in v6.0.0 @@ -1155,9 +1155,9 @@ Configuration items related to RocksDB ### `max-manifest-file-size` + The maximum size of a RocksDB Manifest file -+ Default value: `"128MB"` ++ Default value: `"128MiB"` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `create-if-missing` @@ -1191,14 +1191,14 @@ Configuration items related to RocksDB + The size limit of the archived WAL files. When the value is exceeded, the system deletes these files. + Default value: `0` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `max-total-wal-size` + The maximum RocksDB WAL size in total, which is the size of `*.log` files in the `data-dir`. + Default value: - + When `storage.engine="raft-kv"`, the default value is `"4GB"`. + + When `storage.engine="raft-kv"`, the default value is `"4GiB"`. + When `storage.engine="partitioned-raft-kv"`, the default value is `1`. ### `stats-dump-period` @@ -1211,17 +1211,17 @@ Configuration items related to RocksDB ### `compaction-readahead-size` -+ Enables the readahead feature during RocksDB compaction and specifies the size of readahead data. If you are using mechanical disks, it is recommended to set the value to 2MB at least. ++ Enables the readahead feature during RocksDB compaction and specifies the size of readahead data. If you are using mechanical disks, it is recommended to set the value to 2MiB at least. + Default value: `0` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `writable-file-max-buffer-size` + The maximum buffer size used in WritableFileWrite -+ Default value: `"1MB"` ++ Default value: `"1MiB"` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `use-direct-io-for-flush-and-compaction` @@ -1231,9 +1231,9 @@ Configuration items related to RocksDB ### `rate-bytes-per-sec` + When Titan is disabled, this configuration item limits the I/O rate of RocksDB compaction to reduce the impact of RocksDB compaction on the foreground read and write performance during traffic peaks. When Titan is enabled, this configuration item limits the summed I/O rates of RocksDB compaction and Titan GC. If you find that the I/O or CPU consumption of RocksDB compaction and Titan GC is too large, set this configuration item to an appropriate value according the disk I/O bandwidth and the actual write traffic. -+ Default value: `10GB` ++ Default value: `10GiB` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `rate-limiter-refill-period` @@ -1259,23 +1259,23 @@ Configuration items related to RocksDB ### `bytes-per-sync` + The rate at which OS incrementally synchronizes files to disk while these files are being written asynchronously -+ Default value: `"1MB"` ++ Default value: `"1MiB"` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `wal-bytes-per-sync` + The rate at which OS incrementally synchronizes WAL files to disk while the WAL files are being written -+ Default value: `"512KB"` ++ Default value: `"512KiB"` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `info-log-max-size` + The maximum size of Info log -+ Default value: `"1GB"` ++ Default value: `"1GiB"` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `info-log-roll-time` @@ -1335,7 +1335,7 @@ Configuration items related to Titan. > > - To enhance the performance of wide table and JSON data writing and point query, starting from TiDB v7.6.0, the default value changes from `false` to `true`, which means that Titan is enabled by default. > - Existing clusters upgraded to v7.6.0 or later versions retain the original configuration, which means that if Titan is not explicitly enabled, it still uses RocksDB. -> - If the cluster has enabled Titan before upgrading to TiDB v7.6.0 or later versions, Titan will be retained after the upgrade, and the [`min-blob-size`](/tikv-configuration-file.md#min-blob-size) configuration before the upgrade will be retained. If you do not explicitly configure the value before the upgrade, the default value of the previous version `1KB` will be retained to ensure the stability of the cluster configuration after the upgrade. +> - If the cluster has enabled Titan before upgrading to TiDB v7.6.0 or later versions, Titan will be retained after the upgrade, and the [`min-blob-size`](/tikv-configuration-file.md#min-blob-size) configuration before the upgrade will be retained. If you do not explicitly configure the value before the upgrade, the default value of the previous version `1KiB` will be retained to ensure the stability of the cluster configuration after the upgrade. + Enables or disables Titan. + Default value: `true` @@ -1363,10 +1363,10 @@ Configuration items related to `rocksdb.defaultcf`, `rocksdb.writecf`, and `rock ### `block-size` + The default size of a RocksDB block -+ Default value for `defaultcf` and `writecf`: `"32KB"` -+ Default value for `lockcf`: `"16KB"` -+ Minimum value: `"1KB"` -+ Unit: KB|MB|GB ++ Default value for `defaultcf` and `writecf`: `"32KiB"` ++ Default value for `lockcf`: `"16KiB"` ++ Minimum value: `"1KiB"` ++ Unit: KiB|MiB|GiB ### `block-cache-size` @@ -1379,7 +1379,7 @@ Configuration items related to `rocksdb.defaultcf`, `rocksdb.writecf`, and `rock + Default value for `writecf`: `Total machine memory * 15%` + Default value for `lockcf`: `Total machine memory * 2%` + Minimum value: `0` -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ### `disable-block-cache` @@ -1460,12 +1460,12 @@ Configuration items related to `rocksdb.defaultcf`, `rocksdb.writecf`, and `rock ### `write-buffer-size` + Memtable size -+ Default value for `defaultcf` and `writecf`: `"128MB"` ++ Default value for `defaultcf` and `writecf`: `"128MiB"` + Default value for `lockcf`: - + When `storage.engine="raft-kv"`, the default value is `"32MB"`. - + When `storage.engine="partitioned-raft-kv"`, the default value is `"4MB"`. + + When `storage.engine="raft-kv"`, the default value is `"32MiB"`. + + When `storage.engine="partitioned-raft-kv"`, the default value is `"4MiB"`. + Minimum value: `0` -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ### `max-write-buffer-number` @@ -1482,18 +1482,18 @@ Configuration items related to `rocksdb.defaultcf`, `rocksdb.writecf`, and `rock ### `max-bytes-for-level-base` + The maximum number of bytes at base level (level-1). Generally, it is set to 4 times the size of a memtable. When the level-1 data size reaches the limit value of `max-bytes-for-level-base`, the SST files of level-1 and their overlapping SST files of level-2 will be compacted. -+ Default value for `defaultcf` and `writecf`: `"512MB"` -+ Default value for `lockcf`: `"128MB"` ++ Default value for `defaultcf` and `writecf`: `"512MiB"` ++ Default value for `lockcf`: `"128MiB"` + Minimum value: `0` -+ Unit: KB|MB|GB -+ It is recommended that the value of `max-bytes-for-level-base` is set approximately equal to the data volume in L0 to reduce unnecessary compaction. For example, if the compression method is "no:no:lz4:lz4:lz4:lz4:lz4", the value of `max-bytes-for-level-base` should be `write-buffer-size * 4`, because there is no compression of L0 and L1 and the trigger condition of compaction for L0 is that the number of the SST files reaches 4 (the default value). When L0 and L1 both adopt compaction, you need to analyze RocksDB logs to understand the size of an SST file compressed from a memtable. For example, if the file size is 32 MB, it is recommended to set the value of `max-bytes-for-level-base` to 128 MB (`32 MB * 4`). ++ Unit: KiB|MiB|GiB ++ It is recommended that the value of `max-bytes-for-level-base` is set approximately equal to the data volume in L0 to reduce unnecessary compaction. For example, if the compression method is "no:no:lz4:lz4:lz4:lz4:lz4", the value of `max-bytes-for-level-base` should be `write-buffer-size * 4`, because there is no compression of L0 and L1 and the trigger condition of compaction for L0 is that the number of the SST files reaches 4 (the default value). When L0 and L1 both adopt compaction, you need to analyze RocksDB logs to understand the size of an SST file compressed from a memtable. For example, if the file size is 32 MiB, it is recommended to set the value of `max-bytes-for-level-base` to 128 MiB (`32 MiB * 4`). ### `target-file-size-base` + The size of the target file at base level. This value is overridden by `compaction-guard-max-output-file-size` when the `enable-compaction-guard` value is `true`. -+ Default value: `"8MB"` ++ Default value: `"8MiB"` + Minimum value: `0` -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ### `level0-file-num-compaction-trigger` @@ -1517,9 +1517,9 @@ Configuration items related to `rocksdb.defaultcf`, `rocksdb.writecf`, and `rock ### `max-compaction-bytes` + The maximum number of bytes written into disk per compaction -+ Default value: `"2GB"` ++ Default value: `"2GiB"` + Minimum value: `0` -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ### `compaction-pri` @@ -1561,14 +1561,14 @@ Configuration items related to `rocksdb.defaultcf`, `rocksdb.writecf`, and `rock ### `soft-pending-compaction-bytes-limit` + The soft limit on the pending compaction bytes. When `storage.flow-control.enable` is set to `true`, `storage.flow-control.soft-pending-compaction-bytes-limit` overrides this configuration item. -+ Default value: `"192GB"` -+ Unit: KB|MB|GB ++ Default value: `"192GiB"` ++ Unit: KiB|MiB|GiB ### `hard-pending-compaction-bytes-limit` + The hard limit on the pending compaction bytes. When `storage.flow-control.enable` is set to `true`, `storage.flow-control.hard-pending-compaction-bytes-limit` overrides this configuration item. -+ Default value: `"256GB"` -+ Unit: KB|MB|GB ++ Default value: `"256GiB"` ++ Unit: KiB|MiB|GiB ### `enable-compaction-guard` @@ -1579,14 +1579,14 @@ Configuration items related to `rocksdb.defaultcf`, `rocksdb.writecf`, and `rock ### `compaction-guard-min-output-file-size` + The minimum SST file size when the compaction guard is enabled. This configuration prevents SST files from being too small when the compaction guard is enabled. -+ Default value: `"8MB"` -+ Unit: KB|MB|GB ++ Default value: `"8MiB"` ++ Unit: KiB|MiB|GiB ### `compaction-guard-max-output-file-size` + The maximum SST file size when the compaction guard is enabled. The configuration prevents SST files from being too large when the compaction guard is enabled. This configuration overrides `target-file-size-base` for the same column family. -+ Default value: `"128MB"` -+ Unit: KB|MB|GB ++ Default value: `"128MiB"` ++ Unit: KiB|MiB|GiB ### `format-version` New in v6.2.0 @@ -1627,14 +1627,14 @@ Configuration items related to `rocksdb.defaultcf.titan`. > **Note:** > -> - Starting from TiDB v7.6.0, Titan is enabled by default to enhance the performance of wide table and JSON data writing and point query. The default value of `min-blob-size` changes from `1KB` to `32KB`. This means that values exceeding `32KB` is stored in Titan, while other data continues to be stored in RocksDB. -> - To ensure configuration consistency, for existing clusters upgrading to TiDB v7.6.0 or later versions, if you do not explicitly set `min-blob-size` before the upgrade, TiDB retains the previous default value of `1KB`. -> - A value smaller than `32KB` might affect the performance of range scans. However, if the workload primarily involves heavy writes and point queries, you can consider decreasing the value of `min-blob-size` for better performance. +> - Starting from TiDB v7.6.0, Titan is enabled by default to enhance the performance of wide table and JSON data writing and point query. The default value of `min-blob-size` changes from `1KiB` to `32KiB`. This means that values exceeding `32KiB` is stored in Titan, while other data continues to be stored in RocksDB. +> - To ensure configuration consistency, for existing clusters upgrading to TiDB v7.6.0 or later versions, if you do not explicitly set `min-blob-size` before the upgrade, TiDB retains the previous default value of `1KiB`. +> - A value smaller than `32KiB` might affect the performance of range scans. However, if the workload primarily involves heavy writes and point queries, you can consider decreasing the value of `min-blob-size` for better performance. + The smallest value stored in a Blob file. Values smaller than the specified size are stored in the LSM-Tree. -+ Default value: `"32KB"` ++ Default value: `"32KiB"` + Minimum value: `0` -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ### `blob-file-compression` @@ -1649,31 +1649,31 @@ Configuration items related to `rocksdb.defaultcf.titan`. ### `zstd-dict-size` -+ The zstd dictionary compression size. The default value is `"0KB"`, which means to disable the zstd dictionary compression. In this case, Titan compresses data based on single values, whereas RocksDB compresses data based on blocks (`32KB` by default). When the average size of Titan values is less than `32KB`, Titan's compression ratio is lower than that of RocksDB. Taking JSON as an example, the store size in Titan can be 30% to 50% larger than that of RocksDB. The actual compression ratio depends on whether the value content is suitable for compression and the similarity among different values. You can enable the zstd dictionary compression to increase the compression ratio by configuring `zstd-dict-size` (for example, set it to `16KB`). The actual store size can be lower than that of RocksDB. But the zstd dictionary compression might lead to about 10% performance regression in specific workloads. -+ Default value: `"0KB"` -+ Unit: KB|MB|GB ++ The zstd dictionary compression size. The default value is `"0KiB"`, which means to disable the zstd dictionary compression. In this case, Titan compresses data based on single values, whereas RocksDB compresses data based on blocks (`32KiB` by default). When the average size of Titan values is less than `32KiB`, Titan's compression ratio is lower than that of RocksDB. Taking JSON as an example, the store size in Titan can be 30% to 50% larger than that of RocksDB. The actual compression ratio depends on whether the value content is suitable for compression and the similarity among different values. You can enable the zstd dictionary compression to increase the compression ratio by configuring `zstd-dict-size` (for example, set it to `16KiB`). The actual store size can be lower than that of RocksDB. But the zstd dictionary compression might lead to about 10% performance regression in specific workloads. ++ Default value: `"0KiB"` ++ Unit: KiB|MiB|GiB ### `blob-cache-size` + The cache size of a Blob file -+ Default value: `"0GB"` ++ Default value: `"0GiB"` + Minimum value: `0` + Recommended value: After database stabilization, it is recommended to set the RocksDB block cache (`storage.block-cache.capacity`) based on monitoring to maintain a block cache hit rate of at least 95%, and set `blob-cache-size` to `(total memory size) * 50% - (size of block cache)`. This is to ensure that the block cache is sufficiently large to cache the entire RocksDB, while maximizing the blob cache size. However, to prevent a significant drop in the block cache hit rate, do not set the blob cache size too large. -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ### `min-gc-batch-size` + The minimum total size of Blob files required to perform GC for one time -+ Default value: `"16MB"` ++ Default value: `"16MiB"` + Minimum value: `0` -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ### `max-gc-batch-size` + The maximum total size of Blob files allowed to perform GC for one time -+ Default value: `"64MB"` ++ Default value: `"64MiB"` + Minimum value: `0` -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ### `discardable-ratio` @@ -1699,9 +1699,9 @@ Configuration items related to `rocksdb.defaultcf.titan`. ### `merge-small-file-threshold` + When the size of a Blob file is smaller than this value, the Blob file might still be selected for GC. In this situation, `discardable-ratio` is ignored. -+ Default value: `"8MB"` ++ Default value: `"8MiB"` + Minimum value: `0` -+ Unit: KB|MB|GB ++ Unit: KiB|MiB|GiB ### `blob-run-mode` @@ -1742,9 +1742,9 @@ Configuration items related to `raftdb` ### `max-manifest-file-size` + The maximum size of a RocksDB Manifest file -+ Default value: `"20MB"` ++ Default value: `"20MiB"` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `create-if-missing` @@ -1775,29 +1775,29 @@ Configuration items related to `raftdb` + The size limit of the archived WAL files. When the value is exceeded, the system deletes these files. + Default value: `0` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `max-total-wal-size` + The maximum RocksDB WAL size in total -+ Default value: `"4GB"` - + When `storage.engine="raft-kv"`, the default value is `"4GB"`. ++ Default value: + + When `storage.engine="raft-kv"`, the default value is `"4GiB"`. + When `storage.engine="partitioned-raft-kv"`, the default value is `1`. ### `compaction-readahead-size` + Controls whether to enable the readahead feature during RocksDB compaction and specify the size of readahead data. -+ If you use mechanical disks, it is recommended to set the value to `2MB` at least. ++ If you use mechanical disks, it is recommended to set the value to `2MiB` at least. + Default value: `0` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `writable-file-max-buffer-size` + The maximum buffer size used in WritableFileWrite -+ Default value: `"1MB"` ++ Default value: `"1MiB"` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `use-direct-io-for-flush-and-compaction` @@ -1817,23 +1817,23 @@ Configuration items related to `raftdb` ### `bytes-per-sync` + The rate at which OS incrementally synchronizes files to disk while these files are being written asynchronously -+ Default value: `"1MB"` ++ Default value: `"1MiB"` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `wal-bytes-per-sync` + The rate at which OS incrementally synchronizes WAL files to disk when the WAL files are being written -+ Default value: `"512KB"` ++ Default value: `"512KiB"` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `info-log-max-size` + The maximum size of Info logs -+ Default value: `"1GB"` ++ Default value: `"1GiB"` + Minimum value: `0` -+ Unit: B|KB|MB|GB ++ Unit: B|KiB|MiB|GiB ### `info-log-roll-time` @@ -1880,24 +1880,24 @@ Configuration items related to Raft Engine. ### `batch-compression-threshold` + Specifies the threshold size of a log batch. A log batch larger than this configuration is compressed. If you set this configuration item to `0`, compression is disabled. -+ Default value: `"8KB"` ++ Default value: `"8KiB"` ### `bytes-per-sync` + Specifies the maximum accumulative size of buffered writes. When this configuration value is exceeded, buffered writes are flushed to the disk. + If you set this configuration item to `0`, incremental sync is disabled. -+ Default value: `"4MB"` ++ Default value: `"4MiB"` ### `target-file-size` + Specifies the maximum size of log files. When a log file is larger than this value, it is rotated. -+ Default value: `"128MB"` ++ Default value: `"128MiB"` ### `purge-threshold` + Specifies the threshold size of the main log queue. When this configuration value is exceeded, the main log queue is purged. + This configuration can be used to adjust the disk space usage of Raft Engine. -+ Default value: `"10GB"` ++ Default value: `"10GiB"` ### `recovery-mode` @@ -1908,7 +1908,7 @@ Configuration items related to Raft Engine. ### `recovery-read-block-size` + The minimum I/O size for reading log files during recovery. -+ Default value: `"16KB"` ++ Default value: `"16KiB"` + Minimum value: `"512B"` ### `recovery-threads` @@ -2091,7 +2091,7 @@ Configuration items related to BR backup. + The threshold of the backup SST file size. If the size of a backup file in a TiKV Region exceeds this threshold, the file is backed up to several files with the TiKV Region split into multiple Region ranges. Each of the files in the split Regions is the same size as `sst-max-size` (or slightly larger). + For example, when the size of a backup file in the Region of `[a,e)` is larger than `sst-max-size`, the file is backed up to several files with regions `[a,b)`, `[b,c)`, `[c,d)` and `[d,e)`, and the size of `[a,b)`, `[b,c)`, `[c,d)` is the same as that of `sst-max-size` (or slightly larger). -+ Default value: `"144MB"` ++ Default value: `"144MiB"` ### `enable-auto-tune` New in v5.4.0 @@ -2139,7 +2139,7 @@ Configuration items related to log backup. ### `initial-scan-pending-memory-quota` New in v6.2.0 + The quota of cache used for storing incremental scan data during log backup. -+ Default value: `min(Total machine memory * 10%, 512 MB)` ++ Default value: `min(Total machine memory * 10%, 512 MiB)` ### `initial-scan-rate-limit` New in v6.2.0 @@ -2174,17 +2174,17 @@ Configuration items related to TiCDC. ### `old-value-cache-memory-quota` + The upper limit of memory usage by TiCDC old values. -+ Default value: `512MB` ++ Default value: `512MiB` ### `sink-memory-quota` + The upper limit of memory usage by TiCDC data change events. -+ Default value: `512MB` ++ Default value: `512MiB` ### `incremental-scan-speed-limit` + The maximum speed at which historical data is incrementally scanned. -+ Default value: `"128MB"`, which means 128 MB per second. ++ Default value: `"128MiB"`, which means 128 MiB per second. ### `incremental-scan-threads` @@ -2268,14 +2268,14 @@ Suppose that your machine on which TiKV is deployed has limited resources, for e #### `foreground-write-bandwidth` New in v6.0.0 + The soft limit on the bandwidth with which transactions write data. -+ Default value: `0KB` (which means no limit) -+ Recommended setting: Use the default value `0` in most cases unless the `foreground-cpu-time` setting is not enough to limit the write bandwidth. For such an exception, it is recommended to set the value smaller than `50MB` in the instance with 4 or less cores. ++ Default value: `0KiB` (which means no limit) ++ Recommended setting: Use the default value `0` in most cases unless the `foreground-cpu-time` setting is not enough to limit the write bandwidth. For such an exception, it is recommended to set the value smaller than `50MiB` in the instance with 4 or less cores. #### `foreground-read-bandwidth` New in v6.0.0 + The soft limit on the bandwidth with which transactions and the Coprocessor read data. -+ Default value: `0KB` (which means no limit) -+ Recommended setting: Use the default value `0` in most cases unless the `foreground-cpu-time` setting is not enough to limit the read bandwidth. For such an exception, it is recommended to set the value smaller than `20MB` in the instance with 4 or less cores. ++ Default value: `0KiB` (which means no limit) ++ Recommended setting: Use the default value `0` in most cases unless the `foreground-cpu-time` setting is not enough to limit the read bandwidth. For such an exception, it is recommended to set the value smaller than `20MiB` in the instance with 4 or less cores. ### Background Quota Limiter @@ -2301,7 +2301,7 @@ Suppose that your machine on which TiKV is deployed has limited resources, for e > This configuration item is returned in the result of `SHOW CONFIG`, but currently setting it does not take any effect. + The soft limit on the bandwidth with which background transactions write data. -+ Default value: `0KB` (which means no limit) ++ Default value: `0KiB` (which means no limit) #### `background-read-bandwidth` New in v6.2.0 @@ -2310,7 +2310,7 @@ Suppose that your machine on which TiKV is deployed has limited resources, for e > This configuration item is returned in the result of `SHOW CONFIG`, but currently setting it does not take any effect. + The soft limit on the bandwidth with which background transactions and the Coprocessor read data. -+ Default value: `0KB` (which means no limit) ++ Default value: `0KiB` (which means no limit) #### `enable-auto-tune` New in v6.2.0 @@ -2374,24 +2374,24 @@ Configuration items related to [Load Base Split](/configure-load-base-split.md). + Controls the traffic threshold at which a Region is identified as a hotspot. + Default value: - + `30MiB` per second when [`region-split-size`](#region-split-size) is less than 4 GB. - + `100MiB` per second when [`region-split-size`](#region-split-size) is greater than or equal to 4 GB. + + `30MiB` per second when [`region-split-size`](#region-split-size) is less than 4 GiB. + + `100MiB` per second when [`region-split-size`](#region-split-size) is greater than or equal to 4 GiB. ### `qps-threshold` + Controls the QPS threshold at which a Region is identified as a hotspot. + Default value: - + `3000` when [`region-split-size`](#region-split-size) is less than 4 GB. - + `7000` when [`region-split-size`](#region-split-size) is greater than or equal to 4 GB. + + `3000` when [`region-split-size`](#region-split-size) is less than 4 GiB. + + `7000` when [`region-split-size`](#region-split-size) is greater than or equal to 4 GiB. ### `region-cpu-overload-threshold-ratio` New in v6.2.0 + Controls the CPU usage threshold at which a Region is identified as a hotspot. + Default value: - + `0.25` when [`region-split-size`](#region-split-size) is less than 4 GB. - + `0.75` when [`region-split-size`](#region-split-size) is greater than or equal to 4 GB. + + `0.25` when [`region-split-size`](#region-split-size) is less than 4 GiB. + + `0.75` when [`region-split-size`](#region-split-size) is greater than or equal to 4 GiB. ## memory New in v7.5.0 @@ -2403,4 +2403,4 @@ Configuration items related to [Load Base Split](/configure-load-base-split.md). ### `profiling-sample-per-bytes` New in v7.5.0 + Specifies the amount of data sampled by Heap Profiling each time, rounding up to the nearest power of 2. -+ Default value: `512KB` ++ Default value: `512KiB` From be6ebe55feb975cae1a76811fca3b6fbf32cff51 Mon Sep 17 00:00:00 2001 From: Weizhen Wang Date: Tue, 19 Mar 2024 09:36:42 +0800 Subject: [PATCH 39/82] *: add tidb_opt_use_invisible_indexes (#16762) --- sql-statements/sql-statement-alter-index.md | 3 +-- sql-statements/sql-statement-create-index.md | 4 +++- system-variables.md | 8 ++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/sql-statements/sql-statement-alter-index.md b/sql-statements/sql-statement-alter-index.md index 3224a68dfaa8a..f729fb3ef24d7 100644 --- a/sql-statements/sql-statement-alter-index.md +++ b/sql-statements/sql-statement-alter-index.md @@ -6,7 +6,7 @@ aliases: ['/docs/dev/sql-statements/sql-statement-alter-index/'] # ALTER INDEX -The `ALTER INDEX` statement is used to modify the visibility of the index to `Visible` or `Invisible`. Invisible indexes are maintained by DML statements, but will not be used by the query optimizer. This is useful in scenarios where you want to double-check before removing an index permanently. +The `ALTER INDEX` statement is used to modify the visibility of the index to `Visible` or `Invisible`. Invisible indexes are maintained by DML statements, but will not be used by the query optimizer. This is useful in scenarios where you want to double-check before removing an index permanently. Starting from TiDB v8.0.0, you can make the optimizer select invisible indexes by modifying the system variable [`tidb_opt_use_invisible_indexes`](/system-variables.md#tidb_opt_use_invisible_indexes-new-in-v800). ## Synopsis @@ -119,7 +119,6 @@ Query OK, 0 rows affected (0.02 sec) * Invisible indexes in TiDB are modeled on the equivalent feature from MySQL 8.0. * Similiar to MySQL, TiDB does not permit `PRIMARY KEY` indexes to be made invisible. -* MySQL provides an optimizer switch `use_invisible_indexes=on` to make all invisible indexes _visible_ again. This functionality is not available in TiDB. ## See also diff --git a/sql-statements/sql-statement-create-index.md b/sql-statements/sql-statement-create-index.md index 5749fe1efffce..39d8775e86d4b 100644 --- a/sql-statements/sql-statement-create-index.md +++ b/sql-statements/sql-statement-create-index.md @@ -347,13 +347,15 @@ See [Index Selection - Use multi-valued indexes](/choose-index.md#use-multi-valu ## Invisible index -Invisible indexes are indexes that are ignored by the query optimizer: +By default, invisible indexes are indexes that are ignored by the query optimizer: ```sql CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE(c2)); CREATE UNIQUE INDEX c1 ON t1 (c1) INVISIBLE; ``` +Starting from TiDB v8.0.0, you can make the optimizer select invisible indexes by modifying the system variable [`tidb_opt_use_invisible_indexes`](/system-variables.md#tidb_opt_use_invisible_indexes-new-in-v800). + For details, see [`ALTER INDEX`](/sql-statements/sql-statement-alter-index.md). ## Associated system variables diff --git a/system-variables.md b/system-variables.md index e9013c43dc510..02ff00c67ca99 100644 --- a/system-variables.md +++ b/system-variables.md @@ -4493,6 +4493,14 @@ SHOW WARNINGS; - Default value: `24.0` - Indicates the concurrency number of TiFlash computation. This variable is internally used in the Cost Model, and it is NOT recommended to modify its value. +### tidb_opt_use_invisible_indexes New in v8.0.0 + +- Scope: SESSION +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes +- Type: Boolean +- Default value: `OFF` +- This variable controls whether the optimizer can select [invisible indexes](/sql-statements/sql-statement-create-index.md#invisible-index) for query optimization in the current session. Invisible indexes are maintained by DML statements, but will not be used by the query optimizer. This is useful in scenarios where you want to double-check before removing an index permanently. When the variable is set to `ON`, the optimizer can select invisible indexes for query optimization in the session. + ### tidb_opt_write_row_id > **Note:** From 6cd81683295db9ed54b40b40c6f8ad97f17320bc Mon Sep 17 00:00:00 2001 From: Aolin Date: Tue, 19 Mar 2024 09:44:13 +0800 Subject: [PATCH 40/82] Update tiflash support pushdown func list to add cast decimal as double (#16641) --- tiflash/tiflash-supported-pushdown-calculations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiflash/tiflash-supported-pushdown-calculations.md b/tiflash/tiflash-supported-pushdown-calculations.md index 0374ccdd64ca2..0e8f552411449 100644 --- a/tiflash/tiflash-supported-pushdown-calculations.md +++ b/tiflash/tiflash-supported-pushdown-calculations.md @@ -42,7 +42,7 @@ TiFlash supports the following push-down expressions: | [Regular expression functions and operators](/functions-and-operators/string-functions.md) | `REGEXP`, `REGEXP_LIKE()`, `REGEXP_INSTR()`, `REGEXP_SUBSTR()`, `REGEXP_REPLACE()`, `RLIKE` | | [Date functions](/functions-and-operators/date-and-time-functions.md) | `DATE_FORMAT()`, `TIMESTAMPDIFF()`, `FROM_UNIXTIME()`, `UNIX_TIMESTAMP(int)`, `UNIX_TIMESTAMP(decimal)`, `STR_TO_DATE(date)`, `STR_TO_DATE(datetime)`, `DATEDIFF()`, `YEAR()`, `MONTH()`, `DAY()`, `EXTRACT(datetime)`, `DATE()`, `HOUR()`, `MICROSECOND()`, `MINUTE()`, `SECOND()`, `SYSDATE()`, `DATE_ADD/ADDDATE(datetime, int)`, `DATE_ADD/ADDDATE(string, int/real)`, `DATE_SUB/SUBDATE(datetime, int)`, `DATE_SUB/SUBDATE(string, int/real)`, `QUARTER()`, `DAYNAME()`, `DAYOFMONTH()`, `DAYOFWEEK()`, `DAYOFYEAR()`, `LAST_DAY()`, `MONTHNAME()`, `TO_SECONDS()`, `TO_DAYS()`, `FROM_DAYS()`, `WEEKOFYEAR()` | | [JSON function](/functions-and-operators/json-functions.md) | `JSON_LENGTH()`, `->`, `->>`, `JSON_EXTRACT()`, `JSON_ARRAY()`, `JSON_DEPTH()`, `JSON_VALID()`, `JSON_KEYS()`, `JSON_CONTAINS_PATH()`, `JSON_UNQUOTE()` | -| [Conversion functions](/functions-and-operators/cast-functions-and-operators.md) | `CAST(int AS DOUBLE), CAST(int AS DECIMAL)`, `CAST(int AS STRING)`, `CAST(int AS TIME)`, `CAST(double AS INT)`, `CAST(double AS DECIMAL)`, `CAST(double AS STRING)`, `CAST(double AS TIME)`, `CAST(string AS INT)`, `CAST(string AS DOUBLE), CAST(string AS DECIMAL)`, `CAST(string AS TIME)`, `CAST(decimal AS INT)`, `CAST(decimal AS STRING)`, `CAST(decimal AS TIME)`, `CAST(time AS INT)`, `CAST(time AS DECIMAL)`, `CAST(time AS STRING)`, `CAST(time AS REAL)`, `CAST(json AS JSON)`, `CAST(json AS STRING)`, `CAST(int AS JSON)`, `CAST(real AS JSON)`, `CAST(decimal AS JSON)`, `CAST(string AS JSON)`, `CAST(time AS JSON)`, `CAST(duration AS JSON)` | +| [Conversion functions](/functions-and-operators/cast-functions-and-operators.md) | `CAST(int AS DOUBLE), CAST(int AS DECIMAL)`, `CAST(int AS STRING)`, `CAST(int AS TIME)`, `CAST(double AS INT)`, `CAST(double AS DECIMAL)`, `CAST(double AS STRING)`, `CAST(double AS TIME)`, `CAST(string AS INT)`, `CAST(string AS DOUBLE), CAST(string AS DECIMAL)`, `CAST(string AS TIME)`, `CAST(decimal AS INT)`, `CAST(decimal AS STRING)`, `CAST(decimal AS TIME)`, `CAST(decimal AS DOUBLE)`, `CAST(time AS INT)`, `CAST(time AS DECIMAL)`, `CAST(time AS STRING)`, `CAST(time AS REAL)`, `CAST(json AS JSON)`, `CAST(json AS STRING)`, `CAST(int AS JSON)`, `CAST(real AS JSON)`, `CAST(decimal AS JSON)`, `CAST(string AS JSON)`, `CAST(time AS JSON)`, `CAST(duration AS JSON)` | | [Aggregate functions](/functions-and-operators/aggregate-group-by-functions.md) | `MIN()`, `MAX()`, `SUM()`, `COUNT()`, `AVG()`, `APPROX_COUNT_DISTINCT()`, `GROUP_CONCAT()` | | [Miscellaneous functions](/functions-and-operators/miscellaneous-functions.md) | `INET_NTOA()`, `INET_ATON()`, `INET6_NTOA()`, `INET6_ATON()` | From 1ea1a6c2eefa88d3a0af4bcca4118cfabd491760 Mon Sep 17 00:00:00 2001 From: Aolin Date: Tue, 19 Mar 2024 09:48:43 +0800 Subject: [PATCH 41/82] update tiflash function pushdown list to add power (#16640) --- tiflash/tiflash-supported-pushdown-calculations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiflash/tiflash-supported-pushdown-calculations.md b/tiflash/tiflash-supported-pushdown-calculations.md index 0e8f552411449..f35b41478c95b 100644 --- a/tiflash/tiflash-supported-pushdown-calculations.md +++ b/tiflash/tiflash-supported-pushdown-calculations.md @@ -35,7 +35,7 @@ TiFlash supports the following push-down expressions: | Expression Type | Operations | | :-------------- | :------------------------------------- | -| [Numeric functions and operators](/functions-and-operators/numeric-functions-and-operators.md) | `+`, `-`, `/`, `*`, `%`, `>=`, `<=`, `=`, `!=`, `<`, `>`, `ROUND()`, `ABS()`, `FLOOR(int)`, `CEIL(int)`, `CEILING(int)`, `SQRT()`, `LOG()`, `LOG2()`, `LOG10()`, `LN()`, `EXP()`, `POW()`, `SIGN()`, `RADIANS()`, `DEGREES()`, `CONV()`, `CRC32()`, `GREATEST(int/real)`, `LEAST(int/real)` | +| [Numeric functions and operators](/functions-and-operators/numeric-functions-and-operators.md) | `+`, `-`, `/`, `*`, `%`, `>=`, `<=`, `=`, `!=`, `<`, `>`, `ROUND()`, `ABS()`, `FLOOR(int)`, `CEIL(int)`, `CEILING(int)`, `SQRT()`, `LOG()`, `LOG2()`, `LOG10()`, `LN()`, `EXP()`, `POW()`, `POWER()`, `SIGN()`, `RADIANS()`, `DEGREES()`, `CONV()`, `CRC32()`, `GREATEST(int/real)`, `LEAST(int/real)` | | [Logical functions](/functions-and-operators/control-flow-functions.md) and [operators](/functions-and-operators/operators.md) | `AND`, `OR`, `NOT`, `CASE WHEN`, `IF()`, `IFNULL()`, `ISNULL()`, `IN`, `LIKE`, `ILIKE`, `COALESCE`, `IS` | | [Bitwise operations](/functions-and-operators/bit-functions-and-operators.md) | `&` (bitand), \| (bitor), `~` (bitneg), `^` (bitxor) | | [String functions](/functions-and-operators/string-functions.md) | `SUBSTR()`, `CHAR_LENGTH()`, `REPLACE()`, `CONCAT()`, `CONCAT_WS()`, `LEFT()`, `RIGHT()`, `ASCII()`, `LENGTH()`, `TRIM()`, `LTRIM()`, `RTRIM()`, `POSITION()`, `FORMAT()`, `LOWER()`, `UCASE()`, `UPPER()`, `SUBSTRING_INDEX()`, `LPAD()`, `RPAD()`, `STRCMP()` | From 5bacb0d78e9d8ea342d47f858d6e104f0c8fefce Mon Sep 17 00:00:00 2001 From: YangKeao Date: Tue, 19 Mar 2024 09:53:14 +0800 Subject: [PATCH 42/82] Add documents for `information_schema.tidb_index_usage` and `sys.schema_unused_index`. (#16446) --- TOC-tidb-cloud.md | 1 + TOC.md | 2 + .../information-schema-tidb-index-usage.md | 103 ++++++++++++++++++ information-schema/information-schema.md | 3 + sys-schema.md | 54 +++++++++ system-variables.md | 2 +- tidb-configuration-file.md | 2 +- 7 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 information-schema/information-schema-tidb-index-usage.md create mode 100644 sys-schema.md diff --git a/TOC-tidb-cloud.md b/TOC-tidb-cloud.md index 1dbb4039cdf8f..5c46152b16969 100644 --- a/TOC-tidb-cloud.md +++ b/TOC-tidb-cloud.md @@ -585,6 +585,7 @@ - [`TABLE_STORAGE_STATS`](/information-schema/information-schema-table-storage-stats.md) - [`TIDB_HOT_REGIONS_HISTORY`](/information-schema/information-schema-tidb-hot-regions-history.md) - [`TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) + - [`TIDB_INDEX_USAGE`](/information-schema/information-schema-tidb-index-usage.md) - [`TIDB_SERVERS_INFO`](/information-schema/information-schema-tidb-servers-info.md) - [`TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) - [`TIFLASH_REPLICA`](/information-schema/information-schema-tiflash-replica.md) diff --git a/TOC.md b/TOC.md index 416cf6c99bba4..c7a167155b701 100644 --- a/TOC.md +++ b/TOC.md @@ -960,6 +960,7 @@ - [`TIDB_HOT_REGIONS`](/information-schema/information-schema-tidb-hot-regions.md) - [`TIDB_HOT_REGIONS_HISTORY`](/information-schema/information-schema-tidb-hot-regions-history.md) - [`TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) + - [`TIDB_INDEX_USAGE`](/information-schema/information-schema-tidb-index-usage.md) - [`TIDB_SERVERS_INFO`](/information-schema/information-schema-tidb-servers-info.md) - [`TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) - [`TIFLASH_REPLICA`](/information-schema/information-schema-tiflash-replica.md) @@ -976,6 +977,7 @@ - PERFORMANCE_SCHEMA - [Overview](/performance-schema/performance-schema.md) - [`SESSION_CONNECT_ATTRS`](/performance-schema/performance-schema-session-connect-attrs.md) + - [`SYS`](/sys-schema.md) - [Metadata Lock](/metadata-lock.md) - [TiDB DDL V2](/ddl-v2.md) - UI diff --git a/information-schema/information-schema-tidb-index-usage.md b/information-schema/information-schema-tidb-index-usage.md new file mode 100644 index 0000000000000..00e57aa9cd906 --- /dev/null +++ b/information-schema/information-schema-tidb-index-usage.md @@ -0,0 +1,103 @@ +--- +title: TIDB_INDEX_USAGE +summary: Learn the `TIDB_INDEX_USAGE` INFORMATION_SCHEMA table. +--- + +# TIDB_INDEX_USAGE + + + +Starting from v8.0.0, TiDB provides the `TIDB_INDEX_USAGE` table. You can use `TIDB_INDEX_USAGE` to get the usage statistics of all indexes on the current TiDB node. By default, TiDB collects these index usage statistics during SQL statement execution. You can disable this feature by turning off the [`instance.tidb_enable_collect_execution_info`](/tidb-configuration-file.md#tidb_enable_collect_execution_info) configuration item or the [`tidb_enable_collect_execution_info`](/system-variables.md#tidb_enable_collect_execution_info) system variable. + + + + + +Starting from v8.0.0, TiDB provides the `TIDB_INDEX_USAGE` table. You can use `TIDB_INDEX_USAGE` to get the usage statistics of all indexes on the current TiDB node. By default, TiDB collects these index usage statistics during SQL statement execution. You can disable this feature by turning off the [`instance.tidb_enable_collect_execution_info`](https://docs.pingcap.com/tidb/v8.0/tidb-configuration-file#tidb_enable_collect_execution_info) configuration item or the [`tidb_enable_collect_execution_info`](/system-variables.md#tidb_enable_collect_execution_info) system variable. + + + +```sql +USE INFORMATION_SCHEMA; +DESC TIDB_INDEX_USAGE; +``` + +```sql ++--------------------------+-------------+------+------+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++--------------------------+-------------+------+------+---------+-------+ +| TABLE_SCHEMA | varchar(64) | YES | | NULL | | +| TABLE_NAME | varchar(64) | YES | | NULL | | +| INDEX_NAME | varchar(64) | YES | | NULL | | +| QUERY_TOTAL | bigint(21) | YES | | NULL | | +| KV_REQ_TOTAL | bigint(21) | YES | | NULL | | +| ROWS_ACCESS_TOTAL | bigint(21) | YES | | NULL | | +| PERCENTAGE_ACCESS_0 | bigint(21) | YES | | NULL | | +| PERCENTAGE_ACCESS_0_1 | bigint(21) | YES | | NULL | | +| PERCENTAGE_ACCESS_1_10 | bigint(21) | YES | | NULL | | +| PERCENTAGE_ACCESS_10_20 | bigint(21) | YES | | NULL | | +| PERCENTAGE_ACCESS_20_50 | bigint(21) | YES | | NULL | | +| PERCENTAGE_ACCESS_50_100 | bigint(21) | YES | | NULL | | +| PERCENTAGE_ACCESS_100 | bigint(21) | YES | | NULL | | +| LAST_ACCESS_TIME | datetime | YES | | NULL | | ++--------------------------+-------------+------+------+---------+-------+ +14 rows in set (0.00 sec) +``` + +The columns in the `TIDB_INDEX_USAGE` table are as follows: + +* `TABLE_SCHEMA`: The name of the database to which the table containing the index belongs. +* `TABLE_NAME`: The name of the table containing the index. +* `INDEX_NAME`: The name of the index. +* `QUERY_TOTAL`: The total number of statements accessing the index. +* `KV_REQ_TOTAL`: The total number of KV requests generated when accessing the index. +* `ROWS_ACCESS_TOTAL`: The total number of rows scanned when accessing the index. +* `PERCENTAGE_ACCESS_0`: The number of times the row access ratio (the percentage of accessed rows out of the total number of rows in the table) is 0. +* `PERCENTAGE_ACCESS_0_1`: The number of times the row access ratio is between 0% and 1%. +* `PERCENTAGE_ACCESS_1_10`: The number of times the row access ratio is between 1% and 10%. +* `PERCENTAGE_ACCESS_10_20`: The number of times the row access ratio is between 10% and 20%. +* `PERCENTAGE_ACCESS_20_50`: The number of times the row access ratio is between 20% and 50%. +* `PERCENTAGE_ACCESS_50_100`: The number of times the row access ratio is between 50% and 100%. +* `PERCENTAGE_ACCESS_100`: The number of times the row access ratio is 100%. +* `LAST_ACCESS_TIME`: The time of the most recent access to the index. + +## CLUSTER_TIDB_INDEX_USAGE + +The `TIDB_INDEX_USAGE` table only provides usage statistics of all indexes on a single TiDB node. To obtain the index usage statistics on all TiDB nodes in the cluster, you need to query the `CLUSTER_TIDB_INDEX_USAGE` table. + +Compared with the `TIDB_INDEX_USAGE` table, the query result of the `CLUSTER_TIDB_INDEX_USAGE` table includes an additional `INSTANCE` field. This field displays the IP address and port of each node in the cluster, which helps you distinguish the statistics across different nodes. + +```sql +USE INFORMATION_SCHEMA; +DESC CLUSTER_TIDB_INDEX_USAGE; +``` + +The output is as follows: + +```sql ++-------------------------+-----------------------------------------------------------------+------+------+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++-------------------------+-----------------------------------------------------------------+------+------+---------+-------+ +| INSTANCE | varchar(64) | YES | | NULL | | +| ID | bigint(21) unsigned | NO | PRI | NULL | | +| START_TIME | timestamp(6) | YES | | NULL | | +| CURRENT_SQL_DIGEST | varchar(64) | YES | | NULL | | +| CURRENT_SQL_DIGEST_TEXT | text | YES | | NULL | | +| STATE | enum('Idle','Running','LockWaiting','Committing','RollingBack') | YES | | NULL | | +| WAITING_START_TIME | timestamp(6) | YES | | NULL | | +| MEM_BUFFER_KEYS | bigint(64) | YES | | NULL | | +| MEM_BUFFER_BYTES | bigint(64) | YES | | NULL | | +| SESSION_ID | bigint(21) unsigned | YES | | NULL | | +| USER | varchar(16) | YES | | NULL | | +| DB | varchar(64) | YES | | NULL | | +| ALL_SQL_DIGESTS | text | YES | | NULL | | +| RELATED_TABLE_IDS | text | YES | | NULL | | +| WAITING_TIME | double | YES | | NULL | | ++-------------------------+-----------------------------------------------------------------+------+------+---------+-------+ +15 rows in set (0.00 sec) +``` + +## Limitations + +- The data in the `TIDB_INDEX_USAGE` table might be delayed by up to 5 minutes. +- After TiDB restarts, the data in the `TIDB_INDEX_USAGE` table is cleared. diff --git a/information-schema/information-schema.md b/information-schema/information-schema.md index 9afd5684c5624..ac9b22bca1a52 100644 --- a/information-schema/information-schema.md +++ b/information-schema/information-schema.md @@ -123,6 +123,7 @@ Many `INFORMATION_SCHEMA` tables have a corresponding `SHOW` command. The benefi | `CLUSTER_SLOW_QUERY` | Provides a cluster-level view of the `SLOW_QUERY` table. This table is not available on [TiDB Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-serverless) clusters. | | `CLUSTER_STATEMENTS_SUMMARY` | Provides a cluster-level view of the `STATEMENTS_SUMMARY` table. This table is not available on [TiDB Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-serverless) clusters. | | `CLUSTER_STATEMENTS_SUMMARY_HISTORY` | Provides a cluster-level view of the `STATEMENTS_SUMMARY_HISTORY` table. This table is not available on [TiDB Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-serverless) clusters. | +| `CLUSTER_TIDB_INDEX_USAGE` | Provides a cluster-level view of the `TIDB_INDEX_USAGE` table. | | `CLUSTER_TIDB_TRX` | Provides a cluster-level view of the `TIDB_TRX` table. | | [`CLUSTER_SYSTEMINFO`](/information-schema/information-schema-cluster-systeminfo.md) | Provides details about kernel parameter configuration for servers in the cluster. This table is not applicable to TiDB Cloud. | | [`DATA_LOCK_WAITS`](/information-schema/information-schema-data-lock-waits.md) | Provides the lock-waiting information on the TiKV server. | @@ -145,6 +146,7 @@ Many `INFORMATION_SCHEMA` tables have a corresponding `SHOW` command. The benefi | [`TIDB_HOT_REGIONS`](/information-schema/information-schema-tidb-hot-regions.md) | Provides statistics about which regions are hot. | | [`TIDB_HOT_REGIONS_HISTORY`](/information-schema/information-schema-tidb-hot-regions-history.md) | Provides history statistics about which Regions are hot. | | [`TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) | Provides index information about TiDB tables. | +| [`TIDB_INDEX_USAGE`](/information-schema/information-schema-tidb-index-usage.md) | Provides the information of the index usage statistics on the TiDB node. | | [`TIDB_SERVERS_INFO`](/information-schema/information-schema-tidb-servers-info.md) | Provides a list of TiDB servers (namely, tidb-server component) | | [`TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) | Provides the information of the transactions that are being executed on the TiDB node. | | [`TIFLASH_REPLICA`](/information-schema/information-schema-tiflash-replica.md) | Provides details about TiFlash replicas. | @@ -196,6 +198,7 @@ Many `INFORMATION_SCHEMA` tables have a corresponding `SHOW` command. The benefi | [`TIDB_HOT_REGIONS`](https://docs.pingcap.com/tidb/stable/information-schema-tidb-hot-regions) | Provides statistics about which regions are hot. This table is not applicable to TiDB Cloud. | | [`TIDB_HOT_REGIONS_HISTORY`](/information-schema/information-schema-tidb-hot-regions-history.md) | Provides history statistics about which Regions are hot. | | [`TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) | Provides index information about TiDB tables. | +| [`TIDB_INDEX_USAGE`](/information-schema/information-schema-tidb-index-usage.md) | Provides the information of the index usage statistics on the TiDB node. | | [`TIDB_SERVERS_INFO`](/information-schema/information-schema-tidb-servers-info.md) | Provides a list of TiDB servers (namely, tidb-server component) | | [`TIDB_TRX`](/information-schema/information-schema-tidb-trx.md) | Provides the information of the transactions that are being executed on the TiDB node. | | [`TIFLASH_REPLICA`](/information-schema/information-schema-tiflash-replica.md) | Provides details about TiFlash replicas. | diff --git a/sys-schema.md b/sys-schema.md new file mode 100644 index 0000000000000..4c3beda035e2a --- /dev/null +++ b/sys-schema.md @@ -0,0 +1,54 @@ +--- +title: sys Schema +summary: Learn about the system tables in the `sys` schema. +--- + +# `sys` Schema + +Starting from v8.0.0, TiDB provides the `sys` schema. You can use the views in `sys` schema to understand the data in the system tables, [`INFORMATION_SCHEMA`](/information-schema/information-schema.md), and [`PERFORMANCE SCHEMA`](/performance-schema/performance-schema.md) of TiDB. + +## Manually create the `sys` schema and views + +For clusters upgraded from versions earlier than v8.0.0, the `sys` schema and the views in it are not created automatically. You can manually create them using the following SQL statements: + +```sql +CREATE DATABASE IF NOT EXISTS sys; +CREATE OR REPLACE VIEW sys.schema_unused_indexes AS + SELECT + table_schema as object_schema, + table_name as object_name, + index_name + FROM information_schema.cluster_tidb_index_usage + WHERE + table_schema not in ('sys', 'mysql', 'INFORMATION_SCHEMA', 'PERFORMANCE_SCHEMA') and + index_name != 'PRIMARY' + GROUP BY table_schema, table_name, index_name + HAVING + sum(last_access_time) is null; +``` + +## `schema_unused_index` + +`schema_unused_index` records indexes that have not been used since the last start of TiDB. It includes the following columns: + +- `OBJECT_SCHEMA`: The name of the database to which the table containing the index belongs. +- `OBJECT_NAME`: The name of the table containing the index. +- `INDEX_NAME`: The name of the index. + +```sql +USE SYS; +DESC SCHEMA_UNUSED_INDEXES; +``` + +The output is as follows: + +```sql ++---------------+-------------+------+------+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++---------------+-------------+------+------+---------+-------+ +| object_schema | varchar(64) | YES | | NULL | | +| object_name | varchar(64) | YES | | NULL | | +| index_name | varchar(64) | YES | | NULL | | ++---------------+-------------+------+------+---------+-------+ +3 rows in set (0.00 sec) +``` \ No newline at end of file diff --git a/system-variables.md b/system-variables.md index 02ff00c67ca99..7e11470b1f90c 100644 --- a/system-variables.md +++ b/system-variables.md @@ -1951,7 +1951,7 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; - Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No - Type: Boolean - Default value: `ON` -- This variable controls whether to record the execution information of each operator in the slow query log. +- This variable controls whether to record the execution information of each operator in the slow query log and whether to record the [usage statistics of indexes](/information-schema/information-schema-tidb-index-usage.md). ### tidb_enable_column_tracking New in v5.4.0 diff --git a/tidb-configuration-file.md b/tidb-configuration-file.md index c2101b164902b..22d205089d648 100644 --- a/tidb-configuration-file.md +++ b/tidb-configuration-file.md @@ -849,7 +849,7 @@ Configuration items related to read isolation. ### `tidb_enable_collect_execution_info` -- This configuration controls whether to record the execution information of each operator in the slow query log. +- This configuration controls whether to record the execution information of each operator in the slow query log and whether to record the [usage statistics of indexes](/information-schema/information-schema-tidb-index-usage.md). - Default value: `true` - Before v6.1.0, this configuration is set by `enable-collect-execution-info`. From cb1c65a8a7f2328cc46e63662645cae26a9f78eb Mon Sep 17 00:00:00 2001 From: xixirangrang Date: Tue, 19 Mar 2024 10:14:13 +0800 Subject: [PATCH 43/82] *: add data type default values (#16693) --- data-type-default-values.md | 41 ++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/data-type-default-values.md b/data-type-default-values.md index be1e547958f85..7ac7fa12a2188 100644 --- a/data-type-default-values.md +++ b/data-type-default-values.md @@ -8,7 +8,7 @@ aliases: ['/docs/dev/data-type-default-values/','/docs/dev/reference/sql/data-ty The `DEFAULT` value clause in a data type specification indicates a default value for a column. The default value must be a constant and cannot be a function or an expression. But for the time type, you can specify the `NOW`, `CURRENT_TIMESTAMP`, `LOCALTIME`, and `LOCALTIMESTAMP` functions as the default for `TIMESTAMP` and `DATETIME` columns. -The `BLOB`, `TEXT`, and `JSON` columns __cannot__ be assigned a default value. +Starting from v8.0.0, TiDB supports [specifying expressions as default values](#specify-expressions-as-default-values) for [`BLOB`](/data-type-string.md#blob-type), [`TEXT`](/data-type-string.md#text-type), and [`JSON`](/data-type-json.md#json-type) data types. If a column definition includes no explicit `DEFAULT` value, TiDB determines the default value as follows: @@ -25,3 +25,42 @@ Implicit defaults are defined as follows: - For numeric types, the default is 0. If declared with the `AUTO_INCREMENT` attribute, the default is the next value in the sequence. - For date and time types other than `TIMESTAMP`, the default is the appropriate "zero" value for the type. For `TIMESTAMP`, the default value is the current date and time. - For string types other than `ENUM`, the default value is the empty string. For `ENUM`, the default is the first enumeration value. + +## Specify expressions as default values + +> **Warning:** +> +> Currently, this feature is experimental. It is not recommended that you use it in production environments. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub. + +Starting from 8.0.13, MySQL supports specifying expressions as default values in the `DEFAULT` clause. For more information, see [Explicit default handling as of MySQL 8.0.13](https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html#data-type-defaults-explicit). + +TiDB has implemented this feature and supports specifying some expressions as default values in the `DEFAULT` clause. Starting from v8.0.0, TiDB supports assigning default values to `BLOB`, `TEXT`, and `JSON` data types. However, these default values can only be set as expressions. The following is an example of `BLOB`: + +```sql +CREATE TABLE t2 (b BLOB DEFAULT (RAND())); +``` + +TiDB currently supports the following expressions: + +* [`RAND()`](/functions-and-operators/numeric-functions-and-operators.md) +* [`UUID()`](/functions-and-operators/miscellaneous-functions.md) +* [`UUID_TO_BIN()`](/functions-and-operators/miscellaneous-functions.md) + +Starting from TiDB v8.0.0, the `DEFAULT` clause supports using the following expressions to set default values. + +* `UPPER(SUBSTRING_INDEX(USER(), '@', 1))` + +* `REPLACE(UPPER(UUID()), '-', '')` + +* The `DATE_FORMAT` supports the following formats: + + * `DATE_FORMAT(NOW(), '%Y-%m')` + * `DATE_FORMAT(NOW(), '%Y-%m-%d')` + * `DATE_FORMAT(NOW(), '%Y-%m-%d %H.%i.%s')` + * `DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')` + +* `STR_TO_DATE('1980-01-01', '%Y-%m-%d')` + +> **Note:** +> +> Currently, the `ADD COLUMN` statement does not support using expressions as default values. From 3b530bfef8cf185545c6b210b677bb993ece2952 Mon Sep 17 00:00:00 2001 From: Aolin Date: Tue, 19 Mar 2024 10:32:13 +0800 Subject: [PATCH 44/82] tiproxy: update performance test and metrics (#16694) --- tiproxy/tiproxy-grafana.md | 8 ++ tiproxy/tiproxy-overview.md | 17 ++- tiproxy/tiproxy-performance-test.md | 209 ++++++++++++++++++---------- 3 files changed, 156 insertions(+), 78 deletions(-) diff --git a/tiproxy/tiproxy-grafana.md b/tiproxy/tiproxy-grafana.md index 0d77836e7d694..8339349dfe150 100644 --- a/tiproxy/tiproxy-grafana.md +++ b/tiproxy/tiproxy-grafana.md @@ -47,6 +47,7 @@ TiProxy has four panel groups. The metrics on these panels indicate the current - CPS by Instance: command per second of each TiProxy instance - CPS by Backend: command per second of each TiDB instance - CPS by CMD: command per second grouped by SQL command type +- Handshake Duration: average, P95, and P99 duration of the handshake phase between the client and TiProxy ## Balance @@ -59,3 +60,10 @@ TiProxy has four panel groups. The metrics on these panels indicate the current - Get Backend Duration: the average, p95, p99 duration of TiProxy connecting to a TiDB instance - Ping Backend Duration: the network latency between each TiProxy instance and each TiProxy instance. For example, `10.24.31.1:6000 | 10.24.31.2:4000` indicates the network latency between TiProxy instance `10.24.31.1:6000` and TiDB instance `10.24.31.2:4000` - Health Check Cycle: the duration of a cycle of the health check between a TiProxy instance and all TiDB instances. For example, `10.24.31.1:6000` indicates the duration of the latest health check that TiProxy instance `10.24.31.1:6000` executes on all the TiDB instances. If this duration is higher than 3 seconds, TiProxy may not be timely to refresh the backend TiDB list + +## Traffic + +- Bytes/Second from Backends: the amount of data, in bytes, sent from each TiDB instance to each TiProxy instance per second. +- Packets/Second from Backends: the number of MySQL packets sent from each TiDB instance to each TiProxy instance per second. +- Bytes/Second to Backends: the amount of data, in bytes, sent from each TiProxy instance to each TiDB instance per second. +- Packets/Second to Backends: the number of MySQL packets sent from each TiProxy instance to each TiDB instance per second. diff --git a/tiproxy/tiproxy-overview.md b/tiproxy/tiproxy-overview.md index c67f44c6798a9..04446fcde5138 100644 --- a/tiproxy/tiproxy-overview.md +++ b/tiproxy/tiproxy-overview.md @@ -11,7 +11,7 @@ TiProxy is an optional component. You can also use a third-party proxy component The following figure shows the architecture of TiProxy: -![TiProxy architecture](/media/tiproxy/tiproxy-architecture.png) +TiProxy architecture ## Main features @@ -23,7 +23,7 @@ TiProxy can migrate connections from one TiDB server to another without breaking As shown in the following figure, the client originally connects to TiDB 1 through TiProxy. After the connection migration, the client actually connects to TiDB 2. When TiDB 1 is about to be offline or the ratio of connections on TiDB 1 to connections on TiDB 2 exceeds the set threshold, the connection migration is triggered. The client is unaware of the connection migration. -![TiProxy connection migration](/media/tiproxy/tiproxy-session-migration.png) +TiProxy connection migration Connection migration usually occurs in the following scenarios: @@ -59,7 +59,7 @@ This section describes how to deploy and change TiProxy using TiUP. For how to d ### Deploy TiProxy -1. Generate a self-signed certificate. +1. Before TiUP v1.15.0, you need to manually generate a self-signed certificate. Generate a self-signed certificate for the TiDB instance and place the certificate on all TiDB instances to ensure that all TiDB instances have the same certificate. For detailed steps, see [Generate self-signed certificates](/generate-self-signed-certificates.md). @@ -67,8 +67,8 @@ This section describes how to deploy and change TiProxy using TiUP. For how to d When using TiProxy, you also need to configure the following items for the TiDB instances: - - Configure the [`security.session-token-signing-cert`](/tidb-configuration-file.md#session-token-signing-cert-new-in-v640) and [`security.session-token-signing-key`](/tidb-configuration-file.md#session-token-signing-key-new-in-v640) of TiDB instances to the path of the certificate. Otherwise, the connection cannot be migrated. - - Configure the [`graceful-wait-before-shutdown`](/tidb-configuration-file.md#graceful-wait-before-shutdown-new-in-v50) of TiDB instances to a value greater than the longest transaction duration of the application. Otherwise, the client might disconnect when the TiDB server is offline. For details, see [TiProxy usage limitations](#limitations). + - Before TiUP v1.15.0, configure the [`security.session-token-signing-cert`](/tidb-configuration-file.md#session-token-signing-cert-new-in-v640) and [`security.session-token-signing-key`](/tidb-configuration-file.md#session-token-signing-key-new-in-v640) of TiDB instances to the path of the certificate. Otherwise, the connection cannot be migrated. + - Configure the [`graceful-wait-before-shutdown`](/tidb-configuration-file.md#graceful-wait-before-shutdown-new-in-v50) of TiDB instances to a value greater than the longest transaction duration of the application. Otherwise, the client might disconnect when the TiDB server is offline. You can view the transaction duration through the [Transaction metrics on the TiDB monitoring dashboard](/grafana-tidb-dashboard.md#transaction). For details, see [TiProxy usage limitations](#limitations). A configuration example is as follows: @@ -100,7 +100,7 @@ This section describes how to deploy and change TiProxy using TiUP. For how to d ```yaml component_versions: - tiproxy: "v0.2.0" + tiproxy: "v1.0.0" server_configs: tiproxy: security.server-tls.ca: "/var/ssl/ca.pem" @@ -202,3 +202,8 @@ The following table lists some supported connectors: | Python | PyMySQL | 0.7 | Note that some connectors call the common library to connect to the database, and these connectors are not listed in the table. You can refer to the above table for the required version of the corresponding library. For example, MySQL/Ruby uses libmysqlclient to connect to the database, so it requires that the libmysqlclient used by MySQL/Ruby is version 5.5.7 or later. + +## TiProxy resources + +- [TiProxy Release Notes](https://github.com/pingcap/tiproxy/releases) +- [TiProxy Issues](https://github.com/pingcap/tiup/issues): Lists TiProxy GitHub issues diff --git a/tiproxy/tiproxy-performance-test.md b/tiproxy/tiproxy-performance-test.md index 90b3c648cfee3..7cc0992afd228 100644 --- a/tiproxy/tiproxy-performance-test.md +++ b/tiproxy/tiproxy-performance-test.md @@ -9,33 +9,34 @@ This report tests the performance of TiProxy in the OLTP scenario of Sysbench an The results are as follows: -- The QPS upper limit of TiProxy is affected by the type of workload. Under the basic workloads of Sysbench and the same CPU usage, the QPS of TiProxy is about 20% to 40% lower than that of HAProxy. -- The number of TiDB server instances that TiProxy can hold varies according to the type of workload. Under the basic workloads of Sysbench, a TiProxy can hold 4 to 10 TiDB server instances of the same model. -- The performance of TiProxy is more affected by the number of vCPUs, compared to HAProxy. When the returned data is 10,000 rows and the CPU usage is the same, the QPS of TiProxy is about 30% lower than that of HAProxy. +- The QPS upper limit of TiProxy is affected by the type of workload. Under the basic workloads of Sysbench and the same CPU usage, the QPS of TiProxy is about 25% lower than that of HAProxy. +- The number of TiDB server instances that TiProxy can hold varies according to the type of workload. Under the basic workloads of Sysbench, a TiProxy can hold 5 to 12 TiDB server instances of the same model. +- The row number of the query result set has a significant impact on the QPS of TiProxy, and the impact is the same as that of HAProxy. - The performance of TiProxy increases almost linearly with the number of vCPUs. Therefore, increasing the number of vCPUs can effectively improve the QPS upper limit. +- The number of long connections and the frequency of creating short connections have minimal impact on the QPS of TiProxy. ## Test environment ### Hardware configuration -| Service | Machine Type | CPU Architecture | Instance Count | +| Service | Machine type | CPU model | Instance count | | --- | --- | --- | --- | -| TiProxy | 4C8G | AMD64 | 1 | -| HAProxy | 4C8G | AMD64 | 1 | -| PD | 4C8G | AMD64 | 3 | -| TiDB | 8C16G | AMD64 | 8 | -| TiKV | 8C16G | AMD64 | 8 | -| Sysbench | 8C16G | AMD64 | 1 | +| TiProxy | 4C8G | Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz | 1 | +| HAProxy | 4C8G | Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz | 1 | +| PD | 4C8G | Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz | 3 | +| TiDB | 8C16G | Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz | 8 | +| TiKV | 8C16G | Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz | 8 | +| Sysbench | 8C16G | Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz | 1 | ### Software | Service | Software version | | --- | --- | -| TiProxy | v0.2.0 | +| TiProxy | v1.0.0 | | HAProxy | 2.9.0 | -| PD | v7.6.0 | -| TiDB | v7.6.0 | -| TiKV | v7.6.0 | +| PD | v8.0.0 | +| TiDB | v8.0.0 | +| TiKV | v8.0.0 | | Sysbench | 1.0.17 | ### Configuration @@ -102,73 +103,73 @@ sysbench $testname \ TiProxy test results: -| Threads | QPS | Avg latency(ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU Usage | -| --- | --- | --- | --- | --- | --- | -| 20 | 43935 | 0.45 | 0.63 | 210% | 900% | -| 50 | 87870 | 0.57 | 0.77 | 350% | 1700% | -| 100 | 91611 | 1.09 | 1.79 | 400% | 1800% | +| Threads | QPS | Avg latency (ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU usage | +|---------|---------|------------------|------------------|-------------------|------------------------| +| 20 | 41273 | 0.48 | 0.64 | 190% | 900% | +| 50 | 100255 | 0.50 | 0.62 | 330% | 1900% | +| 100 | 137688 | 0.73 | 1.01 | 400% | 2600% | HAProxy test results: -| Threads | QPS | Avg latency(ms) | P95 latency (ms) | HAProxy CPU usage | TiDB overall CPU Usage | -| --- | --- | --- | --- | --- | --- | -| 20 | 43629 | 0.46 | 0.63 | 130% | 900% | -| 50 | 102934 | 0.49 | 0.61 | 320% | 2000% | -| 100 | 157880 | 0.63 | 0.81 | 400% | 3000% | +| Threads | QPS | Avg latency (ms) | P95 latency (ms) | HAProxy CPU usage | TiDB overall CPU usage | +|---------|--------|------------------|------------------|-------------------|------------------------| +| 20 | 44833 | 0.45 | 0.61 | 140% | 1000% | +| 50 | 103631 | 0.48 | 0.61 | 270% | 2100% | +| 100 | 163069 | 0.61 | 0.77 | 360% | 3100% | ### Read Only TiProxy test results: -| Threads | QPS | Avg latency(ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU Usage | -| --- | --- | --- | --- | --- | --- | -| 50 | 71816 | 11.14 | 12.98 | 340% | 2500% | -| 100 | 79299 | 20.17 | 23.95 | 400% | 2800% | -| 200 | 83371 | 38.37 | 46.63 | 400% | 2900% | +| Threads | QPS | Avg latency (ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU usage | +|---------|--------|------------------|------------------|-------------------|------------------------| +| 50 | 72076 | 11.09 | 12.75 | 290% | 2500% | +| 100 | 109704 | 14.58 | 17.63 | 370% | 3800% | +| 200 | 117519 | 27.21 | 32.53 | 400% | 4100% | HAProxy test results: -| Threads | QPS | Avg latency(ms) | P95 latency (ms) | HAProxy CPU usage | TiDB overall CPU Usage | -| --- | --- | --- | --- | --- | --- | -| 50 | 74945 | 10.67 | 12.08 | 250% | 2500% | -| 100 | 118526 | 13.49 | 18.28 | 350% | 4000% | -| 200 | 131102 | 24.39 | 34.33 | 390% | 4300% | +| Threads | QPS | Avg latency (ms) | P95 latency (ms) | HAProxy CPU usage | TiDB overall CPU usage | +|---------|---------|------------------|------------------|-------------------|------------------------| +| 50 | 75760 | 10.56 | 12.08 | 250% | 2600% | +| 100 | 121730 | 13.14 | 15.83 | 350% | 4200% | +| 200 | 131712 | 24.27 | 30.26 | 370% | 4500% | ### Write Only TiProxy test results: -| Threads | QPS | Avg latency(ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU Usage | -| --- | --- | --- | --- | --- | --- | -| 100 | 67762 | 8.85 | 15.27 | 310% | 3200% | -| 300 | 81113 | 22.18 | 38.25 | 390% | 3900% | -| 500 | 79260 | 37.83 | 56.84 | 400% | 3800% | +| Threads | QPS | Avg latency (ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU usage | +|---------|---------|------------------|------------------|-------------------|------------------------| +| 100 | 81957 | 7.32 | 10.27 | 290% | 3900% | +| 300 | 103040 | 17.45 | 31.37 | 330% | 4700% | +| 500 | 104869 | 28.59 | 52.89 | 340% | 4800% | HAProxy test results: -| Threads | QPS | Avg latency(ms) | P95 latency (ms) | HAProxy CPU usage | TiDB overall CPU Usage | -| --- | --- | --- | --- | --- | --- | -| 100 | 74501 | 8.05 | 12.30 | 220% | 3500% | -| 300 | 97942 | 18.36 | 31.94 | 280% | 4300% | -| 500 | 105352 | 28.44 | 49.21 | 300% | 4500% | +| Threads | QPS | Avg latency (ms) | P95 latency (ms) | HAProxy CPU usage | TiDB overall CPU usage | +|---------|---------|------------------|------------------|-------------------|------------------------| +| 100 | 81708 | 7.34 | 10.65 | 240% | 3700% | +| 300 | 106008 | 16.95 | 31.37 | 320% | 4800% | +| 500 | 122369 | 24.45 | 47.47 | 350% | 5300% | ### Read Write TiProxy test results: -| Threads | QPS | Avg latency(ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU Usage | -| --- | --- | --- | --- | --- | --- | -| 50 | 60170 | 16.62 | 18.95 | 280% | 2700% | -| 100 | 81691 | 24.48 | 31.37 | 340% | 3600% | -| 200 | 88755 | 45.05 | 54.83 | 400% | 4000% | +| Threads | QPS | Avg latency (ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU usage | +|---------|--------|------------------|------------------|-------------------|------------------------| +| 50 | 58571 | 17.07 | 19.65 | 250% | 2600% | +| 100 | 88432 | 22.60 | 29.19 | 330% | 3900% | +| 200 | 108758 | 36.73 | 51.94 | 380% | 4800% | HAProxy test results: -| Threads | QPS | Avg latency(ms) | P95 latency (ms) | HAProxy CPU usage | TiDB overall CPU Usage | -| --- | --- | --- | --- | --- | --- | -| 50 | 58151 | 17.19 | 20.37 | 240% | 2600% | -| 100 | 94123 | 21.24 | 26.68 | 370% | 4100% | -| 200 | 107423 | 37.21 | 45.79 | 400% | 4700% | +| Threads | QPS | Avg latency (ms) | P95 latency (ms) | HAProxy CPU usage | TiDB overall CPU usage | +|---------|---------|------------------|------------------|-------------------|------------------------| +| 50 | 61226 | 16.33 | 19.65 | 190% | 2800% | +| 100 | 96569 | 20.70 | 26.68 | 290% | 4100% | +| 200 | 120163 | 31.28 | 49.21 | 340% | 5200% | ## Result set test @@ -202,21 +203,21 @@ sysbench oltp_read_only \ TiProxy test results: -| Range Size | QPS | Avg latency(ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU Usage | Inbound Network (MiB/s) | Outbound Network (MiB/s) | -| --- | --- | --- | --- | --- | --- | --- | --- | -| 10 | 92100 | 1.09 | 1.34 | 330% | 3700% | 150 | 150 | -| 100 | 57931 | 1.73 | 2.30 | 370% | 2800% | 840 | 840 | -| 1000 | 8249 | 12.12 | 18.95 | 250% | 1300% | 1140 | 1140 | -| 10000 | 826 | 120.77 | 363.18 | 230% | 600% | 1140 | 1140 | +| Range size | QPS | Avg latency (ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU usage | Inbound network (MiB/s) | Outbound network (MiB/s) | +|------------|---------|------------------|------------------|-------------------|------------------------|-------------------------|--------------------------| +| 10 | 80157 | 1.25 | 1.61 | 340% | 2600% | 140 | 140 | +| 100 | 55936 | 1.79 | 2.43 | 370% | 2800% | 820 | 820 | +| 1000 | 10313 | 9.69 | 13.70 | 310% | 1500% | 1370 | 1370 | +| 10000 | 1064 | 93.88 | 142.39 | 250% | 600% | 1430 | 1430 | HAProxy test results: -| Range Size | QPS | Avg latency(ms) | P95 latency (ms) | HAProxy CPU usage | TiDB overall CPU Usage | Inbound Network (MiB/s) | Outbound Network (MiB/s) | -| --- | --- | --- | --- | --- | --- | --- | --- | -| 10 | 93202 | 1.07 | 1.30 | 330% | 3800% | 145 | 145 | -| 100 | 64348 | 1.55 | 1.86 | 350% | 3100% | 830 | 830 | -| 1000 | 8944 | 11.18 | 14.73 | 240% | 1400% | 1100 | 1100 | -| 10000 | 908 | 109.96 | 139.85 | 180% | 600% | 1130 | 1130 | +| Range size | QPS | Avg latency (ms) | P95 latency (ms) | HAProxy CPU usage | TiDB overall CPU usage | Inbound network (MiB/s) | Outbound network (MiB/s) | +|------------|--------|------------------|------------------|-------------------|------------------------|-------------------------|--------------------------| +| 10 | 94376 | 1.06 | 1.30 | 250% | 4000% | 150 | 150 | +| 100 | 70129 | 1.42 | 1.76 | 270% | 3300% | 890 | 890 | +| 1000 | 9501 | 11.18 | 14.73 | 240% | 1500% | 1180 | 1180 | +| 10000 | 955 | 104.61 | 320.17 | 180% | 1200% | 1200 | 1200 | ## Scalability test @@ -241,9 +242,73 @@ sysbench oltp_point_select \ ### Test results -| vCPU | Threads | QPS | Avg latency(ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU Usage | -| --- | --- | --- | --- | --- | --- | --- | -| 2 | 40 | 58508 | 0.68 | 0.97 | 190% | 1200% | -| 4 | 80 | 104890 | 0.76 | 1.16 | 390% | 2000% | -| 6 | 120 | 155520 | 0.77 | 1.14 | 590% | 2900% | -| 8 | 160 | 202134 | 0.79 | 1.18 | 800% | 3900% | +| vCPU | Threads | QPS | Avg latency (ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU usage | +|------|---------|---------|------------------|------------------|-------------------|------------------------| +| 2 | 40 | 58508 | 0.68 | 0.97 | 190% | 1200% | +| 4 | 80 | 104890 | 0.76 | 1.16 | 390% | 2000% | +| 6 | 120 | 155520 | 0.77 | 1.14 | 590% | 2900% | +| 8 | 160 | 202134 | 0.79 | 1.18 | 800% | 3900% | + +## Long connection test + +### Test plan + +This test aims to verify that a large number of idle connections have minimal impact on the QPS when the client uses long connections. This test creates 5000, 10000, and 15000 idle long connections, and then executes `sysbench`. + +This test uses the default value for the `conn-buffer-size` configuration: + +```yaml +proxy.conn-buffer-size: 32768 +``` + +Use the following command to perform the test: + +```bash +sysbench oltp_point_select \ + --threads=50 \ + --time=1200 \ + --report-interval=10 \ + --rand-type=uniform \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=$host \ + --mysql-port=$port \ + run --tables=32 --table-size=1000000 +``` + +### Test results + +| Connection count | QPS | Avg latency (ms) | P95 latency (ms) | TiProxy CPU usage | TiProxy memory usage (MB) | TiDB overall CPU usage | +|------------------|-------|------------------|------------------|-------------------|---------------------------|------------------------| +| 5000 | 96620 | 0.52 | 0.64 | 330% | 920 | 1800% | +| 10000 | 96143 | 0.52 | 0.65 | 330% | 1710 | 1800% | +| 15000 | 96048 | 0.52 | 0.65 | 330% | 2570 | 1900% | + +## Short connection test + +### Test plan + +This test aims to verify that frequent creation and destruction of connections have minimal impact on the QPS when the client uses short connections. This test starts another client program to create and disconnect 100, 200, and 300 short connections per second while executing `sysbench`. + +Use the following command to perform the test: + +```bash +sysbench oltp_point_select \ + --threads=50 \ + --time=1200 \ + --report-interval=10 \ + --rand-type=uniform \ + --db-driver=mysql \ + --mysql-db=sbtest \ + --mysql-host=$host \ + --mysql-port=$port \ + run --tables=32 --table-size=1000000 +``` + +### Test results + +| New connections per second | QPS | Avg latency (ms) | P95 latency (ms) | TiProxy CPU usage | TiDB overall CPU usage | +|----------------------------|--------|------------------|------------------|-------------------|------------------------| +| 100 | 95597 | 0.52 | 0.65 | 330% | 1800% | +| 200 | 94692 | 0.53 | 0.67 | 330% | 1800% | +| 300 | 94102 | 0.53 | 0.68 | 330% | 1900% | From db4a3e51991b387391bd56096226dfd7edab9077 Mon Sep 17 00:00:00 2001 From: yibin Date: Tue, 19 Mar 2024 10:44:12 +0800 Subject: [PATCH 45/82] Add div_precision_increment system variable doc (#16736) --- system-variables.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/system-variables.md b/system-variables.md index 7e11470b1f90c..cd95e53212067 100644 --- a/system-variables.md +++ b/system-variables.md @@ -506,6 +506,16 @@ For more possible values of this variable, see [Authentication plugin status](/s +### div_precision_increment New in v8.0.0 + +- Scope: SESSION | GLOBAL +- Persists to cluster: Yes +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes +- Type: Integer +- Default value: `4` +- Range: `[0, 30]` +- This variable specifies the number of digits by which to increase the scale of the result of a division operation performed using the `/` operator. This variable is the same as MySQL. + ### error_count - Scope: SESSION From fbd435773d788518a1536cf9fcf0210f1cb76c90 Mon Sep 17 00:00:00 2001 From: Cheng Rui <44940678+RobertCheng-956@users.noreply.github.com> Date: Tue, 19 Mar 2024 10:51:42 +0800 Subject: [PATCH 46/82] Update partitioned-table.md (#16598) --- mysql-compatibility.md | 2 +- partitioned-table.md | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/mysql-compatibility.md b/mysql-compatibility.md index 0716f33b423a7..0851074746c9a 100644 --- a/mysql-compatibility.md +++ b/mysql-compatibility.md @@ -172,7 +172,7 @@ In TiDB, all supported DDL changes can be performed online. However, there are s * The `ALGORITHM={INSTANT,INPLACE,COPY}` syntax functions only as an assertion in TiDB, and does not modify the `ALTER` algorithm. See [`ALTER TABLE`](/sql-statements/sql-statement-alter-table.md) for further details. * Adding/Dropping the primary key of the `CLUSTERED` type is unsupported. For more details about the primary key of the `CLUSTERED` type, refer to [clustered index](/clustered-indexes.md). * Different types of indexes (`HASH|BTREE|RTREE|FULLTEXT`) are not supported, and will be parsed and ignored when specified. -* TiDB supports `HASH`, `RANGE`, `LIST`, and `KEY` partitioning types. Currently, the `KEY` partition type does not support partition statements with an empty partition column list. For an unsupported partition type, TiDB returns `Warning: Unsupported partition type %s, treat as normal table`, where `%s` is the specific unsupported partition type. +* TiDB supports `HASH`, `RANGE`, `LIST`, and `KEY` partitioning types. For an unsupported partition type, TiDB returns `Warning: Unsupported partition type %s, treat as normal table`, where `%s` is the specific unsupported partition type. * Range, Range COLUMNS, List, and List COLUMNS partitioned tables support `ADD`, `DROP`, `TRUNCATE`, and `REORGANIZE` operations. Other partition operations are ignored. * Hash and Key partitioned tables support `ADD`, `COALESCE`, and `TRUNCATE` operations. Other partition operations are ignored. * The following syntaxes are not supported for partitioned tables: diff --git a/partitioned-table.md b/partitioned-table.md index 1b80da4c7beb1..9d4de51a37997 100644 --- a/partitioned-table.md +++ b/partitioned-table.md @@ -665,11 +665,11 @@ PARTITION BY KEY(fname, store_id) PARTITIONS 4; ``` -Currently, TiDB does not support creating Key partitioned tables if the partition column list specified in `PARTITION BY KEY` is empty. For example, after you execute the following statement, TiDB will create a non-partitioned table and return an `Unsupported partition type KEY, treat as normal table` warning. +Similar to MySQL, TiDB supports creating Key partitioned tables with an empty partition column list specified in `PARTITION BY KEY`. For example, the following statement creates a partitioned table using the primary key `id` as the partitioning key: ```sql CREATE TABLE employees ( - id INT NOT NULL, + id INT NOT NULL PRIMARY KEY, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', @@ -682,6 +682,20 @@ PARTITION BY KEY() PARTITIONS 4; ``` +If the table lacks a primary key but contains a unique key, the unique key is used as the partitioning key: + +```sql +CREATE TABLE k1 ( + id INT NOT NULL, + name VARCHAR(20), + UNIQUE KEY (id) +) +PARTITION BY KEY() +PARTITIONS 2; +``` + +However, the previous statement will fail if the unique key column is not defined as `NOT NULL`. + #### How TiDB handles Linear Hash partitions Before v6.4.0, if you execute DDL statements of [MySQL Linear Hash](https://dev.mysql.com/doc/refman/8.0/en/partitioning-linear-hash.html) partitions in TiDB, TiDB can only create non-partitioned tables. In this case, if you still want to use partitioned tables in TiDB, you need to modify the DDL statements. @@ -1682,8 +1696,6 @@ YEARWEEK() Currently, TiDB supports Range partitioning, Range COLUMNS partitioning, List partitioning, List COLUMNS partitioning, Hash partitioning, and Key partitioning. Other partitioning types that are available in MySQL are not supported yet in TiDB. -Currently, TiDB does not support using an empty partition column list for Key partitioning. - With regard to partition management, any operation that requires moving data in the bottom implementation is not supported currently, including but not limited to: adjust the number of partitions in a Hash partitioned table, modify the Range of a Range partitioned table, and merge partitions. For the unsupported partitioning types, when you create a table in TiDB, the partitioning information is ignored and the table is created in the regular form with a warning reported. From 4a793137671e81bd8c53c0948b17b1b2f55fc316 Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Tue, 19 Mar 2024 11:00:43 +0800 Subject: [PATCH 47/82] txn: add description about deprecating the tidb_disable_txn_auto_retry system variable (#16541) --- optimistic-transaction.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/optimistic-transaction.md b/optimistic-transaction.md index 147ad9fa41966..f7e4b1fe558c1 100644 --- a/optimistic-transaction.md +++ b/optimistic-transaction.md @@ -65,6 +65,10 @@ However, TiDB transactions also have the following disadvantages: ## Transaction retries +> **Note:** +> +> Starting from v8.0.0, the [`tidb_disable_txn_auto_retry`](/system-variables.md#tidb_disable_txn_auto_retry) system variable is deprecated, and TiDB no longer supports automatic retries of optimistic transactions. It is recommended to use the [Pessimistic transaction mode](/pessimistic-transaction.md). If you encounter optimistic transaction conflicts, you can capture the error and retry transactions in your application. + In the optimistic transaction model, transactions might fail to be committed because of write–write conflict in heavy contention scenarios. TiDB uses optimistic concurrency control by default, whereas MySQL applies pessimistic concurrency control. This means that MySQL adds locks during the execution of write-type SQL statements, and its Repeatable Read isolation level allows for current reads, so commits generally do not encounter exceptions. To lower the difficulty of adapting applications, TiDB provides an internal retry mechanism. ### Automatic retry From 669d9575cdf141c4eefee35da01075ddd8046950 Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Tue, 19 Mar 2024 11:05:12 +0800 Subject: [PATCH 48/82] txn: deprecate the tidb_disable_txn_auto_retry system variable (#16530) --- system-variables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system-variables.md b/system-variables.md index cd95e53212067..c278a76a51a58 100644 --- a/system-variables.md +++ b/system-variables.md @@ -1744,7 +1744,7 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; > **Warning:** > -> Starting from TiDB v8.0.0, this variable will be deprecated, and TiDB will no longer support automatic retries of optimistic transactions. As an alternative, when encountering transaction conflicts, you can capture the error and retry transactions in your application, or use the [Pessimistic transaction mode](/pessimistic-transaction.md) instead. +> Starting from v8.0.0, this variable is deprecated, and TiDB no longer supports automatic retries of optimistic transactions. As an alternative, when encountering optimistic transaction conflicts, you can capture the error and retry transactions in your application, or use the [Pessimistic transaction mode](/pessimistic-transaction.md) instead. - Scope: SESSION | GLOBAL - Persists to cluster: Yes From 1ac320adb1c07efff4efa78f2fd7ae378e9e931d Mon Sep 17 00:00:00 2001 From: hongyunyan <649330952@qq.com> Date: Tue, 19 Mar 2024 11:11:13 +0800 Subject: [PATCH 49/82] Add sql mode format restrictions to expr in ticdc filter (#16626) --- ticdc/ticdc-filter.md | 74 ++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/ticdc/ticdc-filter.md b/ticdc/ticdc-filter.md index 6ad1c17ec9250..fbd0273eb9ed1 100644 --- a/ticdc/ticdc-filter.md +++ b/ticdc/ticdc-filter.md @@ -57,31 +57,55 @@ Description of configuration parameters: - `matcher`: the database and table that this event filter rule applies to. The syntax is the same as [table filter](/table-filter.md). - `ignore-event`: the event type to be ignored. This parameter accepts an array of strings. You can configure multiple event types. Currently, the following event types are supported: -| Event | Type | Alias | Description | -| --------------- | ---- | -|--------------------------| -| all dml | | |Matches all DML events | -| all ddl | | |Matches all DDL events | -| insert | DML | |Matches `insert` DML event | -| update | DML | |Matches `update` DML event | -| delete | DML | |Matches `delete` DML event | -| create schema | DDL | create database |Matches `create database` event | -| drop schema | DDL | drop database |Matches `drop database` event | -| create table | DDL | |Matches `create table` event | -| drop table | DDL | |Matches `drop table` event | -| rename table | DDL | |Matches `rename table` event | -| truncate table | DDL | |Matches `truncate table` event | -| alter table | DDL | |Matches `alter table` event, including all clauses of `alter table`, `create index` and `drop index` | -| add table partition | DDL | |Matches `add table partition` event | -| drop table partition | DDL | |Matches `drop table partition` event | -| truncate table partition | DDL | |Matches `truncate table partition` event | -| create view | DDL | |Matches `create view`event | -| drop view | DDL | |Matches `drop view` event | - -- `ignore-sql`: the DDL statements to be ignored. This parameter accepts an array of strings, in which you can configure multiple regular expressions. This rule only applies to DDL events. -- `ignore-delete-value-expr`: this parameter accepts a SQL expression. This rule only applies to delete DML events with the specified value. -- `ignore-insert-value-expr`: this parameter accepts a SQL expression. This rule only applies to insert DML events with the specified value. -- `ignore-update-old-value-expr`: this parameter accepts a SQL expression. This rule only applies to update DML events whose old value contains the specified value. -- `ignore-update-new-value-expr`: this parameter accepts a SQL expression. This rule only applies to update DML events whose new value contains the specified value. + | Event | Type | Alias | Description | + | --------------- | ---- | -|--------------------------| + | all dml | | |Matches all DML events | + | all ddl | | |Matches all DDL events | + | insert | DML | |Matches `insert` DML event | + | update | DML | |Matches `update` DML event | + | delete | DML | |Matches `delete` DML event | + | create schema | DDL | create database |Matches `create database` event | + | drop schema | DDL | drop database |Matches `drop database` event | + | create table | DDL | |Matches `create table` event | + | drop table | DDL | |Matches `drop table` event | + | rename table | DDL | |Matches `rename table` event | + | truncate table | DDL | |Matches `truncate table` event | + | alter table | DDL | |Matches `alter table` event, including all clauses of `alter table`, `create index` and `drop index` | + | add table partition | DDL | |Matches `add table partition` event | + | drop table partition | DDL | |Matches `drop table partition` event | + | truncate table partition | DDL | |Matches `truncate table partition` event | + | create view | DDL | |Matches `create view`event | + | drop view | DDL | |Matches `drop view` event | + | modify schema charset and collate | DDL | |Matches `modify schema charset and collate` event | + | recover table | DDL | |Matches `recover table` event | + | rebase auto id | DDL | |Matches `rebase auto id` event | + | modify table comment | DDL | |Matches `modify table comment` event | + | modify table charset and collate | DDL | |Matches `modify table charset and collate` event | + | exchange table partition | DDL | |Matches `exchange table partition` event | + | reorganize table partition | DDL | |Matches `reorganize table partition` event | + | alter table partitioning | DDL | |Matches `alter table partitioning` event | + | remove table partitioning | DDL | |Matches `remove table partitioning` event | + | add column | DDL | |Matches `add column` event | + | drop column | DDL | |Matches `drop column` event | + | modify column | DDL | |Matches `modify column` event | + | set default value | DDL | |Matches `set default value` event | + | add primary key | DDL | |Matches `add primary key` event | + | drop primary key | DDL | |Matches `drop primary key` event | + | rename index | DDL | |Matches `rename index` event | + | alter index visibility | DDL | |Matches `alter index visibility` event | + | alter ttl info | DDL | |Matches `alter ttl info` event | + | alter ttl remove| DDL | |Matches DDL events that remove all TTL attributes of a table | + | multi schema change | DDL | |Matches DDL events that change multiple attributes of a table within the same DDL statement | + + > **Note:** + > + > TiDB's DDL statements support changing multiple attributes of a single table at the same time, such as `ALTER TABLE t MODIFY COLUMN a INT, ADD COLUMN b INT, DROP COLUMN c;`. This operation is defined as MultiSchemaChange. If you want to filter out this type of DDL, you need to configure `"multi schema change"` in `ignore-event`. + +- `ignore-sql`: the regular expressions of the DDL statements to be filtered out. This parameter accepts an array of strings, in which you can configure multiple regular expressions. This configuration only applies to DDL events. +- `ignore-delete-value-expr`: this parameter accepts a SQL expression that follows the default SQL mode, used to filter out the `DELETE` type of DML events with a specified value. +- `ignore-insert-value-expr`: this parameter accepts a SQL expression that follows the default SQL mode, used to filter out the `INSERT` type of DML events with a specified value. +- `ignore-update-old-value-expr`: this parameter accepts a SQL expression that follows the default SQL mode, used to filter out the `UPDATE` type of DML events with a specified old value. +- `ignore-update-new-value-expr`: this parameter accepts a SQL expression that follows the default SQL mode, used to filter out the `UPDATE` DML events with a specified new value. > **Note:** > From 9b7fbf0db8bace41f1b9674a530e5fe8d29cdc7e Mon Sep 17 00:00:00 2001 From: xixirangrang Date: Tue, 19 Mar 2024 11:36:43 +0800 Subject: [PATCH 50/82] tidb: add `general-log-file` and `compression` (#16663) --- command-line-flags-for-tidb-configuration.md | 6 ++++++ tidb-configuration-file.md | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/command-line-flags-for-tidb-configuration.md b/command-line-flags-for-tidb-configuration.md index e4b5b936f2e7e..1981b1c94f778 100644 --- a/command-line-flags-for-tidb-configuration.md +++ b/command-line-flags-for-tidb-configuration.md @@ -79,6 +79,12 @@ When you start the TiDB cluster, you can use command-line options or environment - Default: `""` - If this option is not set, logs are output to "stderr". If this option is set, logs are output to the corresponding file. +## `--log-general` + ++ The filename of the [General Log](/system-variables.md#tidb_general_log) ++ Default: `""` ++ If this option is not set, the general log is written to the file specified by [`--log-file`](#--log-file) by default. + ## `--log-slow-query` - The directory for the slow query log diff --git a/tidb-configuration-file.md b/tidb-configuration-file.md index 22d205089d648..706a66ce6ea29 100644 --- a/tidb-configuration-file.md +++ b/tidb-configuration-file.md @@ -319,6 +319,12 @@ Configuration items related to log. - Default value: `10000` - When the number of query rows (including the intermediate results based on statistics) is larger than this value, it is an `expensive` operation and outputs log with the `[EXPENSIVE_QUERY]` prefix. +### `general-log-file` New in v8.0.0 + ++ The filename of the [general log](/system-variables.md#tidb_general_log). ++ Default value: `""` ++ If you specify a filename, the general log is written to this specified file. If the value is blank, the general log is written to the server log of the TiDB instance. You can specify the name of the server log using [`filename`](#filename). + ### `timeout` New in v7.1.0 - Sets the timeout for log-writing operations in TiDB. In case of a disk failure that prevents logs from being written, this configuration item can trigger the TiDB process to panic instead of hang. @@ -355,6 +361,13 @@ Configuration items related to log files. - Default value: `0` - All the log files are retained by default. If you set it to `7`, seven log files are retained at maximum. +#### `compression` New in v8.0.0 + ++ The compression method for the log. ++ Default value: `""` ++ Value options: `""`, `"gzip"` ++ The default value is `""`, which means no compression. To enable the gzip compression, set this value to `"gzip"`. After compression is enabled, all log files are affected, such as [`slow-query-file`](#slow-query-file) and [`general-log-file`](#general-log-file-new-in-v800). + ## Security Configuration items related to security. From ab2181966eadf2e17996baf183355e0c318ebd87 Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Tue, 19 Mar 2024 11:48:43 +0800 Subject: [PATCH 51/82] Add TiCDC Debezium Protocol docs (#16703) --- TOC.md | 1 + ticdc/ticdc-changefeed-config.md | 2 +- ticdc/ticdc-debezium.md | 138 +++++++++++++++++++++++++++++++ ticdc/ticdc-overview.md | 2 +- 4 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 ticdc/ticdc-debezium.md diff --git a/TOC.md b/TOC.md index c7a167155b701..f76d89486e3c6 100644 --- a/TOC.md +++ b/TOC.md @@ -577,6 +577,7 @@ - [TiCDC Canal-JSON Protocol](/ticdc/ticdc-canal-json.md) - [TiCDC Open Protocol](/ticdc/ticdc-open-protocol.md) - [TiCDC CSV Protocol](/ticdc/ticdc-csv.md) + - [TiCDC Debezium Protocol](/ticdc/ticdc-debezium.md) - [TiCDC Open API v2](/ticdc/ticdc-open-api-v2.md) - [TiCDC Open API v1](/ticdc/ticdc-open-api.md) - TiCDC Data Consumption diff --git a/ticdc/ticdc-changefeed-config.md b/ticdc/ticdc-changefeed-config.md index 1e6215af3d754..1e25ea169a4d9 100644 --- a/ticdc/ticdc-changefeed-config.md +++ b/ticdc/ticdc-changefeed-config.md @@ -138,7 +138,7 @@ enable-table-across-nodes = false # ] # The protocol configuration item specifies the protocol format used for encoding messages. -# When the downstream is Kafka, the protocol can only be canal-json, avro, or open-protocol. +# When the downstream is Kafka, the protocol can only be canal-json, avro, debezium, or open-protocol. # When the downstream is Pulsar, the protocol can only be canal-json. # When the downstream is a storage service, the protocol can only be canal-json or csv. # Note: This configuration item only takes effect if the downstream is Kafka, Pulsar, or a storage service. diff --git a/ticdc/ticdc-debezium.md b/ticdc/ticdc-debezium.md new file mode 100644 index 0000000000000..253c3b9da6016 --- /dev/null +++ b/ticdc/ticdc-debezium.md @@ -0,0 +1,138 @@ +--- +title: TiCDC Debezium Protocol +summary: Learn the concept of the TiCDC Debezium Protocol and how to use it. +--- + +# TiCDC Debezium Protocol + +[Debezium](https://debezium.io/) is a tool for capturing database changes. It converts each captured database change into a message called an "event" and sends these events to Kafka. Starting from v8.0.0, TiCDC supports sending TiDB changes to Kafka using a Debezium style output format, simplifying migration from MySQL databases for users who had previously been using Debezium's MySQL integration. + +## Use the Debezium message format + +When you use Kafka as the downstream sink, specify the `protocol` field as `debezium` in `sink-uri` configuration. Then TiCDC encapsulates the Debezium messages based on the events and sends TiDB data change events to the downstream. + +Currently, the Debezium protocol only supports Row Changed events and directly ignores DDL events and WATERMARK events. A Row changed event represents a data change in a row. When a row changes, the Row Changed event is sent, including relevant information about the row both before and after the change. A WATERMARK event marks the replication progress of a table, indicating that all events earlier than the watermark have been sent to the downstream. + +The configuration example for using the Debezium message format is as follows: + +```shell +cdc cli changefeed create --server=http://127.0.0.1:8300 --changefeed-id="kafka-debezium" --sink-uri="kafka://127.0.0.1:9092/topic-name?kafka-version=2.4.0&protocol=debezium" +``` + +The Debezium output format contains the schema information of the current row so that downstream consumers can better understand the data structure of the current row. For scenarios where schema information is unnecessary, you can also disable the schema output by setting the `debezium-disable-schema` parameter to `true` in the changefeed configuration file or `sink-uri`. + +In addition, the original Debezium format does not include important fields such as the unique transaction identifier of the `CommitTS` in TiDB. To ensure data integrity, TiCDC adds two fields, `CommitTs` and `ClusterID`, to the Debezium format to identify the relevant information of TiDB data changes. + +## Message format definition + +This section describes the format definition of the DML event output in the Debezium format. + +### DML event + +TiCDC encodes a DML event in the following format: + +```json +{ + "payload":{ + "ts_ms":1707103832957, + "transaction":null, + "op":"c", + "before":null, + "after":{ + "a":4, + "b":2 + }, + "source":{ + "version":"2.4.0.Final", + "connector":"TiCDC", + "name":"default", + "ts_ms":1707103832263, + "snapshot":"false", + "db":"test", + "table":"t2", + "server_id":0, + "gtid":null, + "file":"", + "pos":0, + "row":0, + "thread":0, + "query":null, + "commit_ts":447507027004751877, + "cluster_id":"default" + } + }, + "schema":{ + "type":"struct", + "optional":false, + "name":"default.test.t2.Envelope", + "version":1, + "fields":{ + { + "type":"struct", + "optional":true, + "name":"default.test.t2.Value", + "field":"before", + "fields":[ + { + "type":"int32", + "optional":false, + "field":"a" + }, + { + "type":"int32", + "optional":true, + "field":"b" + } + ] + }, + { + "type":"struct", + "optional":true, + "name":"default.test.t2.Value", + "field":"after", + "fields":[ + { + "type":"int32", + "optional":false, + "field":"a" + }, + { + "type":"int32", + "optional":true, + "field":"b" + } + ] + }, + { + "type":"string", + "optional":false, + "field":"op" + }, + ... + } + } +} +``` + +The key fields of the preceding JSON data are explained as follows: + +| Field | Type | Description | +|:----------|:-------|:-------------------------------------------------------| +| payload.op | String | The type of the change event. `"c"` indicates an `INSERT` event, `"u"` indicates an `UPDATE` event, and `"d"` indicates a `DELETE` event. | +| payload.ts_ms | Number | The timestamp (in milliseconds) when TiCDC generates this message. | +| payload.before | JSON | The data value before the change event of a statement. For `"c"` events, the value of the `before` field is `null`. | +| payload.after | JSON | The data value after the change event of a statement. For `"d"` events, the value of the `after` field is `null`. | +| payload.source.commit_ts | Number | The `CommitTs` identifier when TiCDC generates this message. | +| payload.source.db | String | The name of the database where the event occurs. | +| payload.source.table | String | The name of the table where the event occurs. | +| schema.fields | JSON | The type information of each field in the payload, including the schema information of the row data before and after the change. | + +### Data type mapping + +The data format mapping in the TiCDC Debezium message basically follows the [Debezium data type mapping rules](https://debezium.io/documentation/reference/2.4/connectors/mysql.html#mysql-data-types), which is generally consistent with the native message of the Debezium Connector for MySQL. However, for some data types, the following differences exist between TiCDC Debezium and Debezium Connector messages: + +- Currently, TiDB does not support spatial data types, including GEOMETRY, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON, and GEOMETRYCOLLECTION. + +- For string-like data types, including Varchar, String, VarString, TinyBlob, MediumBlob, BLOB, and LongBlob, when the column has the BINARY flag, TiCDC encodes it as a String type after encoding it in Base64; when the column does not have the BINARY flag, TiCDC encodes it directly as a String type. The native Debezium Connector encodes it in different ways according to `binary.handling.mode`. + +- For the Decimal data type, including `DECIMAL` and `NUMERIC`, TiCDC uses the float64 type to represent it. The native Debezium Connector encodes it in float32 or float64 according to the different precision of the data type. diff --git a/ticdc/ticdc-overview.md b/ticdc/ticdc-overview.md index 094b8f1b35046..c3b3858380000 100644 --- a/ticdc/ticdc-overview.md +++ b/ticdc/ticdc-overview.md @@ -24,7 +24,7 @@ TiCDC has the following key capabilities: - Replicating incremental data between TiDB clusters with second-level RPO and minute-level RTO. - Bidirectional replication between TiDB clusters, allowing the creation of a multi-active TiDB solution using TiCDC. - Replicating incremental data from a TiDB cluster to a MySQL database or other MySQL-compatible databases with low latency. -- Replicating incremental data from a TiDB cluster to a Kafka cluster. The recommended data format includes [Canal-JSON](/ticdc/ticdc-canal-json.md) and [Avro](/ticdc/ticdc-avro-protocol.md). +- Replicating incremental data from a TiDB cluster to a Kafka cluster. The recommended data format includes [Canal-JSON](/ticdc/ticdc-canal-json.md), [Avro](/ticdc/ticdc-avro-protocol.md), and [Debezium](/ticdc/ticdc-debezium.md). - Replicating incremental data from a TiDB cluster to storage services, such as Amazon S3, GCS, Azure Blob Storage, and NFS. - Replicating tables with the ability to filter databases, tables, DMLs, and DDLs. - High availability with no single point of failure, supporting dynamically adding and deleting TiCDC nodes. From efca22ab0e2ae0dd1db2d21cd2ba81b04b163480 Mon Sep 17 00:00:00 2001 From: cfzjywxk Date: Tue, 19 Mar 2024 12:14:13 +0800 Subject: [PATCH 52/82] *: add `tidb_low_resolution_tso_update_interval` (#16706) --- system-variables.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/system-variables.md b/system-variables.md index c278a76a51a58..798a54c0ace58 100644 --- a/system-variables.md +++ b/system-variables.md @@ -3409,9 +3409,21 @@ For a system upgraded to v5.0 from an earlier version, if you have not modified - Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No - Type: Boolean - Default value: `OFF` -- This variable is used to set whether to enable the low precision TSO feature. After this feature is enabled, new transactions use a timestamp updated every 2 seconds to read data. +- This variable is used to set whether to enable the low-precision TSO feature. After this feature is enabled, TiDB uses the cached timestamp to read data. The cached timestamp is updated every 2 seconds by default. Starting from v8.0.0, you can configure the update interval by [`tidb_low_resolution_tso_update_interval`](#tidb_low_resolution_tso_update_interval-new-in-v800). - The main applicable scenario is to reduce the overhead of acquiring TSO for small read-only transactions when reading old data is acceptable. +### `tidb_low_resolution_tso_update_interval` New in v8.0.0 + +- Scope:GLOBAL +- Persists to cluster: Yes +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No +- Type:Integer +- Default value:`2000` +- Range:`[10, 60000]` +- Unit: Milliseconds +- This variable is used to set the update interval of the cached timestamp used in the low-precision TSO feature, in milliseconds. +- This variable is only available when [`tidb_low_resolution_tso`](#tidb_low_resolution_tso) is enabled. + ### tidb_max_auto_analyze_time New in v6.1.0 - Scope: GLOBAL From c4eaa01fbe4236322fcf40d97f4a4398122f1ef0 Mon Sep 17 00:00:00 2001 From: xixirangrang Date: Tue, 19 Mar 2024 12:33:42 +0800 Subject: [PATCH 53/82] tidb: add the description for `tidb_enable_auto_analyze_priority_queue` (#16730) --- statistics.md | 1 + system-variables.md | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/statistics.md b/statistics.md index 8d3fc672b66cd..7b6db2d637880 100644 --- a/statistics.md +++ b/statistics.md @@ -352,6 +352,7 @@ Three system variables related to automatic update of statistics are as follows: | [`tidb_auto_analyze_start_time`](/system-variables.md#tidb_auto_analyze_start_time) | `00:00 +0000` | The start time in a day when TiDB can perform automatic update | | [`tidb_auto_analyze_end_time`](/system-variables.md#tidb_auto_analyze_end_time) | `23:59 +0000` | The end time in a day when TiDB can perform automatic update | | [`tidb_auto_analyze_partition_batch_size`](/system-variables.md#tidb_auto_analyze_partition_batch_size-new-in-v640) | `1` | The number of partitions that TiDB automatically analyzes when analyzing a partitioned table (that is, when automatically updating statistics on a partitioned table) | +| [`tidb_enable_auto_analyze_priority_queue`](/system-variables.md#tidb_enable_auto_analyze_priority_queue-new-in-v800) | `ON` | Controls whether to enable the priority queue to schedule the tasks of automatically collecting statistics. When this variable is enabled, TiDB prioritizes collecting statistics for tables that are more valuable to collect, such as newly created indexes and partitioned tables with partition changes. Additionally, TiDB prioritizes tables with lower health scores, placing them at the front of the queue. | When the ratio of the number of modified rows to the total number of rows of `tbl` in a table is greater than `tidb_auto_analyze_ratio`, and the current time is between `tidb_auto_analyze_start_time` and `tidb_auto_analyze_end_time`, TiDB executes the `ANALYZE TABLE tbl` statement in the background to automatically update the statistics on this table. diff --git a/system-variables.md b/system-variables.md index 798a54c0ace58..8ef52f24d8854 100644 --- a/system-variables.md +++ b/system-variables.md @@ -1872,6 +1872,15 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; - Determines whether TiDB automatically updates table statistics as a background operation. - This setting was previously a `tidb.toml` option (`performance.run-auto-analyze`), but changed to a system variable starting from TiDB v6.1.0. +### tidb_enable_auto_analyze_priority_queue New in v8.0.0 + +- Scope: GLOBAL +- Persists to cluster: Yes +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No +- Type: Boolean +- Default value: `ON` +- This variable is used to control whether to enable the priority queue to schedule the tasks of automatically collecting statistics. When this variable is enabled, TiDB prioritizes collecting statistics for tables that are more valuable to collect, such as newly created indexes and partitioned tables with partition changes. Additionally, TiDB prioritizes tables with lower health scores, placing them at the front of the queue. + ### tidb_enable_auto_increment_in_generated - Scope: SESSION | GLOBAL From 8a6dbb39baa400ebe119c2dd8857ec7c71d8a9f9 Mon Sep 17 00:00:00 2001 From: Yuanjia Zhang Date: Tue, 19 Mar 2024 13:00:43 +0800 Subject: [PATCH 54/82] planner: update SPM doc (#16772) --- optimizer-hints.md | 2 +- sql-plan-management.md | 48 +++++++++++++++++++++++++++++++++++++++++- system-variables.md | 11 ++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/optimizer-hints.md b/optimizer-hints.md index 38a7813cf4ced..369020b628aae 100644 --- a/optimizer-hints.md +++ b/optimizer-hints.md @@ -12,7 +12,7 @@ If you encounter a situation where hints do not take effect, see [Troubleshoot c ## Syntax -Optimizer hints are case insensitive and specified within `/*+ ... */` comments following the `SELECT`, `UPDATE` or `DELETE` keyword in a SQL statement. Optimizer hints are not currently supported for `INSERT` statements. +Optimizer hints are case insensitive and specified within `/*+ ... */` comments following the `SELECT`, `INSERT`, `UPDATE` or `DELETE` keyword in a SQL statement. Multiple hints can be specified by separating with commas. For example, the following query uses three different hints: diff --git a/sql-plan-management.md b/sql-plan-management.md index 7f8a6d2258e62..e402c92b4d7c6 100644 --- a/sql-plan-management.md +++ b/sql-plan-management.md @@ -236,7 +236,7 @@ To make the execution plan of a SQL statement fixed to a historical execution pl When using this feature, note the following: - The feature generates hints according to historical execution plans and uses the generated hints for binding. Because historical execution plans are stored in [Statement Summary Tables](/statement-summary-tables.md), before using this feature, you need to enable the [`tidb_enable_stmt_summary`](/system-variables.md#tidb_enable_stmt_summary-new-in-v304) system variable first. -- This feature does not support TiFlash queries, Join queries with three or more tables, and queries that contain subqueries. +- For TiFlash queries, Join queries with three or more tables, and queries that contain subqueries, the auto-generated hints are not adequate, which might result in the plan not being fully bound. In such cases, a warning will occur when creating a binding. - If a historical execution plan is for a SQL statement with hints, the hints will be added to the binding. For example, after executing `SELECT /*+ max_execution_time(1000) */ * FROM t`, the binding created with its `plan_digest` will include `max_execution_time(1000)`. The SQL statement of this binding method is as follows: @@ -484,6 +484,52 @@ SHOW binding_cache status; 1 row in set (0.00 sec) ``` +## Utilize the statement summary table to obtain queries that need to be bound + +[Statement summary](/statement-summary-tables.md) records recent SQL execution information, such as latency, execution times, and corresponding query plans. You can query statement summary tables to get qualified `plan_digest`, and then [create bindings according to these historical execution plans](/sql-plan-management.md#create-a-binding-according-to-a-historical-execution-plan). + +The following example queries `SELECT` statements that have been executed more than 10 times in the past two weeks, and have multiple execution plans without SQL binding. It sorts the queries by the execution times, and binds the top 100 queries to their fastest plans. + +```sql +WITH stmts AS ( -- Gets all information + SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY + UNION ALL + SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY +), +best_plans AS ( + SELECT plan_digest, `digest`, avg_latency, + CONCAT('create global binding from history using plan digest "', plan_digest, '"') as binding_stmt + FROM stmts t1 + WHERE avg_latency = (SELECT min(avg_latency) FROM stmts t2 -- The plan with the lowest query latency + WHERE t2.`digest` = t1.`digest`) +) + +SELECT any_value(digest_text) as query, + SUM(exec_count) as exec_count, + plan_hint, binding_stmt +FROM stmts, best_plans +WHERE stmts.`digest` = best_plans.`digest` + AND summary_begin_time > DATE_SUB(NOW(), interval 14 day) -- Executed in the past 2 weeks + AND stmt_type = 'Select' -- Only consider select statements + AND schema_name NOT IN ('INFORMATION_SCHEMA', 'mysql') -- Not an internal query + AND plan_in_binding = 0 -- No binding yet +GROUP BY stmts.`digest` + HAVING COUNT(DISTINCT(stmts.plan_digest)) > 1 -- This query is unstable. It has more than 1 plan. + AND SUM(exec_count) > 10 -- High-frequency, and has been executed more than 10 times. +ORDER BY SUM(exec_count) DESC LIMIT 100; -- Top 100 high-frequency queries. +``` + +By applying certain filtering conditions to obtain queries that meet the criteria, you can then directly execute the statements in the corresponding `binding_stmt` column to create bindings. + +``` ++---------------------------------------------+------------+-----------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ +| query | exec_count | plan_hint | binding_stmt | ++---------------------------------------------+------------+-----------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ +| select * from `t` where `a` = ? and `b` = ? | 401 | use_index(@`sel_1` `test`.`t` `a`), no_order_index(@`sel_1` `test`.`t` `a`) | create global binding from history using plan digest "0d6e97fb1191bbd08dddefa7bd007ec0c422b1416b152662768f43e64a9958a6" | +| select * from `t` where `b` = ? and `c` = ? | 104 | use_index(@`sel_1` `test`.`t` `b`), no_order_index(@`sel_1` `test`.`t` `b`) | create global binding from history using plan digest "80c2aa0aa7e6d3205755823aa8c6165092c8521fb74c06a9204b8d35fc037dd9" | ++---------------------------------------------+------------+-----------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------+ +``` + ## Cross-database binding Starting from v7.6.0, you can create cross-database bindings in TiDB by using the wildcard `*` to represent a database name in the binding creation syntax. Before creating cross-database bindings, you need to first enable the [`tidb_opt_enable_fuzzy_binding`](/system-variables.md#tidb_opt_enable_fuzzy_binding-new-in-v760) system variable. diff --git a/system-variables.md b/system-variables.md index 8ef52f24d8854..3e021c6ccd656 100644 --- a/system-variables.md +++ b/system-variables.md @@ -3375,6 +3375,17 @@ For a system upgraded to v5.0 from an earlier version, if you have not modified
+### `tidb_load_binding_timeout` New in v8.0.0 + +- Scope: GLOBAL +- Persists to cluster: Yes +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No +- Type: Integer +- Default value: `200` +- Range: `(0, 2147483647]` +- Unit: Milliseconds +- This variable is used to control the timeout of loading bindings. If the execution time of loading bindings exceeds this value, the loading will stop. + ### `tidb_lock_unchanged_keys` New in v7.1.1 and v7.3.0 - Scope: SESSION | GLOBAL From 131b1e466b77251cf94e2a01a440dde1c43c4e65 Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Tue, 19 Mar 2024 13:48:42 +0800 Subject: [PATCH 55/82] pitr: support s3 object lock (#16715) --- br/backup-and-restore-storages.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/br/backup-and-restore-storages.md b/br/backup-and-restore-storages.md index eb25c40104a9e..09cd3352ec01f 100644 --- a/br/backup-and-restore-storages.md +++ b/br/backup-and-restore-storages.md @@ -260,4 +260,10 @@ BR supports specifying the Azure server-side encryption scope or providing the e ## Other features supported by the storage service -BR v6.3.0 supports AWS [S3 Object Lock](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lock.html). You can enable this feature to prevent backup data from being tampered with or deleted. +Amazon [S3 Object Lock](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lock.html) can help prevent backup data from accidental or intentional deletion during a specified retention period, enhancing the security and integrity of data. Starting from v6.3.0, BR supports Amazon S3 Object Lock for snapshot backups, adding an additional layer of security for full backups. Starting from v8.0.0, PITR also supports Amazon S3 Object Lock. Whether for full backups or log data backups, the Object Lock feature ensures more reliable data protection, further strengthening the security of data backup and recovery and meeting regulatory requirements. + +BR and PITR automatically detect whether the Amazon S3 Object Lock feature is enabled or disabled. You do not need to perform any additional operations. + +> **Warning:** +> +> If the Object Lock feature is enabled during the snapshot backup or PITR log backup process, the snapshot backup or log backup might fail. You need to restart the snapshot backup or PITR log backup task to continue the backup. From 31ed51daff9d83e65144c32899e5ced7d3bb7920 Mon Sep 17 00:00:00 2001 From: Yuanjia Zhang Date: Tue, 19 Mar 2024 14:23:14 +0800 Subject: [PATCH 56/82] planner: update Plan Cache doc (#16771) --- choose-index.md | 72 ++++++++++++++++++++++++++++++++++++++ sql-prepared-plan-cache.md | 2 +- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/choose-index.md b/choose-index.md index c4d239a2b60e1..6ef39b09e17b0 100644 --- a/choose-index.md +++ b/choose-index.md @@ -404,3 +404,75 @@ mysql> EXPLAIN SELECT /*+ use_index_merge(t3, idx) */ * FROM t3 WHERE ((1 member +-------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 3 rows in set, 2 warnings (0.00 sec) ``` + +### Multi-valued indexes and plan cache + +A query plan that uses `member of` to choose multi-valued indexes can be cached. A query plan that uses the `JSON_CONTAINS()` or `JSON_OVERLAPS()` function to choose multi-valued indexes cannot be cached. + +The following are some examples that query plans can be cached: + +```sql +mysql> CREATE TABLE t5 (j1 JSON, j2 JSON, INDEX idx1((CAST(j1 AS SIGNED ARRAY)))); +Query OK, 0 rows affected (0.04 sec) + +mysql> PREPARE st FROM 'SELECT /*+ use_index(t5, idx1) */ * FROM t5 WHERE (? member of (j1))'; +Query OK, 0 rows affected (0.00 sec) + +mysql> SET @a=1; +Query OK, 0 rows affected (0.00 sec) + +mysql> EXECUTE st USING @a; +Empty set (0.01 sec) + +mysql> EXECUTE st USING @a; +Empty set (0.00 sec) + +mysql> SELECT @@last_plan_from_cache; ++------------------------+ +| @@last_plan_from_cache | ++------------------------+ +| 1 | ++------------------------+ +1 row in set (0.00 sec) + +mysql> PREPARE st FROM 'SELECT /*+ use_index(t5, idx1) */ * FROM t5 WHERE (? member of (j1)) AND JSON_CONTAINS(j2, ?)'; +Query OK, 0 rows affected (0.00 sec) + +mysql> SET @a=1, @b='[1,2]'; +Query OK, 0 rows affected (0.00 sec) + +mysql> EXECUTE st USING @a, @b; +Empty set (0.00 sec) + +mysql> EXECUTE st USING @a, @b; +Empty set (0.00 sec) + +mysql> SELECT @@LAST_PLAN_FROM_CACHE; -- can hit plan cache if the JSON_CONTAINS doesn't impact index selection ++------------------------+ +| @@LAST_PLAN_FROM_CACHE | ++------------------------+ +| 1 | ++------------------------+ +1 row in set (0.00 sec) +``` + +The following are some examples that query plans cannot be cached: + +```sql +mysql> PREPARE st2 FROM 'SELECT /*+ use_index(t5, idx1) */ * FROM t5 WHERE JSON_CONTAINS(j1, ?)'; +Query OK, 0 rows affected (0.00 sec) + +mysql> SET @a='[1,2]'; +Query OK, 0 rows affected (0.01 sec) + +mysql> EXECUTE st2 USING @a; +Empty set, 1 warning (0.00 sec) + +mysql> SHOW WARNINGS; -- cannot hit plan cache since the JSON_CONTAINS predicate might affect index selection ++---------+------+-------------------------------------------------------------------------------------------------------+ +| Level | Code | Message | ++---------+------+-------------------------------------------------------------------------------------------------------+ +| Warning | 1105 | skip prepared plan-cache: json_contains function with immutable parameters can affect index selection | ++---------+------+-------------------------------------------------------------------------------------------------------+ +1 row in set (0.01 sec) +``` \ No newline at end of file diff --git a/sql-prepared-plan-cache.md b/sql-prepared-plan-cache.md index 2c3bb789993f3..38728b9a2c7ca 100644 --- a/sql-prepared-plan-cache.md +++ b/sql-prepared-plan-cache.md @@ -20,7 +20,7 @@ TiDB also supports execution plan caching for some non-`PREPARE` statements, sim In the current version of TiDB, if a `Prepare` statement meets any of the following conditions, the query or the plan is not cached: - The query contains SQL statements other than `SELECT`, `UPDATE`, `INSERT`, `DELETE`, `Union`, `Intersect`, and `Except`. -- The query accesses partitioned tables or temporary tables, or a table that contains generated columns. +- The query accesses partitioned tables or temporary tables. - The query contains non-correlated sub-queries, such as `SELECT * FROM t1 WHERE t1.a > (SELECT 1 FROM t2 WHERE t2.b < 1)`. - The query contains correlated sub-queries with `PhysicalApply` operators in the execution plan, such as `SELECT * FROM t1 WHERE t1.a > (SELECT a FROM t2 WHERE t1.b > t2.b)`. - The query contains the `ignore_plan_cache` or `set_var` hint, such as `SELECT /*+ ignore_plan_cache() */ * FROM t` or `SELECT /*+ set_var(max_execution_time=1) */ * FROM t`. From c26dd884f577724490d44868610a1084250139dc Mon Sep 17 00:00:00 2001 From: ris <79858083+RidRisR@users.noreply.github.com> Date: Mon, 18 Mar 2024 23:42:42 -0700 Subject: [PATCH 57/82] Update minimum value for initial-scan-rate-limit (#16549) --- tikv-configuration-file.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tikv-configuration-file.md b/tikv-configuration-file.md index e3c1d4e321a35..a29420e150cbc 100644 --- a/tikv-configuration-file.md +++ b/tikv-configuration-file.md @@ -2145,6 +2145,7 @@ Configuration items related to log backup. + The rate limit on throughput in an incremental data scan during log backup, which means the maximum amount of data that can be read from the disk per second. Note that if you only specify a number (for example, `60`), the unit is Byte instead of KiB. + Default value: 60MiB ++ Minimum value: 1MiB ### `max-flush-interval` New in v6.2.0 From 994def2eb2ae23fc6681bef766a8a41ca376d262 Mon Sep 17 00:00:00 2001 From: Aolin Date: Tue, 19 Mar 2024 15:23:13 +0800 Subject: [PATCH 58/82] create-index: remove the description that no stats are collected for mv index (#16412) --- sql-statements/sql-statement-create-index.md | 1 - 1 file changed, 1 deletion(-) diff --git a/sql-statements/sql-statement-create-index.md b/sql-statements/sql-statement-create-index.md index 39d8775e86d4b..2211011be0ddd 100644 --- a/sql-statements/sql-statement-create-index.md +++ b/sql-statements/sql-statement-create-index.md @@ -342,7 +342,6 @@ See [Index Selection - Use multi-valued indexes](/choose-index.md#use-multi-valu - Compared with normal indexes, DML operations will modify more index records for multi-valued indexes, so multi-valued indexes will have a greater performance impact than normal indexes. - Because multi-valued indexes are a special type of expression index, multi-valued indexes have the same limitations as expression indexes. - If a table uses multi-valued indexes, you cannot back up, replicate, or import the table using BR, TiCDC, or TiDB Lightning to a TiDB cluster earlier than v6.6.0. -- Since improvements to the statistics for multi-valued indexes are still ongoing, when a query hits multiple multi-valued indexes, TiDB might not be able to select the optimal index. In such cases, it is recommended to use the [`use_index_merge`](/optimizer-hints.md#use_index_merget1_name-idx1_name--idx2_name-) optimizer hint to enforce a fixed execution plan. For detailed steps, refer to [Use multi-valued indexes](/choose-index.md#use-multi-valued-indexes). - For a query with complex conditions, TiDB might not be able to select multi-valued indexes. For information on the condition patterns supported by multi-valued indexes, refer to [Use multi-valued indexes](/choose-index.md#use-multi-valued-indexes). ## Invisible index From aca59295d4b31e1dd10923d80d4cc98c7b279a27 Mon Sep 17 00:00:00 2001 From: xixirangrang Date: Tue, 19 Mar 2024 20:30:42 +0800 Subject: [PATCH 59/82] add explaination for log densitive feat (#16705) --- system-variables.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/system-variables.md b/system-variables.md index 3e021c6ccd656..24d464d7d2bed 100644 --- a/system-variables.md +++ b/system-variables.md @@ -4784,10 +4784,17 @@ SHOW WARNINGS; - Scope: SESSION | GLOBAL - Persists to cluster: Yes - Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No -- Type: Boolean +- Type: Enumeration - Default value: `OFF` -- This variable controls whether to hide user information in the SQL statement being recorded into the TiDB log and slow log. -- When you set the variable to `1`, user information is hidden. For example, if the executed SQL statement is `insert into t values (1,2)`, the statement is recorded as `insert into t values (?,?)` in the log. +- Possible values: `OFF`, `ON`, `MARKER` +- This variable controls whether to hide the user information in the SQL statement being recorded into the TiDB log and slow log. +- The default value is `OFF`, which means that the user information is not processed in any way. +- When you set the variable to `ON`, the user information is hidden. For example, if the executed SQL statement is `INSERT INTO t VALUES (1,2)`, the statement is recorded as `INSERT INTO t VALUES (?,?)` in the log. +- When you set the variable to `MARKER`, the user information is wrapped in `‹ ›`. For example, if the executed SQL statement is `INSERT INTO t VALUES (1,2)`, the statement is recorded as `INSERT INTO t VALUES (‹1›,‹2›)` in the log. If the input has `‹`, it is escaped as `‹‹`, and `›` is escaped as `››`. Based on the marked logs, you can decide whether to desensitize the marked information when the logs are displayed. + +> **Warning:** +> +> The `MARKER` option is experimental. It is not recommended that you use it in the production environment. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub. ### tidb_regard_null_as_point New in v5.4.0 From 55af1afd19f1a4ff01b8dd9f8f5fdeab1121b0c0 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Tue, 19 Mar 2024 13:39:42 +0100 Subject: [PATCH 60/82] Removed the limitation on plan cache for partitioned tables. (#16359) --- optimizer-fix-controls.md | 8 +++++++- partitioned-table.md | 2 +- sql-non-prepared-plan-cache.md | 2 +- sql-prepared-plan-cache.md | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/optimizer-fix-controls.md b/optimizer-fix-controls.md index de8b98807d664..e79f2613bb480 100644 --- a/optimizer-fix-controls.md +++ b/optimizer-fix-controls.md @@ -26,6 +26,12 @@ SET SESSION tidb_opt_fix_control = '44262:ON,44389:ON'; ## Optimizer Fix Controls reference +### [`33031`](https://github.com/pingcap/tidb/issues/33031) New in v8.0.0 + +- Default value: `OFF` +- Possible values: `ON`, `OFF` +- This variable controls whether to allow plan cache for partitioned tables. If it is set to `ON`, neither [Prepared statement plan cache](/sql-prepared-plan-cache.md) nor [Non-prepared statement plan cache](/sql-non-prepared-plan-cache.md) will be enabled for [partitioned tables](/partitioned-table.md). + ### [`44262`](https://github.com/pingcap/tidb/issues/44262) New in v6.5.3 and v7.2.0 - Default value: `OFF` @@ -63,4 +69,4 @@ SET SESSION tidb_opt_fix_control = '44262:ON,44389:ON'; - Default value: `1000` - Possible values: `[0, 2147483647]` - This variable sets the threshold for the optimizer's heuristic strategy to select access paths. If the estimated rows for an access path (such as `Index_A`) is much smaller than that of other access paths (default `1000` times), the optimizer skips the cost comparison and directly selects `Index_A`. -- `0` means to disable this heuristic strategy. \ No newline at end of file +- `0` means to disable this heuristic strategy. diff --git a/partitioned-table.md b/partitioned-table.md index 9d4de51a37997..1f614f01babaa 100644 --- a/partitioned-table.md +++ b/partitioned-table.md @@ -1999,7 +1999,7 @@ mysql> explain select /*+ TIDB_INLJ(t1, t2) */ t1.* from t1, t2 where t2.code = From example 2, you can see that in `dynamic` mode, the execution plan with IndexJoin is selected when you execute the query. -Currently, neither `static` nor `dynamic` pruning mode supports prepared statements plan cache. +Currently, `static` pruning mode does not support plan cache for both prepared and non-prepared statements. #### Update statistics of partitioned tables in dynamic pruning mode diff --git a/sql-non-prepared-plan-cache.md b/sql-non-prepared-plan-cache.md index 35eb61467fd5b..1378361f75c97 100644 --- a/sql-non-prepared-plan-cache.md +++ b/sql-non-prepared-plan-cache.md @@ -87,7 +87,7 @@ Due to the preceding risks and the fact that the execution plan cache only provi - Queries that filter on columns of `JSON`, `ENUM`, `SET`, or `BIT` type are not supported, such as `SELECT * FROM t WHERE json_col = '{}'`. - Queries that filter on `NULL` values are not supported, such as `SELECT * FROM t WHERE a is NULL`. - Queries with more than 200 parameters after parameterization are not supported by default, such as `SELECT * FROM t WHERE a in (1, 2, 3, ... 201)`. Starting from v7.3.0, you can modify this limit by setting the [`44823`](/optimizer-fix-controls.md#44823-new-in-v730) fix in the [`tidb_opt_fix_control`](/system-variables.md#tidb_opt_fix_control-new-in-v653-and-v710) system variable. -- Queries that access partitioned tables, virtual columns, temporary tables, views, or memory tables are not supported, such as `SELECT * FROM INFORMATION_SCHEMA.COLUMNS`, where `COLUMNS` is a TiDB memory table. +- Queries that access virtual columns, temporary tables, views, or memory tables are not supported, such as `SELECT * FROM INFORMATION_SCHEMA.COLUMNS`, where `COLUMNS` is a TiDB memory table. - Queries with hints or bindings are not supported. - DML statements or `SELECT` statements with the `FOR UPDATE` clause are not supported by default. To remove this restriction, you can execute `SET tidb_enable_non_prepared_plan_cache_for_dml = ON`. diff --git a/sql-prepared-plan-cache.md b/sql-prepared-plan-cache.md index 38728b9a2c7ca..07786ff8d2e05 100644 --- a/sql-prepared-plan-cache.md +++ b/sql-prepared-plan-cache.md @@ -20,7 +20,7 @@ TiDB also supports execution plan caching for some non-`PREPARE` statements, sim In the current version of TiDB, if a `Prepare` statement meets any of the following conditions, the query or the plan is not cached: - The query contains SQL statements other than `SELECT`, `UPDATE`, `INSERT`, `DELETE`, `Union`, `Intersect`, and `Except`. -- The query accesses partitioned tables or temporary tables. +- The query accesses temporary tables, or a table that contains generated columns. - The query contains non-correlated sub-queries, such as `SELECT * FROM t1 WHERE t1.a > (SELECT 1 FROM t2 WHERE t2.b < 1)`. - The query contains correlated sub-queries with `PhysicalApply` operators in the execution plan, such as `SELECT * FROM t1 WHERE t1.a > (SELECT a FROM t2 WHERE t1.b > t2.b)`. - The query contains the `ignore_plan_cache` or `set_var` hint, such as `SELECT /*+ ignore_plan_cache() */ * FROM t` or `SELECT /*+ set_var(max_execution_time=1) */ * FROM t`. From 1966294dd1bbf91730397a517315c97fc267a97b Mon Sep 17 00:00:00 2001 From: Aolin Date: Wed, 20 Mar 2024 14:15:42 +0800 Subject: [PATCH 61/82] Doc for Pipelined DML (#16704) --- configure-memory-usage.md | 4 ++++ system-variables.md | 25 +++++++++++++++++++++++++ tidb-configuration-file.md | 2 ++ 3 files changed, 31 insertions(+) diff --git a/configure-memory-usage.md b/configure-memory-usage.md index ebc11d7382155..18f2c20cb0531 100644 --- a/configure-memory-usage.md +++ b/configure-memory-usage.md @@ -130,6 +130,10 @@ The following example constructs a memory-intensive SQL statement that triggers 5. By checking the directory of status files (In the preceding example, the directory is `/tiup/deploy/tidb-4000/log/oom_record`), you can see a record directory with the corresponding timestamp (for example, `record2022-10-09T17:18:38+08:00`). The record directory includes three files: `goroutinue`, `heap`, and `running_sql`. These three files are suffixed with the time when status files are logged. They respectively record goroutine stack information, the usage status of heap memory, and the running SQL information when the alarm is triggered. For the content in `running_sql`, refer to [`expensive-queries`](/identify-expensive-queries.md). +## Reduce the memory usage for write transactions in tidb-server + +The transaction model used by TiDB requires that all write operations of transactions are first cached in memory before being committed. When TiDB writes large transactions, memory usage might increase and become a bottleneck. To reduce or avoid high memory usage by large transactions under various constraints, you can adjust the [`tidb_dml_type`](/system-variables.md#tidb_dml_type-new-in-v800) system variable to `"bulk"` or use [Non-transactional DML statements](/non-transactional-dml.md). + ## Other memory control behaviors of tidb-server ### Flow control diff --git a/system-variables.md b/system-variables.md index 24d464d7d2bed..83f8c000989b0 100644 --- a/system-variables.md +++ b/system-variables.md @@ -1806,6 +1806,31 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; > > Starting from v7.0.0, `tidb_dml_batch_size` no longer takes effect on the [`LOAD DATA` statement](/sql-statements/sql-statement-load-data.md). +### tidb_dml_type New in v8.0.0 + +> **Warning:** +> +> The bulk DML execution mode (`tidb_dml_type = "bulk"`) is an experimental feature. It is not recommended that you use it in the production environment. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues). When TiDB performs large transactions using the bulk DML mode, it might affect the memory usage and execution efficiency of TiCDC, TiFlash, and the resolved-ts module of TiKV, and might cause OOM issues. Therefore, it is not recommended to use this mode when these components or features are enabled. + +- Scope: SESSION +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes +- Type: String +- Default value: `"standard"` +- Value options: `"standard"`, `"bulk"` +- This variable controls the execution mode of DML statements. + - `"standard"` indicates the standard DML execution mode, where TiDB transactions are cached in memory before being committed. This mode is suitable for high-concurrency transaction scenarios with potential conflicts and is the default recommended execution mode. + - `"bulk"` indicates the bulk DML execution mode, which is suitable for scenarios where a large amount of data is written, causing excessive memory usage in TiDB. + - During the execution of TiDB transactions, the data is not fully cached in the TiDB memory, but is continuously written to TiKV to reduce memory usage and smooth the write pressure. + - Only `INSERT`, `UPDATE`, `REPLACE`, and `DELETE` statements are affected by the `"bulk"` mode. + - `"bulk"` mode is only suitable for scenarios where a large amount of **data is written without conflicts**. This mode is not efficient for handling write conflicts, as write-write conflicts might cause large transactions to fail and be rolled back. + - `"bulk"` mode only takes effect on statements with auto-commit enabled, and requires the [`pessimistic-auto-commit`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#pessimistic-auto-commit-new-in-v600) configuration item to be set to `false`. + - When using the `"bulk"` mode to execute statements, ensure that the [metadata lock](/metadata-lock.md) remains enabled during the execution process. + - `"bulk"` mode cannot be used on [temporary tables](/temporary-tables.md) and [cached tables](/cached-tables.md). + - `"bulk"` mode cannot be used on tables containing foreign keys and tables referenced by foreign keys when the foreign key constraint check is enabled (`foreign_key_checks = ON`). + - In situations that the environment does not support or is incompatible with the `"bulk"` mode, TiDB falls back to the `"standard"` mode and returns a warning message. To verify if the `"bulk"` mode is used, you can check the `pipelined` field using [`tidb_last_txn_info`](#tidb_last_txn_info-new-in-v409). A `true` value indicates that the `"bulk"` mode is used. + - When executing large transactions in the `"bulk"` mode, the transaction duration might be long. For transactions in this mode, the maximum TTL of the transaction lock is the greater value between [`max-txn-ttl`](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#max-txn-ttl) and 24 hours. Additionally, if the transaction execution time exceeds the value set by [`tidb_gc_max_wait_time`](#tidb_gc_max_wait_time-new-in-v610), the GC might force a rollback of the transaction, leading to its failure. + - This mode is implemented by the Pipelined DML feature. For detailed design and GitHub issues, see [Pipelined DML](https://github.com/pingcap/tidb/blob/master/docs/design/2024-01-09-pipelined-DML.md) and [#50215](https://github.com/pingcap/tidb/issues/50215). + ### tidb_enable_1pc New in v5.0 > **Note:** diff --git a/tidb-configuration-file.md b/tidb-configuration-file.md index 706a66ce6ea29..88643fa2b1142 100644 --- a/tidb-configuration-file.md +++ b/tidb-configuration-file.md @@ -488,6 +488,7 @@ Configuration items related to performance. - Default value: `3600000` - Unit: Millisecond - The transaction that holds locks longer than this time can only be committed or rolled back. The commit might not be successful. +- For transactions executed using the [`"bulk"` DML mode](/system-variables.md#tidb_dml_type-new-in-v800), the maximum TTL can exceed the limit of this configuration item. The maximum value is the greater value between this configuration item and 24 hours. ### `stmt-count-limit` @@ -841,6 +842,7 @@ For pessimistic transaction usage, refer to [TiDB Pessimistic Transaction Mode]( + Determines the transaction mode that the auto-commit transaction uses when the pessimistic transaction mode is globally enabled (`tidb_txn_mode='pessimistic'`). By default, even if the pessimistic transaction mode is globally enabled, the auto-commit transaction still uses the optimistic transaction mode. After enabling `pessimistic-auto-commit` (set to `true`), the auto-commit transaction also uses pessimistic mode, which is consistent with the other explicitly committed pessimistic transactions. + For scenarios with conflicts, after enabling this configuration, TiDB includes auto-commit transactions into the global lock-waiting management, which avoids deadlocks and mitigates the latency spike brought by deadlock-causing conflicts. + For scenarios with no conflicts, if there are many auto-commit transactions (the specific number is determined by the real scenarios. For example, the number of auto-commit transactions accounts for more than half of the total number of applications), and a single transaction operates a large data volume, enabling this configuration causes performance regression. For example, the auto-commit `INSERT INTO SELECT` statement. ++ When the session-level system variable [`tidb_dml_type`](/system-variables.md#tidb_dml_type-new-in-v800) is set to `"bulk"`, the effect of this configuration in the session is equivalent to setting it to `false`. + Default value: `false` ### constraint-check-in-place-pessimistic New in v6.4.0 From b5780fe894196725ad354d28e9621fbd044838ae Mon Sep 17 00:00:00 2001 From: xzhangxian1008 Date: Wed, 20 Mar 2024 14:59:13 +0800 Subject: [PATCH 62/82] Spill of parallel aggregation in TiDB (#15755) --- configure-memory-usage.md | 14 +++----------- system-variables.md | 13 +++++++++++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/configure-memory-usage.md b/configure-memory-usage.md index 18f2c20cb0531..de90b3dbde9d9 100644 --- a/configure-memory-usage.md +++ b/configure-memory-usage.md @@ -149,8 +149,8 @@ TiDB supports disk spill for execution operators. When the memory usage of a SQL - The disk spill behavior is jointly controlled by the following parameters: [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query), [`tidb_enable_tmp_storage_on_oom`](/system-variables.md#tidb_enable_tmp_storage_on_oom), [`tmp-storage-path`](/tidb-configuration-file.md#tmp-storage-path), and [`tmp-storage-quota`](/tidb-configuration-file.md#tmp-storage-quota). - When the disk spill is triggered, TiDB outputs a log containing the keywords `memory exceeds quota, spill to disk now` or `memory exceeds quota, set aggregate mode to spill-mode`. -- Disk spill for the Sort, MergeJoin, and HashJoin operator is introduced in v4.0.0; disk spill for the HashAgg operator is introduced in v5.2.0. -- When the SQL executions containing Sort, MergeJoin, or HashJoin cause OOM, TiDB triggers disk spill by default. When SQL executions containing HashAgg cause OOM, TiDB does not trigger disk spill by default. You can configure the system variable `tidb_executor_concurrency = 1` to trigger disk spill for HashAgg. +- Disk spill for the Sort, MergeJoin, and HashJoin operators is introduced in v4.0.0; disk spill for the non-concurrent algorithm of the HashAgg operator is introduced in v5.2.0; disk spill for the concurrent algorithm of the HashAgg operator is introduced in v8.0.0. +- When the SQL executions containing Sort, MergeJoin, HashJoin, or HashAgg cause OOM, TiDB triggers disk spill by default. > **Note:** > @@ -182,15 +182,7 @@ The following example uses a memory-consuming SQL statement to demonstrate the d ERROR 1105 (HY000): Out Of Memory Quota![conn_id=3] ``` -4. Configure the system variable `tidb_executor_concurrency` to 1. With this configuration, when out of memory, HashAgg automatically tries to trigger disk spill. - - {{< copyable "sql" >}} - - ```sql - SET tidb_executor_concurrency = 1; - ``` - -5. Execute the same SQL statement. You can find that this time, the statement is successfully executed and no error message is returned. From the following detailed execution plan, you can see that HashAgg has used 600 MB of hard disk space. +4. Execute the same SQL statement. You can find that this time, the statement is successfully executed and no error message is returned. From the following detailed execution plan, you can see that HashAgg has used 600 MB of hard disk space. {{< copyable "sql" >}} diff --git a/system-variables.md b/system-variables.md index 83f8c000989b0..3ef5f0b131ac1 100644 --- a/system-variables.md +++ b/system-variables.md @@ -2010,6 +2010,19 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; - Default value: `OFF` - This variable controls whether to enable TiDB to collect `PREDICATE COLUMNS`. After enabling the collection, if you disable it, the information of previously collected `PREDICATE COLUMNS` is cleared. For details, see [Collect statistics on some columns](/statistics.md#collect-statistics-on-some-columns). +### tidb_enable_concurrent_hashagg_spill New in v8.0.0 + +> **Warning:** +> +> Currently, the feature controlled by this variable is experimental. It is not recommended that you use it in production environments. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub. + +- Scope: SESSION | GLOBAL +- Persists to cluster: Yes +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No +- Type: Boolean +- Default value: `ON` +- This variable controls whether TiDB supports disk spill for the concurrent HashAgg algorithm. When it is `ON`, disk spill can be triggered for the concurrent HashAgg algorithm. This variable will be deprecated when this feature is generally available in a future release. + ### tidb_enable_enhanced_security - Scope: NONE From 2598d44a6e8dbb18712317c9b5210b5eed7fc5cd Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 20 Mar 2024 15:14:13 +0800 Subject: [PATCH 63/82] dm: support customized secret key (#16740) --- TOC.md | 1 + dm/dm-command-line-flags.md | 18 +++++---------- dm/dm-customized-secret-key.md | 36 ++++++++++++++++++++++++++++++ dm/dm-export-import-config.md | 2 +- dm/dm-manage-source.md | 6 ++++- dm/dm-master-configuration-file.md | 5 ++++- dm/dmctl-introduction.md | 2 -- dm/maintain-dm-using-tiup.md | 6 ++++- dm/quick-start-create-source.md | 2 ++ dm/quick-start-create-task.md | 4 ++++ dm/quick-start-with-dm.md | 2 +- 11 files changed, 65 insertions(+), 19 deletions(-) create mode 100644 dm/dm-customized-secret-key.md diff --git a/TOC.md b/TOC.md index f76d89486e3c6..f1e45a1f520dd 100644 --- a/TOC.md +++ b/TOC.md @@ -446,6 +446,7 @@ - [Binlog Event Filter](/dm/dm-binlog-event-filter.md) - [Filter DMLs Using SQL Expressions](/dm/feature-expression-filter.md) - [Online DDL Tool Support](/dm/dm-online-ddl-tool-support.md) + - [Customize a Secret Key for Encryption and Decryption](/dm/dm-customized-secret-key.md) - Manage a Data Migration Task - [Precheck a Task](/dm/dm-precheck.md) - [Create a Task](/dm/dm-create-task.md) diff --git a/dm/dm-command-line-flags.md b/dm/dm-command-line-flags.md index e9712359c3c35..33759c9305483 100644 --- a/dm/dm-command-line-flags.md +++ b/dm/dm-command-line-flags.md @@ -75,6 +75,12 @@ This document introduces DM's command-line flags. - The default value is `"http://127.0.0.1:8291"` - Required flag +### `--secret-key-path` + +- The path of the customized secret key for encryption and decryption +- The default value is `""` +- Optional flag + ## DM-worker ### `--advertise-addr` @@ -132,15 +138,3 @@ This document introduces DM's command-line flags. - The `{advertise-addr}` of any DM-master node in the cluster to be connected by dmctl - The default value is `""` - It is a required flag when dmctl interacts with DM-master - -### `--encrypt` - -- Encrypts the plaintext database password into ciphertext -- The default value is `""` -- When this flag is specified, it is only used to encrypt the plaintext without interacting with the DM-master - -### `--decrypt` - -- Decrypts ciphertext encrypted with dmctl into plaintext -- The default value is `""` -- When this flag is specified, it is only used to decrypt the ciphertext without interacting with the DM-master diff --git a/dm/dm-customized-secret-key.md b/dm/dm-customized-secret-key.md new file mode 100644 index 0000000000000..af71bb0bdf4bc --- /dev/null +++ b/dm/dm-customized-secret-key.md @@ -0,0 +1,36 @@ +--- +title: Customize a Secret Key for DM Encryption and Decryption +summary: Learn how to customize a secret key to encrypt and decrypt passwords used in the DM(Data Migration)data source and migration task configurations. +--- + +# Customize a Secret Key for DM Encryption and Decryption + +Before v8.0.0, [DM](/dm/dm-overview.md) uses a [fixed AES-256 secret key](https://github.com/pingcap/tiflow/blob/1252979421fc83ffa2a1548d981e505f7fc0b909/dm/pkg/encrypt/encrypt.go#L27) to encrypt and decrypt passwords in the data source and migration task configurations. However, using a fixed secret key might pose security risks, especially in environments where security is crucial. To enhance security, starting from v8.0.0, DM removes the fixed secret key and enables you to customize a secret key. + +## Usage + +1. Create a custom key file, which must contain a 64-character hexadecimal AES-256 secret key. +2. In the DM-master [command-line flags](/dm/dm-command-line-flags.md) or [configuration file](/dm/dm-master-configuration-file.md), specify `secret-key-path` as the path of your custom key file. + +## Upgrade from a version earlier than v8.0.0 + +Because DM no longer uses the fixed secret key starting from v8.0.0, pay attention to the following when upgrading DM from versions earlier than v8.0.0: + +- If plaintext passwords are used in both [data source configurations](/dm/dm-source-configuration-file.md) and [migration task configurations](/dm/task-configuration-file-full.md), no additional steps are required for the upgrade. +- If encrypted passwords are used in [data source configurations](/dm/dm-source-configuration-file.md) and [migration task configurations](/dm/task-configuration-file-full.md) or if you want to use encrypted passwords in the future, you need to do the following: + 1. Add the `secret-key-path` parameter to the [DM-master configuration file](/dm/dm-master-configuration-file.md) and specify it as the path of your custom key file. The file must contain a 64-character hexadecimal AES-256 key. If the [fixed AES-256 secret key](https://github.com/pingcap/tiflow/blob/1252979421fc83ffa2a1548d981e505f7fc0b909/dm/pkg/encrypt/encrypt.go#L27) was used for encryption before upgrading, you can copy this secret key to your key file. Make sure all DM-master nodes use the same secret key configuration. + 2. Perform a rolling upgrade of DM-master first, followed by a rolling upgrade of DM-worker. For more information, see [Rolling upgrade](/dm/maintain-dm-using-tiup.md#rolling-upgrade). + +## Update the secret key for encryption and decryption + +To update the secret key used for encryption and decryption, take the following steps: + +1. Update `secret-key-path` in the [DM-master configuration file](/dm/dm-master-configuration-file.md). + + > **Note:** + > + > - Make sure all DM-master nodes are updated to the same secret key configuration. + > - During the secret key update, do not create new [data source configuration files](/dm/dm-source-configuration-file.md) or [migration task configuration files](/dm/task-configuration-file-full.md). + +2. Perform a rolling restart of DM-master. +3. Use the passwords encrypted with `tiup dmctl encrypt` (dmctl version >= v8.0.0) when you create new [data source configuration files](/dm/dm-source-configuration-file.md) and [migration task configuration files](/dm/task-configuration-file-full.md). \ No newline at end of file diff --git a/dm/dm-export-import-config.md b/dm/dm-export-import-config.md index a67d4095a8345..50d6f609f8b80 100644 --- a/dm/dm-export-import-config.md +++ b/dm/dm-export-import-config.md @@ -9,7 +9,7 @@ summary: Learn how to export and import data sources and task configuration of c > **Note:** > -> For clusters earlier than v2.0.5, you can use dmctl v2.0.5 or later to export and import the data source and task configuration files. +> For clusters earlier than v2.0.5, you can use dmctl (>= v2.0.5 and < v8.0.0) to export and import the data source and task configuration files. {{< copyable "" >}} diff --git a/dm/dm-manage-source.md b/dm/dm-manage-source.md index 511df3caa1986..c84223c314c61 100644 --- a/dm/dm-manage-source.md +++ b/dm/dm-manage-source.md @@ -11,10 +11,14 @@ This document introduces how to manage data source configurations, including enc In DM configuration files, it is recommended to use the password encrypted with dmctl. For one original password, the encrypted password is different after each encryption. +> **Note:** +> +> Starting from v8.0.0, you must configure [`secret-key-path`](/dm/dm-master-configuration-file.md) for DM-master before using the `dmctl encrypt` command. + {{< copyable "shell-regular" >}} ```bash -./dmctl -encrypt 'abc!@#123' +./dmctl encrypt 'abc!@#123' ``` ``` diff --git a/dm/dm-master-configuration-file.md b/dm/dm-master-configuration-file.md index d32617c5b591f..ec58677c0ab18 100644 --- a/dm/dm-master-configuration-file.md +++ b/dm/dm-master-configuration-file.md @@ -34,7 +34,9 @@ join = "" ssl-ca = "/path/to/ca.pem" ssl-cert = "/path/to/cert.pem" ssl-key = "/path/to/key.pem" -cert-allowed-cn = ["dm"] +cert-allowed-cn = ["dm"] + +secret-key-path = "/path/to/secret/key" ``` ## Configuration parameters @@ -58,3 +60,4 @@ This section introduces the configuration parameters of DM-master. | `ssl-cert` | The path of the file that contains X509 certificate in PEM format for DM-master to connect with other components. | | `ssl-key` | The path of the file that contains X509 key in PEM format for DM-master to connect with other components. | | `cert-allowed-cn` | Common Name list. | +| `secret-key-path` | The file path of the secret key, which is used to encrypt and decrypt upstream and downstream passwords. The file must contain a 64-character hexadecimal AES-256 secret key. | \ No newline at end of file diff --git a/dm/dmctl-introduction.md b/dm/dmctl-introduction.md index a14f4598b1d76..b3d479de9957d 100644 --- a/dm/dmctl-introduction.md +++ b/dm/dmctl-introduction.md @@ -45,7 +45,6 @@ Available Commands: binlog-schema manage or show table schema in schema tracker check-task Checks the configuration file of the task config manage config operations - decrypt Decrypts cipher text to plain text encrypt Encrypts plain text to cipher text help Gets help about any command list-member Lists member information @@ -98,7 +97,6 @@ Available Commands: binlog-schema manage or show table schema in schema tracker check-task Checks the configuration file of the task config manage config operations - decrypt Decrypts cipher text to plain text encrypt Encrypts plain text to cipher text help Gets help about any command list-member Lists member information diff --git a/dm/maintain-dm-using-tiup.md b/dm/maintain-dm-using-tiup.md index 49d50316ae334..5707edc917d46 100644 --- a/dm/maintain-dm-using-tiup.md +++ b/dm/maintain-dm-using-tiup.md @@ -183,7 +183,7 @@ For example, to scale out a DM-worker node in the `prod-cluster` cluster, take t > > Before upgrading, you can use `config export` to export the configuration files of clusters. After upgrading, if you need to downgrade to an earlier version, you can first redeploy the earlier cluster and then use `config import` to import the previous configuration files. > -> For clusters earlier than v2.0.5, you can use dmctl v2.0.5 or later to export and import the data source and task configuration files. +> For clusters earlier than v2.0.5, you can use dmctl (>= v2.0.5 and < v8.0.0) to export and import the data source and task configuration files. > > For clusters later than v2.0.2, currently, it is not supported to automatically import the configuration related to relay worker. You can use `start-relay` command to manually [start relay log](/dm/relay-log.md#enable-and-disable-relay-log). @@ -193,6 +193,10 @@ The rolling upgrade process is made as transparent as possible to the applicatio You can run the `tiup dm upgrade` command to upgrade a DM cluster. For example, the following command upgrades the cluster to `${version}`. Modify `${version}` to your needed version before running this command: +> **Note:** +> +> Starting from v8.0.0, DM removes the fixed secret key for encryption and decryption and enables you to customize a secret key for encryption and decryption. If encrypted passwords are used in [data source configurations](/dm/dm-source-configuration-file.md) and [migration task configurations](/dm/task-configuration-file-full.md) before the upgrade, you need to refer to the upgrade steps in [Customize a Secret Key for DM Encryption and Decryption](/dm/dm-customized-secret-key.md) for additional operations. + {{< copyable "shell-regular" >}} ```bash diff --git a/dm/quick-start-create-source.md b/dm/quick-start-create-source.md index 23886f4eaf8b9..a3af12981f8a6 100644 --- a/dm/quick-start-create-source.md +++ b/dm/quick-start-create-source.md @@ -19,6 +19,8 @@ A data source contains the information for accessing the upstream migration task In DM configuration files, it is recommended to use the password encrypted with dmctl. You can follow the example below to obtain the encrypted password of the data source, which can be used to write the configuration file later. + Starting from v8.0.0, you must configure [`secret-key-path`](/dm/dm-master-configuration-file.md) for DM-master before using the `tiup dmctl encrypt` command. + {{< copyable "shell-regular" >}} ```bash diff --git a/dm/quick-start-create-task.md b/dm/quick-start-create-task.md index 42828fbf32a9b..e4888d3dab432 100644 --- a/dm/quick-start-create-task.md +++ b/dm/quick-start-create-task.md @@ -97,6 +97,10 @@ Before starting a data migration task, you need to configure the MySQL data sour For safety reasons, it is recommended to configure and use encrypted passwords. You can use dmctl to encrypt the MySQL/TiDB password. Suppose the password is "123456": +> **Note:** +> +> Starting from v8.0.0, you must configure [`secret-key-path`](/dm/dm-master-configuration-file.md) for DM-master before using the `dmctl encrypt` command. + {{< copyable "shell-regular" >}} ```bash diff --git a/dm/quick-start-with-dm.md b/dm/quick-start-with-dm.md index 75231181e152d..26c30a4a2b9d9 100644 --- a/dm/quick-start-with-dm.md +++ b/dm/quick-start-with-dm.md @@ -48,7 +48,7 @@ You can use one or multiple MySQL instances as an upstream data source. from: host: "127.0.0.1" user: "root" - password: "fCxfQ9XKCezSzuCD0Wf5dUD+LsKegSg=" # encrypt with `tiup dmctl --encrypt "123456"` + password: "fCxfQ9XKCezSzuCD0Wf5dUD+LsKegSg=" port: 3306 ``` From 1e14467ad5b90c8f6e965c2e433e021a50952632 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Wed, 20 Mar 2024 15:29:14 +0800 Subject: [PATCH 64/82] encryption: add tikv kms encryption for gcp and azure (#16761) --- encryption-at-rest.md | 134 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 118 insertions(+), 16 deletions(-) diff --git a/encryption-at-rest.md b/encryption-at-rest.md index 14ec3d239083e..feefd9066b94c 100644 --- a/encryption-at-rest.md +++ b/encryption-at-rest.md @@ -22,7 +22,7 @@ When a TiDB cluster is deployed, the majority of user data is stored on TiKV and TiKV supports encryption at rest. This feature allows TiKV to transparently encrypt data files using [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) or [SM4](https://en.wikipedia.org/wiki/SM4_(cipher)) in [CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation) mode. To enable encryption at rest, an encryption key must be provided by the user and this key is called master key. TiKV automatically rotates data keys that it used to encrypt actual data files. Manually rotating the master key can be done occasionally. Note that encryption at rest only encrypts data at rest (namely, on disk) and not while data is transferred over network. It is advised to use TLS together with encryption at rest. -Optionally, you can use AWS KMS for both cloud and self-hosted deployments. You can also supply the plaintext master key in a file. +You can use Key Management Service (KMS) for both cloud and self-hosted deployments or supply the plaintext master key in a file. TiKV currently does not exclude encryption keys and user data from core dumps. It is advised to disable core dumps for the TiKV process when using encryption at rest. This is not currently handled by TiKV itself. @@ -59,7 +59,7 @@ TiKV currently supports encrypting data using AES128, AES192, AES256, or SM4 (on * Master key. The master key is provided by user and is used to encrypt the data keys TiKV generates. Management of master key is external to TiKV. * Data key. The data key is generated by TiKV and is the key actually used to encrypt data. -The same master key can be shared by multiple instances of TiKV. The recommended way to provide a master key in production is via AWS KMS. Create a customer master key (CMK) through AWS KMS, and then provide the CMK key ID to TiKV in the configuration file. The TiKV process needs access to the KMS CMK while it is running, which can be done by using an [IAM role](https://aws.amazon.com/iam/). If TiKV fails to get access to the KMS CMK, it will fail to start or restart. Refer to AWS documentation for [KMS](https://docs.aws.amazon.com/kms/index.html) and [IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) usage. +The same master key can be shared by multiple instances of TiKV. The recommended way to provide a master key in production is via KMS. Currently, TiKV supports KMS encryption on [AWS](https://docs.aws.amazon.com/kms/index.html), [Google Cloud](https://cloud.google.com/security/products/security-key-management?hl=en), and [Azure](https://learn.microsoft.com/en-us/azure/key-vault/). To enable KMS encryption, you need to create a customer master key (CMK) through KMS, and then provide the CMK key ID to TiKV using the configuration file. If TiKV fails to get access to the KMS CMK, it will fail to start or restart. Alternatively, if using custom key is desired, supplying the master key via file is also supported. The file must contain a 256 bits (or 32 bytes) key encoded as hex string, end with a newline (namely, `\n`), and contain nothing else. Persisting the key on disk, however, leaks the key, so the key file is only suitable to be stored on the `tempfs` in RAM. @@ -67,9 +67,40 @@ Data keys are passed to the underlying storage engine (namely, RocksDB). All fil Regardless of data encryption method, data keys are encrypted using AES256 in GCM mode for additional authentication. This required the master key to be 256 bits (32 bytes), when passing from file instead of KMS. -### Key creation +### Configure encryption + +To enable encryption, you can add the encryption section in the configuration files of TiKV and PD: + +``` +[security.encryption] +data-encryption-method = "aes128-ctr" +data-key-rotation-period = "168h" # 7 days +``` + +- `data-encryption-method` specifies the encryption algorithm. The possible values are `"aes128-ctr"`, `"aes192-ctr"`, `"aes256-ctr"`, `"sm4-ctr"` (only for v6.3.0 and later versions), and `"plaintext"`. The default value is `"plaintext"`, which means that encryption is disabled by default. + + - For a new TiKV cluster or an existing TiKV cluster, only data written after encryption has been enabled is guaranteed to be encrypted. + - To disable encryption after it is enabled, remove `data-encryption-method` from the configuration file or set its value to `"plaintext"`, and then restart TiKV. + - To change the encryption algorithm, replace the value of `data-encryption-method` with a supported encryption algorithm, and then restart TiKV. After the replacement, as new data is written in, the encryption files generated by the previous encryption algorithm are gradually rewritten to files generated by the new encryption algorithm. + +- `data-key-rotation-period` specifies how often TiKV rotates keys. + +If encryption is enabled (that is, the value of `data-encryption-method` is not `"plaintext"`), you must specify a master key in either of the following ways: + +- [Specify a master key via KMS](#specify-a-master-key-via-kms) +- [Specify a master key via a file](#specify-a-master-key-via-a-file) -To create a key on AWS, follow these steps: +#### Specify a master key via KMS + +TiKV supports KMS encryption for three platforms: AWS, Google Cloud, and Azure. Depending on the platform where your service is deployed, you can choose one of them to configure KMS encryption. + + + +
+ +**Step 1. Create a master key** + +To create a key on AWS, take the following steps: 1. Go to the [AWS KMS](https://console.aws.amazon.com/kms) on the AWS console. 2. Make sure that you have selected the correct region on the top right corner of your console. @@ -85,19 +116,9 @@ aws --region us-west-2 kms create-alias --alias-name "alias/tidb-tde" --target-k The `--target-key-id` to enter in the second command is in the output of the first command. -### Configure encryption +**Step 2. Configure the master key** -To enable encryption, you can add the encryption section in the configuration files of TiKV and PD: - -``` -[security.encryption] -data-encryption-method = "aes128-ctr" -data-key-rotation-period = "168h" # 7 days -``` - -Possible values for `data-encryption-method` are "aes128-ctr", "aes192-ctr", "aes256-ctr", "sm4-ctr" (only in v6.3.0 and later versions) and "plaintext". The default value is "plaintext", which means encryption is not turned on. `data-key-rotation-period` defines how often TiKV rotates the data key. Encryption can be turned on for a fresh TiKV cluster, or an existing TiKV cluster, though only data written after encryption is enabled is guaranteed to be encrypted. To disable encryption, remove `data-encryption-method` in the configuration file, or reset it to "plaintext", and restart TiKV. To change encryption method, update `data-encryption-method` in the configuration file and restart TiKV. To change the encryption algorithm, replace `data-encryption-method` with a supported encryption algorithm and then restart TiKV. After the replacement, as new data is written in, the encryption file generated by the previous encryption algorithm is gradually rewritten to a file generated by the new encryption algorithm. - -The master key has to be specified if encryption is enabled (that is,`data-encryption-method` is not "plaintext"). To specify a AWS KMS CMK as master key, add the `encryption.master-key` section after the `encryption` section: +To specify the master key using AWS KMS, add the `[security.encryption.master-key]` configuration after the `[security.encryption]` section in the TiKV configuration file: ``` [security.encryption.master-key] @@ -111,6 +132,87 @@ The `key-id` specifies the key ID for the KMS CMK. The `region` is the AWS regio You can also use [multi-Region keys](https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html) in AWS. For this, you need to set up a primary key in a specific region and add replica keys in the regions you require. +
+
+ +**Step 1. Create a master key** + +To create a key on Google Cloud, take the following steps: + +1. Go to the [Key Management](https://console.cloud.google.com/security/kms/keyrings) page in the Google Cloud console. +2. Click **Create key ring**. Enter a name for the key ring, select a location of the key ring, and then click **Create**. Note that the location of the key ring needs to cover the region where the TiDB cluster is deployed. +3. Select the key ring you created in the previous step, and then click **Create Key** on the key ring details page. +4. Enter a name for the key, set the key information as follows, and then click **Create**. + + - **Protection level**: **Software** or **HSM** + - **Key Material**: **Generated key** + - **Purpose**: **Symmetric encrypt/decrypt** + +You can also perform this operation using the gcloud CLI: + +```shell +gcloud kms keyrings create "key-ring-name" --location "global" +gcloud kms keys create "key-name" --keyring "key-ring-name" --location "global" --purpose "encryption" --rotation-period "30d" +``` + +Make sure to replace the values of `"key-ring-name"`, `"key-name"`, `"global"`, and `"30d"` in the preceding command with the names and configurations corresponding to your actual key. + +**Step 2. Configure the master key** + +To specify the master key using Google Cloud KMS, add the `[security.encryption.master-key]` configuration after the `[security.encryption]` section: + +``` +[security.encryption.master-key] +type = "kms" +key-id = "projects/project-name/locations/global/keyRings/key-ring-name/cryptoKeys/key-name" +vendor = "gcp" + +[security.encryption.master-key.gcp] +credential-file-path = "/path/to/credential.json" +``` + +- `key-id` specifies the key ID of the KMS CMK. +- `credential-file-path` specifies the path of the authentication credentials file, which currently supports two types of credentials: Service Account and Authentication User. If the TiKV environment is already configured with [application default credentials](https://cloud.google.com/docs/authentication/application-default-credentials), there is no need to configure `credential-file-path`. + +
+
+ +**Step 1. Create a master key** + +To create a key on Azure, refer to the instructions in [Set and retrieve a key from Azure Key Vault using the Azure portal](https://learn.microsoft.com/en-us/azure/key-vault/keys/quick-create-portal). + +**Step 2. Configure the master key** + +To specify the master key using Azure KMS, add the `[security.encryption.master-key]` configuration after the `[security.encryption]` section in the TiKV configuration file: + +``` +[security.encryption.master-key] +type = 'kms' +key-id = 'your-kms-key-id' +region = 'region-name' +endpoint = 'endpoint' +vendor = 'azure' + +[security.encryption.master-key.azure] +tenant-id = 'tenant_id' +client-id = 'client_id' +keyvault-url = 'keyvault_url' +hsm-name = 'hsm_name' +hsm-url = 'hsm_url' +# The following four fields are optional, used to set client authentication credentials. You can configure them according to the requirements of your scenario. +client_certificate = "" +client_certificate_path = "" +client_certificate_password = "" +client_secret = "" +``` + +Except `vendor`, you need to modify the values of other fields in the preceding configuration to the corresponding configuration of the actual key. + +
+
+ +#### Specify a master key via a file + To specify a master key that's stored in a file, the master key configuration would look like the following: ``` From 3d5a1cb1651a5d78ad2125ed590de15054959cf5 Mon Sep 17 00:00:00 2001 From: lucasliang Date: Wed, 20 Mar 2024 15:33:43 +0800 Subject: [PATCH 65/82] tikv: enable async-io by setting raftstore.store-io-pool-size == 1 as default. (#16735) --- tikv-configuration-file.md | 2 +- tune-tikv-thread-performance.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tikv-configuration-file.md b/tikv-configuration-file.md index a29420e150cbc..53401f6c88969 100644 --- a/tikv-configuration-file.md +++ b/tikv-configuration-file.md @@ -990,7 +990,7 @@ Configuration items related to Raftstore. ### `store-io-pool-size` New in v5.3.0 + The allowable number of threads that process Raft I/O tasks, which is the size of the StoreWriter thread pool. When you modify the size of this thread pool, refer to [Performance tuning for TiKV thread pools](/tune-tikv-thread-performance.md#performance-tuning-for-tikv-thread-pools). -+ Default value: `0` ++ Default value: `1` (Before v8.0.0, the default value is `0`) + Minimum value: `0` ### `future-poll-size` diff --git a/tune-tikv-thread-performance.md b/tune-tikv-thread-performance.md index 43a6b4ef98fc1..36dfc3dd5ce5a 100644 --- a/tune-tikv-thread-performance.md +++ b/tune-tikv-thread-performance.md @@ -61,7 +61,7 @@ Starting from TiKV v5.0, all read requests use the unified thread pool for queri * The Raftstore thread pool. - The Raftstore thread pool is the most complex thread pool in TiKV. The default size (configured by `raftstore.store-pool-size`) of this thread pool is `2`. For the StoreWriter thread pool, the default size (configured by `raftstore.store-io-pool-size`) is `0`. + The Raftstore thread pool is the most complex thread pool in TiKV. The default size (configured by `raftstore.store-pool-size`) of this thread pool is `2`. For the StoreWriter thread pool, the default size (configured by `raftstore.store-io-pool-size`) is `1`. - When the size of the StoreWriter thread pool is 0, all write requests are written into RocksDB in the way of `fsync` by the Raftstore thread. In this case, it is recommended to tune the performance as follows: From 67fb6e6db66b7d6141de55cca1aeeb763d57ba04 Mon Sep 17 00:00:00 2001 From: xixirangrang Date: Wed, 20 Mar 2024 17:29:15 +0800 Subject: [PATCH 66/82] sys-var: add `tidb_schema_cache_size` (#16786) --- system-variables.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/system-variables.md b/system-variables.md index 3ef5f0b131ac1..615d8523d7c4c 100644 --- a/system-variables.md +++ b/system-variables.md @@ -4960,6 +4960,20 @@ SHOW WARNINGS; - By default, Regions are split for a new table when it is being created in TiDB. After this variable is enabled, the newly split Regions are scattered immediately during the execution of the `CREATE TABLE` statement. This applies to the scenario where data need to be written in batches right after the tables are created in batches, because the newly split Regions can be scattered in TiKV beforehand and do not have to wait to be scheduled by PD. To ensure the continuous stability of writing data in batches, the `CREATE TABLE` statement returns success only after the Regions are successfully scattered. This makes the statement's execution time multiple times longer than that when you disable this variable. - Note that if `SHARD_ROW_ID_BITS` and `PRE_SPLIT_REGIONS` have been set when a table is created, the specified number of Regions are evenly split after the table creation. +### tidb_schema_cache_size New in v8.0.0 + +> **Warning:** +> +> This feature is experimental. It is not recommended that you use it in the production environment. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub. + +- Scope: GLOBAL +- Persists to cluster: Yes +- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): Yes +- Type: Integer +- Default value: `0` +- Range: `[0, 9223372036854775807]` +- This variable controls the size of the schema cache in TiDB. The unit is byte. The default value is `0`, which means that the cache limit feature is not enabled. When this feature is enabled, TiDB uses the value you set as the maximum available memory limit, and uses the Least Recently Used (LRU) algorithm to cache the required tables, effectively reducing the memory occupied by the schema information. + ### tidb_schema_version_cache_limit New in v7.4.0 - Scope: GLOBAL From 27c62b50da9c157f0269d2e57d8f987b455218fd Mon Sep 17 00:00:00 2001 From: wk989898 Date: Thu, 21 Mar 2024 10:50:14 +0800 Subject: [PATCH 67/82] ticdc: remove canal protocol document (#16773) --- ticdc/ticdc-faq.md | 8 ++++---- ticdc/ticdc-open-api-v2.md | 2 +- ticdc/ticdc-open-api.md | 2 +- ticdc/ticdc-sink-to-kafka.md | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ticdc/ticdc-faq.md b/ticdc/ticdc-faq.md index 41a2454713f4b..28b64d442dd98 100644 --- a/ticdc/ticdc-faq.md +++ b/ticdc/ticdc-faq.md @@ -108,20 +108,20 @@ If you use the `cdc cli changefeed create` command without specifying the `-conf - Replicates all tables except system tables - Only replicates tables that contain [valid indexes](/ticdc/ticdc-overview.md#best-practices) -## Does TiCDC support outputting data changes in the Canal format? +## Does TiCDC support outputting data changes in the Canal protocol? -Yes. To enable Canal output, specify the protocol as `canal` in the `--sink-uri` parameter. For example: +Yes. Note that for the Canal protocol, TiCDC only supports the JSON output format, while the protobuf format is not officially supported yet. To enable Canal output, specify `protocol` as `canal-json` in the `--sink-uri` configuration. For example: {{< copyable "shell-regular" >}} ```shell -cdc cli changefeed create --server=http://127.0.0.1:8300 --sink-uri="kafka://127.0.0.1:9092/cdc-test?kafka-version=2.4.0&protocol=canal" --config changefeed.toml +cdc cli changefeed create --server=http://127.0.0.1:8300 --sink-uri="kafka://127.0.0.1:9092/cdc-test?kafka-version=2.4.0&protocol=canal-json" --config changefeed.toml ``` > **Note:** > > * This feature is introduced in TiCDC 4.0.2. -> * TiCDC currently supports outputting data changes in the Canal format only to MQ sinks such as Kafka. +> * TiCDC currently supports outputting data changes in the Canal-JSON format only to MQ sinks such as Kafka. For more information, refer to [TiCDC changefeed configurations](/ticdc/ticdc-changefeed-config.md). diff --git a/ticdc/ticdc-open-api-v2.md b/ticdc/ticdc-open-api-v2.md index bdc1b4f41e57e..a31b226f87093 100644 --- a/ticdc/ticdc-open-api-v2.md +++ b/ticdc/ticdc-open-api-v2.md @@ -310,7 +310,7 @@ The `sink` parameters are described as follows: | `date_separator` | `STRING` type. Indicates the date separator type of the file directory. Value options are `none`, `year`, `month`, and `day`. `none` is the default value and means that the date is not separated. (Optional) | | `dispatchers` | An configuration array for event dispatching. (Optional) | | `encoder_concurrency` | `INT` type. The number of encoder threads in the MQ sink. The default value is `16`. (Optional) | -| `protocol` | `STRING` type. For MQ sinks, you can specify the protocol format of the message. The following protocols are currently supported: `canal-json`, `open-protocol`, `canal`, `avro`, and `maxwell`. | +| `protocol` | `STRING` type. For MQ sinks, you can specify the protocol format of the message. The following protocols are currently supported: `canal-json`, `open-protocol`, `avro`, and `maxwell`. | | `schema_registry` | `STRING` type. The schema registry address. (Optional) | | `terminator` | `STRING` type. The terminator is used to separate two data change events. The default value is null, which means `"\r\n"` is used as the terminator. (Optional) | | `transaction_atomicity` | `STRING` type. The atomicity level of the transaction. (Optional) | diff --git a/ticdc/ticdc-open-api.md b/ticdc/ticdc-open-api.md index 2194e7752ebe9..ea24874ea44a3 100644 --- a/ticdc/ticdc-open-api.md +++ b/ticdc/ticdc-open-api.md @@ -163,7 +163,7 @@ The configuration parameters of sink are as follows: `matcher`: The matching syntax of matcher is the same as the filter rule syntax. -`protocol`: For the sink of MQ type, you can specify the protocol format of the message. Currently the following protocols are supported: `canal-json`, `open-protocol`, `canal`, `avro`, and `maxwell`. +`protocol`: For the sink of MQ type, you can specify the protocol format of the message. Currently the following protocols are supported: `canal-json`, `open-protocol`, `avro`, and `maxwell`. ### Example diff --git a/ticdc/ticdc-sink-to-kafka.md b/ticdc/ticdc-sink-to-kafka.md index 0f6af2f2464d9..3fc45116afdd0 100644 --- a/ticdc/ticdc-sink-to-kafka.md +++ b/ticdc/ticdc-sink-to-kafka.md @@ -59,7 +59,7 @@ The following are descriptions of sink URI parameters and values that can be con | `replication-factor` | The number of Kafka message replicas that can be saved (optional, `1` by default). This value must be greater than or equal to the value of [`min.insync.replicas`](https://kafka.apache.org/33/documentation.html#brokerconfigs_min.insync.replicas) in Kafka. | | `required-acks` | A parameter used in the `Produce` request, which notifies the broker of the number of replica acknowledgements it needs to receive before responding. Value options are `0` (`NoResponse`: no response, only `TCP ACK` is provided), `1` (`WaitForLocal`: responds only after local commits are submitted successfully), and `-1` (`WaitForAll`: responds after all replicated replicas are committed successfully. You can configure the minimum number of replicated replicas using the [`min.insync.replicas`](https://kafka.apache.org/33/documentation.html#brokerconfigs_min.insync.replicas) configuration item of the broker). (Optional, the default value is `-1`). | | `compression` | The compression algorithm used when sending messages (value options are `none`, `lz4`, `gzip`, `snappy`, and `zstd`; `none` by default). Note that the Snappy compressed file must be in the [official Snappy format](https://github.com/google/snappy). Other variants of Snappy compression are not supported.| -| `protocol` | The protocol with which messages are output to Kafka. The value options are `canal-json`, `open-protocol`, `canal`, `avro` and `maxwell`. | +| `protocol` | The protocol with which messages are output to Kafka. The value options are `canal-json`, `open-protocol`, `avro` and `maxwell`. | | `auto-create-topic` | Determines whether TiCDC creates the topic automatically when the `topic-name` passed in does not exist in the Kafka cluster (optional, `true` by default). | | `enable-tidb-extension` | Optional. `false` by default. When the output protocol is `canal-json`, if the value is `true`, TiCDC sends [WATERMARK events](/ticdc/ticdc-canal-json.md#watermark-event) and adds the [TiDB extension field](/ticdc/ticdc-canal-json.md#tidb-extension-field) to Kafka messages. From v6.1.0, this parameter is also applicable to the `avro` protocol. If the value is `true`, TiCDC adds [three TiDB extension fields](/ticdc/ticdc-avro-protocol.md#tidb-extension-fields) to the Kafka message. | | `max-batch-size` | New in v4.0.9. If the message protocol supports outputting multiple data changes to one Kafka message, this parameter specifies the maximum number of data changes in one Kafka message. It currently takes effect only when Kafka's `protocol` is `open-protocol` (optional, `16` by default). | From 11c837c0afbe950247d384f7192dcb89800e9255 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Thu, 21 Mar 2024 19:56:15 +0800 Subject: [PATCH 68/82] importinto 8.0 change & DXF enhancement (#16708) --- sql-statements/sql-statement-import-into.md | 154 +++++++++++++------- tidb-distributed-execution-framework.md | 6 +- 2 files changed, 107 insertions(+), 53 deletions(-) diff --git a/sql-statements/sql-statement-import-into.md b/sql-statements/sql-statement-import-into.md index af32895c5f9a8..86f90aa03f47a 100644 --- a/sql-statements/sql-statement-import-into.md +++ b/sql-statements/sql-statement-import-into.md @@ -5,47 +5,49 @@ summary: An overview of the usage of IMPORT INTO in TiDB. # IMPORT INTO -The `IMPORT INTO` statement is used to import data in formats such as `CSV`, `SQL`, and `PARQUET` into an empty table in TiDB via the [Physical Import Mode](https://docs.pingcap.com/tidb/stable/tidb-lightning-physical-import-mode) of TiDB Lightning. +The `IMPORT INTO` statement lets you import data to TiDB via the [Physical Import Mode](https://docs.pingcap.com/tidb/stable/tidb-lightning-physical-import-mode) of TiDB Lightning. You can use `IMPORT INTO` in the following two ways: -> **Note:** -> -> This feature is not available on [TiDB Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-serverless) clusters. - -For TiDB Self-Hosted, `IMPORT INTO` supports importing data from files stored in Amazon S3, GCS, and the TiDB local storage. For [TiDB Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-dedicated), `IMPORT INTO` supports importing data from files stored in Amazon S3 and GCS. - -- For data files stored in Amazon S3 or GCS, `IMPORT INTO` supports running in the [TiDB Distributed eXecution Framework (DXF)](/tidb-distributed-execution-framework.md). - - - When this DXF is enabled ([tidb_enable_dist_task](/system-variables.md#tidb_enable_dist_task-new-in-v710) is `ON`), `IMPORT INTO` splits a data import job into multiple sub-jobs and distributes these sub-jobs to different TiDB nodes for execution to improve the import efficiency. - - When this DXF is disabled, `IMPORT INTO` only supports running on the TiDB node where the current user is connected. - -- For data files stored locally in TiDB, `IMPORT INTO` only supports running on the TiDB node where the current user is connected. Therefore, the data files need to be placed on the TiDB node where the current user is connected. If you access TiDB through a proxy or load balancer, you cannot import data files stored locally in TiDB. +- `IMPORT INTO ... FROM FILE`: imports data files in formats such as `CSV`, `SQL`, and `PARQUET` into an empty table in TiDB. +- `IMPORT INTO ... FROM SELECT`: imports the query result of a `SELECT` statement into an empty table in TiDB. You can also use it to import historical data queried with [`AS OF TIMESTAMP`](/as-of-timestamp.md). ## Restrictions -- For TiDB Self-Hosted, `IMPORT INTO` supports importing data within 10 TiB. For [TiDB Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-dedicated), `IMPORT INTO` supports importing data within 50 GiB. - `IMPORT INTO` only supports importing data into existing empty tables in the database. - `IMPORT INTO` does not support transactions or rollback. Executing `IMPORT INTO` within an explicit transaction (`BEGIN`/`END`) will return an error. -- The execution of `IMPORT INTO` blocks the current connection until the import is completed. To execute the statement asynchronously, you can add the `DETACHED` option. - `IMPORT INTO` does not support working simultaneously with features such as [Backup & Restore](https://docs.pingcap.com/tidb/stable/backup-and-restore-overview), [`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md), [acceleration of adding indexes](/system-variables.md#tidb_ddl_enable_fast_reorg-new-in-v630), data import using TiDB Lightning, data replication using TiCDC, or [Point-in-Time Recovery (PITR)](https://docs.pingcap.com/tidb/stable/br-log-architecture). -- Only one `IMPORT INTO` job can run on a cluster at a time. Although `IMPORT INTO` performs a precheck for running jobs, it is not a hard limit. Starting multiple import jobs might work when multiple clients execute `IMPORT INTO` simultaneously, but you need to avoid that because it might result in data inconsistency or import failures. - During the data import process, do not perform DDL or DML operations on the target table, and do not execute [`FLASHBACK DATABASE`](/sql-statements/sql-statement-flashback-database.md) for the target database. These operations can lead to import failures or data inconsistencies. In addition, it is **NOT** recommended to perform read operations during the import process, as the data being read might be inconsistent. Perform read and write operations only after the import is completed. - The import process consumes system resources significantly. For TiDB Self-Hosted, to get better performance, it is recommended to use TiDB nodes with at least 32 cores and 64 GiB of memory. TiDB writes sorted data to the TiDB [temporary directory](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630) during import, so it is recommended to configure high-performance storage media for TiDB Self-Hosted, such as flash memory. For more information, see [Physical Import Mode limitations](https://docs.pingcap.com/tidb/stable/tidb-lightning-physical-import-mode#requirements-and-restrictions). - For TiDB Self-Hosted, the TiDB [temporary directory](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630) is expected to have at least 90 GiB of available space. It is recommended to allocate storage space that is equal to or greater than the volume of data to be imported. -- One import job supports importing data into one target table only. To import data into multiple target tables, after the import for a target table is completed, you need to create a new job for the next target table. +- One import job supports importing data into one target table only. - `IMPORT INTO` is not supported during TiDB cluster upgrades. -- When the [Global Sort](/tidb-global-sort.md) feature is used for data import, the data size of a single row after encoding must not exceed 32 MiB. -- When the Global Sort feature is used for data import, if the target TiDB cluster is deleted before the import task is completed, temporary data used for global sorting might remain on Amazon S3. In this case, you need to delete the residual data manually to avoid increasing S3 storage costs. - Ensure that the data to be imported does not contain any records with primary key or non-null unique index conflicts. Otherwise, the conflicts can result in import task failures. -- If an `IMPORT INTO` task scheduled by the Distributed eXecution Framework (DXF) is already running, it cannot be scheduled to a new TiDB node. If the TiDB node that executes the data import task is restarted, it will no longer execute the data import task, but transfers the task to another TiDB node to continue executing. However, if the imported data is from a local file, the task will not be transferred to another TiDB node to continue executing. - Known issue: the `IMPORT INTO` task might fail if the PD address in the TiDB node configuration file is inconsistent with the current PD topology of the cluster. This inconsistency can arise in situations such as that PD was scaled in previously, but the TiDB configuration file was not updated accordingly or the TiDB node was not restarted after the configuration file update. +### `IMPORT INTO ... FROM FILE` restrictions + +- For TiDB Self-Hosted, `IMPORT INTO` supports importing data within 10 TiB. For [TiDB Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-dedicated), `IMPORT INTO` supports importing data within 50 GiB. +- The execution of `IMPORT INTO ... FROM FILE` blocks the current connection until the import is completed. To execute the statement asynchronously, you can add the `DETACHED` option. +- Up to 16 `IMPORT INTO` tasks can run simultaneously on each cluster (see [TiDB Distributed eXecution Framework (DXF) usage limitations](/tidb-distributed-execution-framework.md#limitation)). When a cluster lacks sufficient resources or reaches the maximum number of tasks, newly submitted import tasks are queued for execution. +- When the [Global Sort](/tidb-global-sort.md) feature is used for data import, the value of the `THREAD` option must be at least `16`. +- When the [Global Sort](/tidb-global-sort.md) feature is used for data import, the data size of a single row after encoding must not exceed 32 MiB. +- When the Global Sort feature is used for data import, if the target TiDB cluster is deleted before the import task is completed, temporary data used for global sorting might remain on Amazon S3. In this case, you need to delete the residual data manually to avoid increasing S3 storage costs. +- All `IMPORT INTO` tasks that are created when [TiDB Distributed eXecution Framework (DXF)](/tidb-distributed-execution-framework.md) is not enabled run directly on the nodes where the tasks are submitted, and these tasks will not be scheduled for execution on other TiDB nodes even after DXF is enabled later. After DXF is enabled, only newly created `IMPORT INTO` tasks that import data from S3 or GCS are automatically scheduled or failed over to other TiDB nodes for execution. + +### `IMPORT INTO ... FROM SELECT` restrictions + +- `IMPORT INTO ... FROM SELECT` can only be executed on the TiDB node that the current user is connected to, and it blocks the current connection until the import is complete. +- `IMPORT INTO ... FROM SELECT` only supports two [import options](#withoptions): `THREAD` and `DISABLE_PRECHECK`. +- `IMPORT INTO ... FROM SELECT` does not support the task management statements such as `SHOW IMPORT JOB(s)` and `CANCEL IMPORT JOB `. +- The [temporary directory](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630) of TiDB requires sufficient space to store the entire query result of the `SELECT` statement (configuring the `DISK_QUOTA` option is not supported currently). +- Importing historical data using [`tidb_snapshot`](/read-historical-data.md) is not supported. + ## Prerequisites for import Before using `IMPORT INTO` to import data, make sure the following requirements are met: - The target table to be imported is already created in TiDB and it is empty. - The target cluster has sufficient space to store the data to be imported. -- For TiDB Self-Hosted, the [temporary directory](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630) of the TiDB node connected to the current session has at least 90 GiB of available space. If [`tidb_enable_dist_task`](/system-variables.md#tidb_enable_dist_task-new-in-v710) is enabled, also make sure that the temporary directory of each TiDB node in the cluster has sufficient disk space. +- For TiDB Self-Hosted, the [temporary directory](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630) of the TiDB node connected to the current session has at least 90 GiB of available space. If [`tidb_enable_dist_task`](/system-variables.md#tidb_enable_dist_task-new-in-v710) is enabled and the data for import is from S3 or GCS, also make sure that the temporary directory of each TiDB node in the cluster has sufficient disk space. ## Required privileges @@ -56,10 +58,15 @@ Executing `IMPORT INTO` requires the `SELECT`, `UPDATE`, `INSERT`, `DELETE`, and ```ebnf+diagram ImportIntoStmt ::= 'IMPORT' 'INTO' TableName ColumnNameOrUserVarList? SetClause? FROM fileLocation Format? WithOptions? + | + 'IMPORT' 'INTO' TableName ColumnNameList? FROM SelectStatement WithOptions? ColumnNameOrUserVarList ::= '(' ColumnNameOrUserVar (',' ColumnNameOrUserVar)* ')' +ColumnNameList ::= + '(' ColumnName (',' ColumnName)* ')' + SetClause ::= 'SET' SetItem (',' SetItem)* @@ -103,13 +110,14 @@ It specifies the storage location of the data file, which can be an Amazon S3 or > > If [SEM](/system-variables.md#tidb_enable_enhanced_security) is enabled in the target cluster, the `fileLocation` cannot be specified as a local file path. -In the `fileLocation` parameter, you can specify a single file or use the `*` wildcard to match multiple files for import. Note that the wildcard can only be used in the file name, because it does not match directories or recursively match files in subdirectories. Taking files stored on Amazon S3 as examples, you can configure the parameter as follows: +In the `fileLocation` parameter, you can specify a single file, or use the `*` and `[]` wildcards to match multiple files for import. Note that the wildcard can only be used in the file name, because it does not match directories or recursively match files in subdirectories. Taking files stored on Amazon S3 as examples, you can configure the parameter as follows: - Import a single file: `s3:///path/to/data/foo.csv` - Import all files in a specified path: `s3:///path/to/data/*` - Import all files with the `.csv` suffix in a specified path: `s3:///path/to/data/*.csv` - Import all files with the `foo` prefix in a specified path: `s3:///path/to/data/foo*` - Import all files with the `foo` prefix and the `.csv` suffix in a specified path: `s3:///path/to/data/foo*.csv` +- Import `1.csv` and `2.csv` in a specified path: `s3:///path/to/data/[12].csv` ### Format @@ -117,11 +125,11 @@ The `IMPORT INTO` statement supports three data file formats: `CSV`, `SQL`, and ### WithOptions -You can use `WithOptions` to specify import options and control the data import process. For example, to execute the import asynchronously in the backend, you can enable the `DETACHED` mode for the import by adding the `WITH DETACHED` option to the `IMPORT INTO` statement. +You can use `WithOptions` to specify import options and control the data import process. For example, to execute the import of data files asynchronously in the backend, you can enable the `DETACHED` mode for the import by adding the `WITH DETACHED` option to the `IMPORT INTO` statement. The supported options are described as follows: -| Option name | Supported data formats | Description | +| Option name | Supported data sources and formats | Description | |:---|:---|:---| | `CHARACTER_SET=''` | CSV | Specifies the character set of the data file. The default character set is `utf8mb4`. The supported character sets include `binary`, `utf8`, `utf8mb4`, `gb18030`, `gbk`, `latin1`, and `ascii`. | | `FIELDS_TERMINATED_BY=''` | CSV | Specifies the field separator. The default separator is `,`. | @@ -131,17 +139,33 @@ The supported options are described as follows: | `LINES_TERMINATED_BY=''` | CSV | Specifies the line terminator. By default, `IMPORT INTO` automatically identifies `\n`, `\r`, or `\r\n` as line terminators. If the line terminator is one of these three, you do not need to explicitly specify this option. | | `SKIP_ROWS=` | CSV | Specifies the number of rows to skip. The default value is `0`. You can use this option to skip the header in a CSV file. If you use a wildcard to specify the source files for import, this option applies to all source files that are matched by the wildcard in `fileLocation`. | | `SPLIT_FILE` | CSV | Splits a single CSV file into multiple smaller chunks of around 256 MiB for parallel processing to improve import efficiency. This parameter only works for **non-compressed** CSV files and has the same usage restrictions as that of TiDB Lightning [`strict-format`](https://docs.pingcap.com/tidb/stable/tidb-lightning-data-source#strict-format). | -| `DISK_QUOTA=''` | All formats | Specifies the disk space threshold that can be used during data sorting. The default value is 80% of the disk space in the TiDB [temporary directory](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630). If the total disk size cannot be obtained, the default value is 50 GiB. When specifying `DISK_QUOTA` explicitly, make sure that the value does not exceed 80% of the disk space in the TiDB temporary directory. | -| `DISABLE_TIKV_IMPORT_MODE` | All formats | Specifies whether to disable switching TiKV to import mode during the import process. By default, switching TiKV to import mode is not disabled. If there are ongoing read-write operations in the cluster, you can enable this option to avoid impact from the import process. | -| `THREAD=` | All formats | Specifies the concurrency for import. The default value is 50% of the CPU cores, with a minimum value of 1. You can explicitly specify this option to control the resource usage, but make sure that the value does not exceed the number of CPU cores. To import data into a new cluster without any data, it is recommended to increase this concurrency appropriately to improve import performance. If the target cluster is already used in a production environment, it is recommended to adjust this concurrency according to your application requirements. | -| `MAX_WRITE_SPEED=''` | All formats | Controls the write speed to a TiKV node. By default, there is no speed limit. For example, you can specify this option as `1MiB` to limit the write speed to 1 MiB/s. | -| `CHECKSUM_TABLE=''` | All formats | Configures whether to perform a checksum check on the target table after the import to validate the import integrity. The supported values include `"required"` (default), `"optional"`, and `"off"`. `"required"` means performing a checksum check after the import. If the checksum check fails, TiDB will return an error and the import will exit. `"optional"` means performing a checksum check after the import. If an error occurs, TiDB will return a warning and ignore the error. `"off"` means not performing a checksum check after the import. | -| `DETACHED` | All Formats | Controls whether to execute `IMPORT INTO` asynchronously. When this option is enabled, executing `IMPORT INTO` immediately returns the information of the import job (such as the `Job_ID`), and the job is executed asynchronously in the backend. | -| `CLOUD_STORAGE_URI` | All formats | Specifies the target address where encoded KV data for [Global Sort](/tidb-global-sort.md) is stored. When `CLOUD_STORAGE_URI` is not specified, `IMPORT INTO` determines whether to use Global Sort based on the value of the system variable [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-new-in-v740). If this system variable specifies a target storage address, `IMPORT INTO` uses this address for Global Sort. When `CLOUD_STORAGE_URI` is specified with a non-empty value, `IMPORT INTO` uses that value as the target storage address. When `CLOUD_STORAGE_URI` is specified with an empty value, local sorting is enforced. Currently, the target storage address only supports S3. For details about the URI configuration, see [Amazon S3 URI format](/external-storage-uri.md#amazon-s3-uri-format). When this feature is used, all TiDB nodes must have read and write access for the target S3 bucket. | +| `DISK_QUOTA=''` | All file formats | Specifies the disk space threshold that can be used during data sorting. The default value is 80% of the disk space in the TiDB [temporary directory](https://docs.pingcap.com/tidb/stable/tidb-configuration-file#temp-dir-new-in-v630). If the total disk size cannot be obtained, the default value is 50 GiB. When specifying `DISK_QUOTA` explicitly, make sure that the value does not exceed 80% of the disk space in the TiDB temporary directory. | +| `DISABLE_TIKV_IMPORT_MODE` | All file formats | Specifies whether to disable switching TiKV to import mode during the import process. By default, switching TiKV to import mode is not disabled. If there are ongoing read-write operations in the cluster, you can enable this option to avoid impact from the import process. | +| `THREAD=` | All file formats and query results of `SELECT` | Specifies the concurrency for import. For `IMPORT INTO ... FROM FILE`, the default value of `THREAD` is 50% of the number of CPU cores on the TiDB node, the minimum value is `1`, and the maximum value is the number of CPU cores. For `IMPORT INTO ... FROM SELECT`, the default value of `THREAD` is `2`, the minimum value is `1`, and the maximum value is two times the number of CPU cores on the TiDB node. To import data into a new cluster without any data, it is recommended to increase this concurrency appropriately to improve import performance. If the target cluster is already used in a production environment, it is recommended to adjust this concurrency according to your application requirements. | +| `MAX_WRITE_SPEED=''` | All file formats | Controls the write speed to a TiKV node. By default, there is no speed limit. For example, you can specify this option as `1MiB` to limit the write speed to 1 MiB/s. | +| `CHECKSUM_TABLE=''` | All file formats | Configures whether to perform a checksum check on the target table after the import to validate the import integrity. The supported values include `"required"` (default), `"optional"`, and `"off"`. `"required"` means performing a checksum check after the import. If the checksum check fails, TiDB will return an error and the import will exit. `"optional"` means performing a checksum check after the import. If an error occurs, TiDB will return a warning and ignore the error. `"off"` means not performing a checksum check after the import. | +| `DETACHED` | All file formats | Controls whether to execute `IMPORT INTO` asynchronously. When this option is enabled, executing `IMPORT INTO` immediately returns the information of the import job (such as the `Job_ID`), and the job is executed asynchronously in the backend. | +| `CLOUD_STORAGE_URI` | All file formats | Specifies the target address where encoded KV data for [Global Sort](/tidb-global-sort.md) is stored. When `CLOUD_STORAGE_URI` is not specified, `IMPORT INTO` determines whether to use Global Sort based on the value of the system variable [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-new-in-v740). If this system variable specifies a target storage address, `IMPORT INTO` uses this address for Global Sort. When `CLOUD_STORAGE_URI` is specified with a non-empty value, `IMPORT INTO` uses that value as the target storage address. When `CLOUD_STORAGE_URI` is specified with an empty value, local sorting is enforced. Currently, the target storage address only supports S3. For details about the URI configuration, see [Amazon S3 URI format](/external-storage-uri.md#amazon-s3-uri-format). When this feature is used, all TiDB nodes must have read and write access for the target S3 bucket, including at least these permissions: `s3:ListBucket`, `s3:GetObject`, `s3:DeleteObject`, `s3:PutObject`, `s3: AbortMultipartUpload`. | +| `DISABLE_PRECHECK` | All file formats and query results of `SELECT` | Setting this option disables pre-checks of non-critical itemes, such as checking whether there are CDC or PITR tasks. | + +## `IMPORT INTO ... FROM FILE` usage + +> **Note:** +> +> `IMPORT INTO ... FROM FILE` is not available on [TiDB Serverless](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-serverless) clusters. -## Compressed files +For TiDB Self-Hosted, `IMPORT INTO ... FROM FILE` supports importing data from files stored in Amazon S3, GCS, and the TiDB local storage. For [TiDB Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-dedicated), `IMPORT INTO ... FROM FILE` supports importing data from files stored in Amazon S3 and GCS. -`IMPORT INTO` supports importing compressed `CSV` and `SQL` files. It can automatically determine whether a file is compressed and the compression format based on the file extension: +- For data files stored in Amazon S3 or GCS, `IMPORT INTO ... FROM FILE` supports running in the [TiDB Distributed eXecution Framework (DXF)](/tidb-distributed-execution-framework.md). + + - When the DXF is enabled ([tidb_enable_dist_task](/system-variables.md#tidb_enable_dist_task-new-in-v710) is `ON`), `IMPORT INTO` splits a data import job into multiple sub-jobs and distributes these sub-jobs to different TiDB nodes for execution to improve the import efficiency. + - When the DXF is disabled, `IMPORT INTO ... FROM FILE` only supports running on the TiDB node where the current user is connected. + +- For data files stored locally in TiDB, `IMPORT INTO ... FROM FILE` only supports running on the TiDB node where the current user is connected. Therefore, the data files need to be placed on the TiDB node where the current user is connected. If you access TiDB through a proxy or load balancer, you cannot import data files stored locally in TiDB. + +### Compressed files + +`IMPORT INTO ... FROM FILE` supports importing compressed `CSV` and `SQL` files. It can automatically determine whether a file is compressed and the compression format based on the file extension: | Extension | Compression format | |:---|:---| @@ -154,13 +178,13 @@ The supported options are described as follows: > - The Snappy compressed file must be in the [official Snappy format](https://github.com/google/snappy). Other variants of Snappy compression are not supported. > - Because TiDB Lightning cannot concurrently decompress a single large compressed file, the size of the compressed file affects the import speed. It is recommended that a source file is no greater than 256 MiB after decompression. -## Global Sort +### Global Sort > **Warning:** > > The Global Sort feature is experimental. It is not recommended to use it in production environments. -`IMPORT INTO` splits the data import job of a source data file into multiple sub-jobs, each sub-job independently encoding and sorting data before importing. If the encoded KV ranges of these sub-jobs have significant overlap (to learn how TiDB encodes data to KV, see [TiDB computing](/tidb-computing.md)), TiKV needs to keep compaction during import, leading to a decrease in import performance and stability. +`IMPORT INTO ... FROM FILE` splits the data import job of a source data file into multiple sub-jobs, each sub-job independently encoding and sorting data before importing. If the encoded KV ranges of these sub-jobs have significant overlap (to learn how TiDB encodes data to KV, see [TiDB computing](/tidb-computing.md)), TiKV needs to keep compaction during import, leading to a decrease in import performance and stability. In the following scenarios, there can be significant overlap in KV ranges: @@ -173,8 +197,8 @@ When the [TiDB Distributed eXecution Framework (DXF)](/tidb-distributed-executio Global Sort consumes a significant amount of memory resources. Before the data import, it is recommended to configure the [`tidb_server_memory_limit_gc_trigger`](/system-variables.md#tidb_server_memory_limit_gc_trigger-new-in-v640) and [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-new-in-v640) variables, which avoids golang GC being frequently triggered and thus affecting the import efficiency. ```sql -SET GLOBAL tidb_server_memory_limit_gc_trigger=0.99; -SET GLOBAL tidb_server_memory_limit='88%'; +SET GLOBAL tidb_server_memory_limit_gc_trigger=1; +SET GLOBAL tidb_server_memory_limit='75%'; ``` > **Note:** @@ -182,11 +206,11 @@ SET GLOBAL tidb_server_memory_limit='88%'; > - If the KV range overlap in a source data file is low, enabling Global Sort might decrease import performance. This is because when Global Sort is enabled, TiDB needs to wait for the completion of local sorting in all sub-jobs before proceeding with the Global Sort operations and subsequent import. > - After an import job using Global Sort completes, the files stored in the cloud storage for Global Sort are cleaned up asynchronously in a background thread. -## Output +### Output -When `IMPORT INTO` completes the import or when the `DETACHED` mode is enabled, `IMPORT INTO` will return the current job information in the output, as shown in the following examples. For the description of each field, see [`SHOW IMPORT JOB(s)`](/sql-statements/sql-statement-show-import-job.md). +When `IMPORT INTO ... FROM FILE` completes the import or when the `DETACHED` mode is enabled, TiDB returns the current job information in the output, as shown in the following examples. For the description of each field, see [`SHOW IMPORT JOB(s)`](/sql-statements/sql-statement-show-import-job.md). -When `IMPORT INTO` completes the import, the example output is as follows: +When `IMPORT INTO ... FROM FILE` completes the import, the example output is as follows: ```sql IMPORT INTO t FROM '/path/to/small.csv'; @@ -197,7 +221,7 @@ IMPORT INTO t FROM '/path/to/small.csv'; +--------+--------------------+--------------+----------+-------+----------+------------------+---------------+----------------+----------------------------+----------------------------+----------------------------+------------+ ``` -When the `DETACHED` mode is enabled, executing the `IMPORT INTO` statement will immediately return the job information in the output. From the output, you can see that the status of the job is `pending`, which means waiting for execution. +When the `DETACHED` mode is enabled, executing the `IMPORT INTO ... FROM FILE` statement will immediately return the job information in the output. From the output, you can see that the status of the job is `pending`, which means waiting for execution. ```sql IMPORT INTO t FROM '/path/to/small.csv' WITH DETACHED; @@ -208,27 +232,27 @@ IMPORT INTO t FROM '/path/to/small.csv' WITH DETACHED; +--------+--------------------+--------------+----------+-------+---------+------------------+---------------+----------------+----------------------------+------------+----------+------------+ ``` -## View and manage import jobs +### View and manage import jobs For an import job with the `DETACHED` mode enabled, you can use [`SHOW IMPORT`](/sql-statements/sql-statement-show-import-job.md) to view its current job progress. After an import job is started, you can cancel it using [`CANCEL IMPORT JOB `](/sql-statements/sql-statement-cancel-import-job.md). -## Examples +### Examples -### Import a CSV file with headers +#### Import a CSV file with headers ```sql IMPORT INTO t FROM '/path/to/file.csv' WITH skip_rows=1; ``` -### Import a file asynchronously in the `DETACHED` mode +#### Import a file asynchronously in the `DETACHED` mode ```sql IMPORT INTO t FROM '/path/to/file.csv' WITH DETACHED; ``` -### Skip importing a specific field in your data file +#### Skip importing a specific field in your data file Assume that your data file is in the CSV format and its content is as follows: @@ -244,15 +268,21 @@ And assume that the target table schema for the import is `CREATE TABLE t(id int IMPORT INTO t(id, name, @1) FROM '/path/to/file.csv' WITH skip_rows=1; ``` -### Import multiple data files using the wildcard `*` +#### Import multiple data files using wildcards Assume that there are three files named `file-01.csv`, `file-02.csv`, and `file-03.csv` in the `/path/to/` directory. To import these three files into a target table `t` using `IMPORT INTO`, you can execute the following SQL statement: ```sql -IMPORT INTO t FROM '/path/to/file-*.csv' +IMPORT INTO t FROM '/path/to/file-*.csv'; +``` + +If you only need to import `file-01.csv` and `file-03.csv` into the target table, execute the following SQL statement: + +```sql +IMPORT INTO t FROM '/path/to/file-0[13].csv'; ``` -### Import data files from Amazon S3 or GCS +#### Import data files from Amazon S3 or GCS - Import data files from Amazon S3: @@ -268,7 +298,7 @@ IMPORT INTO t FROM '/path/to/file-*.csv' For details about the URI path configuration for Amazon S3 or GCS, see [URI Formats of External Storage Services](/external-storage-uri.md). -### Calculate column values using SetClause +#### Calculate column values using SetClause Assume that your data file is in the CSV format and its content is as follows: @@ -284,13 +314,13 @@ And assume that the target table schema for the import is `CREATE TABLE t(id int IMPORT INTO t(id, name, @1) SET val=@1*100 FROM '/path/to/file.csv' WITH skip_rows=1; ``` -### Import a data file in the SQL format +#### Import a data file in the SQL format ```sql IMPORT INTO t FROM '/path/to/file.sql' FORMAT 'sql'; ``` -### Limit the write speed to TiKV +#### Limit the write speed to TiKV To limit the write speed to a TiKV node to 10 MiB/s, execute the following SQL statement: @@ -298,6 +328,26 @@ To limit the write speed to a TiKV node to 10 MiB/s, execute the following SQL s IMPORT INTO t FROM 's3://bucket/path/to/file.parquet?access-key=XXX&secret-access-key=XXX' FORMAT 'parquet' WITH MAX_WRITE_SPEED='10MiB'; ``` +## `IMPORT INTO ... FROM SELECT` usage + +`IMPORT INTO ... FROM SELECT` lets you import the query result of a `SELECT` statement to an empty table in TiDB. You can also use it to import historical data queried with [`AS OF TIMESTAMP`](/as-of-timestamp.md). + +### Import the query result of `SELECT` + +To import the `UNION` result to the target table `t`, with the import concurrency specified as `8` and precheck of non-critical items configured as disabled, execute the following SQL statement: + +```sql +IMPORT INTO t FROM SELECT * FROM src UNION SELECT * FROM src2 WITH THREAD = 8, DISABLE_PRECHECK; +``` + +### Import historical data at a specified time point + +To import historical data at a specified time point to the target table `t`, execute the following SQL statement: + +```sql +IMPORT INTO t FROM SELECT * FROM src AS OF TIMESTAMP '2024-02-27 11:38:00'; +``` + ## MySQL compatibility This statement is a TiDB extension to MySQL syntax. diff --git a/tidb-distributed-execution-framework.md b/tidb-distributed-execution-framework.md index 5b50c5d46d868..70b68989e923a 100644 --- a/tidb-distributed-execution-framework.md +++ b/tidb-distributed-execution-framework.md @@ -40,7 +40,11 @@ Currently, the DXF supports the distributed execution of the `ADD INDEX` and `IM ## Limitation -- The DXF can only schedule the distributed execution of one `ADD INDEX` task at a time. If a new `ADD INDEX` task is submitted before the current `ADD INDEX` distributed task has finished, the new task is executed through a transaction. +The DXF can only schedule up to 16 tasks (including `ADD INDEX` tasks and `IMPORT INTO` tasks) simultaneously. + +## `ADD INDEX` limitation + +- For each cluster, only one `ADD INDEX` task is allowed for distributed execution at a time. If a new `ADD INDEX` task is submitted before the current `ADD INDEX` distributed task has finished, the new `ADD INDEX` task is executed through a transaction instead of being scheduled by DXF. - Adding indexes on columns with the `TIMESTAMP` data type through the DXF is not supported, because it might lead to inconsistency between the index and the data. ## Prerequisites From 6fda8d91d0c12bed263c3da169fc264cdcc51444 Mon Sep 17 00:00:00 2001 From: crazycs Date: Fri, 22 Mar 2024 07:48:44 +0800 Subject: [PATCH 69/82] add doc for tikv-client.enable-replica-selector-v2 (#16787) --- tidb-configuration-file.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tidb-configuration-file.md b/tidb-configuration-file.md index 88643fa2b1142..96b79531c62ac 100644 --- a/tidb-configuration-file.md +++ b/tidb-configuration-file.md @@ -734,12 +734,21 @@ Configuration items related to opentracing.reporter. > **Warning:** > -> This configuration might be deprecated in future versions. **DO NOT** change the value of this configuration. +> This configuration parameter might be deprecated in future versions. **DO NOT** change the value of it. + The timeout of a single Coprocessor request. + Default value: `60` + Unit: second +### `enable-replica-selector-v2` New in v8.0.0 + +> **Warning:** +> +> This configuration parameter might be deprecated in future versions. **DO NOT** change the value of it. + ++ Whether to use the new version of the Region replica selector when sending RPC requests to TiKV. ++ Default value: `true` + ## tikv-client.copr-cache New in v4.0.0 This section introduces configuration items related to the Coprocessor Cache feature. From 660a70c587b8fc1adc603076baf066d46e3810b6 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Fri, 22 Mar 2024 14:27:45 +0800 Subject: [PATCH 70/82] titan_doc_8.0 (#16777) --- dynamic-config.md | 3 +++ storage-engine/titan-configuration.md | 9 ++++++++- tikv-configuration-file.md | 7 ++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/dynamic-config.md b/dynamic-config.md index d006a759ae8e6..cff4e08482ead 100644 --- a/dynamic-config.md +++ b/dynamic-config.md @@ -213,6 +213,9 @@ The following TiKV configuration items can be modified dynamically: | `{db-name}.{cf-name}.soft-pending-compaction-bytes-limit` | The soft limit on the pending compaction bytes | | `{db-name}.{cf-name}.hard-pending-compaction-bytes-limit` | The hard limit on the pending compaction bytes | | `{db-name}.{cf-name}.titan.blob-run-mode` | The mode of processing blob files | +| `{db-name}.{cf-name}.titan.min-blob-size` | The threshold at which data is stored in Titan. Data is stored in a Titan blob file when its value reaches this threshold. | +| `{db-name}.{cf-name}.titan.blob-file-compression` | The compression algorithm used by Titan blob files | +| `{db-name}.{cf-name}.titan.discardable-ratio` | The threshold of garbage data ratio in Titan data files for GC. When the ratio of useless data in a blob file exceeds the threshold, Titan GC is triggered. | | `server.grpc-memory-pool-quota` | Limits the memory size that can be used by gRPC | | `server.max-grpc-send-msg-len` | Sets the maximum length of a gRPC message that can be sent | | `server.snap-io-max-bytes-per-sec` | Sets the maximum allowable disk bandwidth when processing snapshots | diff --git a/storage-engine/titan-configuration.md b/storage-engine/titan-configuration.md index 5f17f5f641b79..5f5ca31268eb0 100644 --- a/storage-engine/titan-configuration.md +++ b/storage-engine/titan-configuration.md @@ -105,6 +105,10 @@ If you observe that the Titan GC thread is in full load for a long time from **T You can adjust [`rate-bytes-per-sec`](/tikv-configuration-file.md#rate-bytes-per-sec) to limit the I/O rate of RocksDB compaction, reducing its impact on foreground read and write performance during high traffic. +### `shared-blob-cache` (New in v8.0.0) + +You can control whether to enable the shared cache for Titan blob files and RocksDB block files through [`shared-blob-cache`](/tikv-configuration-file.md#shared-blob-cache-new-in-v800). The default value is `true`. When the shared cache is enabled, block files have higher priority. This means that TiKV prioritizes meeting the cache needs of block files and then uses the remaining cache for blob files. + ### Titan configuration example The following is an example of the Titan configuration file. You can either [use TiUP to modify the configuration](/maintain-tidb-using-tiup.md#modify-the-configuration) or [configure a TiDB cluster on Kubernetes](https://docs.pingcap.com/tidb-in-kubernetes/stable/configure-a-tidb-cluster). @@ -121,7 +125,6 @@ max-background-gc = 1 min-blob-size = "32KB" blob-file-compression = "zstd" zstd-dict-size = "16KB" -blob-cache-size = "0GB" discardable-ratio = 0.5 blob-run-mode = "normal" level-merge = false @@ -154,6 +157,10 @@ To fully disable Titan for all existing and future data, you can follow these st 2. (Optional) Perform a full compaction using tikv-ctl. This process will consume a large amount of I/O and CPU resources. + > **Warning:** + > + > When disk space is insufficient, executing the following command might result in the entire cluster running out of available space and thus unable to write data. + ```bash tikv-ctl --pd compact-cluster --bottommost force ``` diff --git a/tikv-configuration-file.md b/tikv-configuration-file.md index 53401f6c88969..4ddca277f7023 100644 --- a/tikv-configuration-file.md +++ b/tikv-configuration-file.md @@ -1658,9 +1658,14 @@ Configuration items related to `rocksdb.defaultcf.titan`. + The cache size of a Blob file + Default value: `"0GiB"` + Minimum value: `0` -+ Recommended value: After database stabilization, it is recommended to set the RocksDB block cache (`storage.block-cache.capacity`) based on monitoring to maintain a block cache hit rate of at least 95%, and set `blob-cache-size` to `(total memory size) * 50% - (size of block cache)`. This is to ensure that the block cache is sufficiently large to cache the entire RocksDB, while maximizing the blob cache size. However, to prevent a significant drop in the block cache hit rate, do not set the blob cache size too large. ++ Recommended value: `0`. Starting from v8.0.0, TiKV introduces the `shared-blob-cache` configuration item and enables it by default, so there is no need to set `blob-cache-size` separately. The configuration of `blob-cache-size` only takes effect when `shared-blob-cache` is set to `false`. + Unit: KiB|MiB|GiB +### `shared-blob-cache` (New in v8.0.0) + ++ Controls whether to enable the shared cache for Titan blob files and RocksDB block files. ++ Default value: `true`. When the shared cache is enabled, block files have higher priority. This means that TiKV prioritizes meeting the cache needs of block files and then uses the remaining cache for blob files. + ### `min-gc-batch-size` + The minimum total size of Blob files required to perform GC for one time From bba9b810b884b7804446949a14406d9e2e59a9cf Mon Sep 17 00:00:00 2001 From: Aolin Date: Mon, 25 Mar 2024 11:47:17 +0800 Subject: [PATCH 71/82] TiProxy: update images (#16808) --- tiproxy/tiproxy-overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tiproxy/tiproxy-overview.md b/tiproxy/tiproxy-overview.md index 04446fcde5138..32eda9fb4040f 100644 --- a/tiproxy/tiproxy-overview.md +++ b/tiproxy/tiproxy-overview.md @@ -11,7 +11,7 @@ TiProxy is an optional component. You can also use a third-party proxy component The following figure shows the architecture of TiProxy: -TiProxy architecture +TiProxy architecture ## Main features @@ -23,7 +23,7 @@ TiProxy can migrate connections from one TiDB server to another without breaking As shown in the following figure, the client originally connects to TiDB 1 through TiProxy. After the connection migration, the client actually connects to TiDB 2. When TiDB 1 is about to be offline or the ratio of connections on TiDB 1 to connections on TiDB 2 exceeds the set threshold, the connection migration is triggered. The client is unaware of the connection migration. -TiProxy connection migration +TiProxy connection migration Connection migration usually occurs in the following scenarios: From b50425498d6535d13e873791de6dacaa24340dcf Mon Sep 17 00:00:00 2001 From: Lilian Lee Date: Mon, 25 Mar 2024 14:17:16 +0800 Subject: [PATCH 72/82] ticdc: add ticdc simple protocol documentation (#16753) --- TOC.md | 3 +- media/ticdc/ticdc-simple-consumer-1.png | Bin 0 -> 122235 bytes media/ticdc/ticdc-simple-consumer-2.png | Bin 0 -> 122977 bytes ticdc/ticdc-changefeed-config.md | 24 +- ticdc/ticdc-simple-protocol.md | 714 ++++++++++++++++++++++++ 5 files changed, 739 insertions(+), 2 deletions(-) create mode 100644 media/ticdc/ticdc-simple-consumer-1.png create mode 100644 media/ticdc/ticdc-simple-consumer-2.png create mode 100644 ticdc/ticdc-simple-protocol.md diff --git a/TOC.md b/TOC.md index f1e45a1f520dd..e24a3e3e943ed 100644 --- a/TOC.md +++ b/TOC.md @@ -576,9 +576,10 @@ - Output Protocols - [TiCDC Avro Protocol](/ticdc/ticdc-avro-protocol.md) - [TiCDC Canal-JSON Protocol](/ticdc/ticdc-canal-json.md) - - [TiCDC Open Protocol](/ticdc/ticdc-open-protocol.md) - [TiCDC CSV Protocol](/ticdc/ticdc-csv.md) - [TiCDC Debezium Protocol](/ticdc/ticdc-debezium.md) + - [TiCDC Open Protocol](/ticdc/ticdc-open-protocol.md) + - [TiCDC Simple Protocol](/ticdc/ticdc-simple-protocol.md) - [TiCDC Open API v2](/ticdc/ticdc-open-api-v2.md) - [TiCDC Open API v1](/ticdc/ticdc-open-api.md) - TiCDC Data Consumption diff --git a/media/ticdc/ticdc-simple-consumer-1.png b/media/ticdc/ticdc-simple-consumer-1.png new file mode 100644 index 0000000000000000000000000000000000000000..bc2bd9efbc9335c16fe4531931e2df030c2b4e51 GIT binary patch literal 122235 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 +
+ +For detailed information on using TiUP Playground, see the following document: + +- [Deploy PD microservices](/tiup/tiup-playground.md#deploy-pd-microservices) + +
+ + +When deploying and using PD microservices, pay attention to the following: + +- After you enable microservices and restart PD for a cluster, PD stops allocating TSO for the cluster. Therefore, you need to deploy the `tso` microservice in the cluster when you enable microservices. +- If the `scheduling` microservice is deployed in a cluster, the scheduling function of the cluster is provided by the `scheduling` microservice. If the `scheduling` microservice is not deployed, the scheduling function of the cluster is still provided by PD. +- The `scheduling` microservice supports dynamic switching, which is enabled by default (`enable-scheduling-fallback` defaults to `true`). If the process of the `scheduling` microservice is terminated, PD continues to provide scheduling services for the cluster by default. + + If the binary versions of the `scheduling` microservice and PD are different, to prevent changes in the scheduling logic, you can disable the dynamic switching function of the `scheduling` microservice by executing `pd-ctl config set enable-scheduling-fallback false`. After this function is disabled, PD will not take over the scheduling service when the process of the `scheduling` microservice is terminated. This means that the scheduling service of the cluster will be unavailable until the `scheduling` microservice is restarted. + +## Tool compatibility + +Microservices do not affect the normal use of data import, export, and other replication tools. + +## FAQs + +- How can I determine if PD becomes a performance bottleneck? + + When your cluster is in a normal state, you can check monitoring metrics in the Grafana PD panel. If the `TiDB - PD server TSO handle time` metric shows a notable increase in latency or the `Heartbeat - TiKV side heartbeat statistics` metric shows a significant number of pending items, it indicates that PD becomes a performance bottleneck. \ No newline at end of file diff --git a/tiup/tiup-playground.md b/tiup/tiup-playground.md index 4ae07c8131ffc..314c07bde839b 100644 --- a/tiup/tiup-playground.md +++ b/tiup/tiup-playground.md @@ -172,3 +172,16 @@ You can specify a `pid` in the `tiup playground scale-in` command to scale in th ```shell tiup playground scale-in --pid 86526 ``` + +## Deploy PD microservices + +Starting from v8.0.0, PD supports the [microservice mode](/pd-microservices.md) (experimental). You can deploy the `tso` microservice and `scheduling` microservice for your cluster using TiUP Playground as follows: + +```shell +./tiup-playground v8.0.0 --pd.mode ms --pd.api 3 --pd.tso 2 --pd.scheduling 3 +``` + +- `--pd.mode`: setting it to `ms` means enabling the microservice mode for PD. +- `--pd.api num`: specifies the number of APIs for PD microservices. It must be at least `1`. +- `--pd.tso num`: specifies the number of instances to be deployed for the `tso` microservice. +- `--pd.scheduling num`: specifies the number of instances to be deployed for the `scheduling` microservice. \ No newline at end of file From 7bbbddc9265dad4fa55a437d9a24af4a09067522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Eeden?= Date: Mon, 25 Mar 2024 09:24:46 +0100 Subject: [PATCH 74/82] DM: Update GitHub URLs for DM (#16737) --- dm/deploy-a-dm-cluster-using-tiup-offline.md | 2 +- dm/deploy-a-dm-cluster-using-tiup.md | 2 +- dm/dm-error-handling.md | 2 +- dm/dm-faq.md | 4 ++-- dm/quick-start-with-dm.md | 2 +- dm/shard-merge-best-practices.md | 2 +- tidb-troubleshooting-map.md | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dm/deploy-a-dm-cluster-using-tiup-offline.md b/dm/deploy-a-dm-cluster-using-tiup-offline.md index 69c70e862bb88..5930e27ca9eea 100644 --- a/dm/deploy-a-dm-cluster-using-tiup-offline.md +++ b/dm/deploy-a-dm-cluster-using-tiup-offline.md @@ -127,7 +127,7 @@ alertmanager_servers: > > - Use `.` to indicate the subcategory of the configuration, such as `log.slow-threshold`. For more formats, see [TiUP configuration template](https://github.com/pingcap/tiup/blob/master/embed/examples/dm/topology.example.yaml). > -> - For more parameter description, see [master `config.toml.example`](https://github.com/pingcap/dm/blob/master/dm/master/dm-master.toml) and [worker `config.toml.example`](https://github.com/pingcap/dm/blob/master/dm/worker/dm-worker.toml). +> - For more parameter description, see [master `config.toml.example`](https://github.com/pingcap/tiflow/blob/master/dm/master/dm-master.toml) and [worker `config.toml.example`](https://github.com/pingcap/tiflow/blob/master/dm/worker/dm-worker.toml). > > - Make sure that the ports among the following components are interconnected: > - The `peer_port` (`8291` by default) among the DM-master nodes are interconnected. diff --git a/dm/deploy-a-dm-cluster-using-tiup.md b/dm/deploy-a-dm-cluster-using-tiup.md index 2d9e061141c6b..26b6cdb054b24 100644 --- a/dm/deploy-a-dm-cluster-using-tiup.md +++ b/dm/deploy-a-dm-cluster-using-tiup.md @@ -144,7 +144,7 @@ alertmanager_servers: > - The TiUP nodes can connect to the `port` of all DM-master nodes (`8261` by default). > - The TiUP nodes can connect to the `port` of all DM-worker nodes (`8262` by default). -For more `master_servers.host.config` parameter description, refer to [master parameter](https://github.com/pingcap/dm/blob/master/dm/master/dm-master.toml). For more `worker_servers.host.config` parameter description, refer to [worker parameter](https://github.com/pingcap/dm/blob/master/dm/worker/dm-worker.toml). +For more `master_servers.host.config` parameter description, refer to [master parameter](https://github.com/pingcap/tiflow/blob/master/dm/master/dm-master.toml). For more `worker_servers.host.config` parameter description, refer to [worker parameter](https://github.com/pingcap/tiflow/blob/master/dm/worker/dm-worker.toml). ## Step 3: Execute the deployment command diff --git a/dm/dm-error-handling.md b/dm/dm-error-handling.md index 6069d8a255233..2ee6a5045c587 100644 --- a/dm/dm-error-handling.md +++ b/dm/dm-error-handling.md @@ -70,7 +70,7 @@ In the error system, usually, the information of a specific error is as follows: Whether DM outputs the error stack information depends on the error severity and the necessity. The error stack records the complete stack call information when the error occurs. If you cannot figure out the error cause based on the basic information and the error message, you can trace the execution path of the code when the error occurs using the error stack. -For the complete list of error codes, refer to the [error code lists](https://github.com/pingcap/dm/blob/master/_utils/terror_gen/errors_release.txt). +For the complete list of error codes, refer to the [error code lists](https://github.com/pingcap/tiflow/blob/master/dm/_utils/terror_gen/errors_release.txt). ## Troubleshooting diff --git a/dm/dm-faq.md b/dm/dm-faq.md index 12e5821c848c0..c6075787a505d 100644 --- a/dm/dm-faq.md +++ b/dm/dm-faq.md @@ -25,7 +25,7 @@ Currently, DM does not support it and only supports the regular expressions of t ## If a statement executed upstream contains multiple DDL operations, does DM support such migration? -DM will attempt to split a single statement containing multiple DDL change operations into multiple statements containing only one DDL operation, but might not cover all cases. It is recommended to include only one DDL operation in a statement executed upstream, or verify it in the test environment. If it is not supported, you can file an [issue](https://github.com/pingcap/dm/issues) to the DM repository. +DM will attempt to split a single statement containing multiple DDL change operations into multiple statements containing only one DDL operation, but might not cover all cases. It is recommended to include only one DDL operation in a statement executed upstream, or verify it in the test environment. If it is not supported, you can file an [issue](https://github.com/pingcap/tiflow/issues) to the `pingcap/tiflow` repository. ## How to handle incompatible DDL statements? @@ -55,7 +55,7 @@ When an exception occurs during data migration and the data migration task canno ## How to handle the error returned by the DDL operation related to the gh-ost table, after `online-ddl: true` is set? ``` -[unit=Sync] ["error information"="{\"msg\":\"[code=36046:class=sync-unit:scope=internal:level=high] online ddls on ghost table `xxx`.`_xxxx_gho`\\ngithub.com/pingcap/dm/pkg/terror.(*Error).Generate ...... +[unit=Sync] ["error information"="{\"msg\":\"[code=36046:class=sync-unit:scope=internal:level=high] online ddls on ghost table `xxx`.`_xxxx_gho`\\ngithub.com/pingcap/tiflow/pkg/terror.(*Error).Generate ...... ``` The above error can be caused by the following reason: diff --git a/dm/quick-start-with-dm.md b/dm/quick-start-with-dm.md index 26c30a4a2b9d9..3386f01ffa96f 100644 --- a/dm/quick-start-with-dm.md +++ b/dm/quick-start-with-dm.md @@ -6,7 +6,7 @@ aliases: ['/docs/tidb-data-migration/dev/get-started/'] # Quick Start Guide for TiDB Data Migration -This document describes how to migrate data from MySQL to TiDB using [TiDB Data Migration](https://github.com/pingcap/dm) (DM). This guide is a quick demo of DM features and is not recommended for any production environment. +This document describes how to migrate data from MySQL to TiDB using [TiDB Data Migration (DM)](/dm/dm-overview.md). This guide is a quick demo of DM features and is not recommended for any production environment. ## Step 1: Deploy a DM cluster diff --git a/dm/shard-merge-best-practices.md b/dm/shard-merge-best-practices.md index 507f276605019..637f97716cc06 100644 --- a/dm/shard-merge-best-practices.md +++ b/dm/shard-merge-best-practices.md @@ -6,7 +6,7 @@ aliases: ['/docs/tidb-data-migration/dev/shard-merge-best-practices/'] # Best Practices of Data Migration in the Shard Merge Scenario -This document describes the features and limitations of [TiDB Data Migration](https://github.com/pingcap/dm) (DM) in the shard merge scenario and provides a data migration best practice guide for your application (the default "pessimistic" mode is used). +This document describes the features and limitations of [TiDB Data Migration (DM)](/dm/dm-overview.md) in the shard merge scenario and provides a data migration best practice guide for your application (the default "pessimistic" mode is used). ## Use a separate data migration task diff --git a/tidb-troubleshooting-map.md b/tidb-troubleshooting-map.md index ee614d974b144..01eff0670ca58 100644 --- a/tidb-troubleshooting-map.md +++ b/tidb-troubleshooting-map.md @@ -472,7 +472,7 @@ Check the specific cause for busy by viewing the monitor **Grafana** -> **TiKV** ### 6.2 Data Migration -- 6.2.1 TiDB Data Migration (DM) is a migration tool that supports data migration from MySQL/MariaDB into TiDB. For details, see [DM on GitHub](https://github.com/pingcap/dm/). +- 6.2.1 TiDB Data Migration (DM) is a migration tool that supports data migration from MySQL/MariaDB into TiDB. For details, see [DM overview](/dm/dm-overview.md). - 6.2.2 `Access denied for user 'root'@'172.31.43.27' (using password: YES)` shows when you run `query status` or check the log. From 993f1189be2d7185fe4bce02a557d5078a535115 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Mon, 25 Mar 2024 17:00:47 +0800 Subject: [PATCH 75/82] add mysql workbench faqs (#16810) (#16828) --- develop/dev-guide-gui-mysql-workbench.md | 13 +++++++++++++ ...workbench-adjust-sqleditor-read-timeout.jpg | Bin 0 -> 393797 bytes tidb-cloud/serverless-driver.md | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 media/develop/mysql-workbench-adjust-sqleditor-read-timeout.jpg diff --git a/develop/dev-guide-gui-mysql-workbench.md b/develop/dev-guide-gui-mysql-workbench.md index 29e7daaadc374..fb9b3ac832766 100644 --- a/develop/dev-guide-gui-mysql-workbench.md +++ b/develop/dev-guide-gui-mysql-workbench.md @@ -149,6 +149,19 @@ Connect to your TiDB cluster depending on the TiDB deployment option you have se +## FAQs + +### How to handle the connection timeout error "Error Code: 2013. Lost connection to MySQL server during query"? + +This error indicates that the query execution time exceeds the timeout limit. To resolve this issue, you can adjust the timeout settings by the following steps: + +1. Launch MySQL Workbench and navigate to the **Workbench Preferences** page. +2. In the **SQL Editor** > **MySQL Session** section, configure the **DBMS connection read timeout interval (in seconds)** option. This sets the maximum amount of time (in seconds) that a query can take before MySQL Workbench disconnects from the server. + + ![MySQL Workbench: adjust timeout option in SQL Editor settings](/media/develop/mysql-workbench-adjust-sqleditor-read-timeout.jpg) + +For more information, see [MySQL Workbench frequently asked questions](https://dev.mysql.com/doc/workbench/en/workbench-faq.html). + ## Next steps - Learn more usage of MySQL Workbench from [the documentation of MySQL Workbench](https://dev.mysql.com/doc/workbench/en/). diff --git a/media/develop/mysql-workbench-adjust-sqleditor-read-timeout.jpg b/media/develop/mysql-workbench-adjust-sqleditor-read-timeout.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0891f2741f8e37828ee18f3dc6bea628353241ac GIT binary patch literal 393797 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
LeTqm0j3xc3JR&x5bummVLlKQ3e0c`p2JF~5Ec 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%0ARh6I_G zxH&Mr=gMHguwSXLUeT!wH_ZJjewXi__IhrLGxjw#aLnw(hX@#{7nTj%g2P^Y7|9Gu z(YqLYkls_E6Y?p!$cA4)78QYnKzhff_b`6uPX;^Fn`Mh1?t0C6!5D<9@nOtYT4_|^74VG zS1g>l8LJ}+=j|)|VkPcpN=XkHLB8()l8IS$!5sh= zC?)ceLe$e^mRNFb@k=LjG|hXw3~PL=_0mcU=DFja`fhaqOc;RW-rv&cp}1@vJ+HF`MX)Mm71G zWjk}i(@x-hca@k{3S3+`gS;u)=&T>Yd{0=>C534Pxc3ZW~d5|YkHZ0ps(mU2}b z?-UPO{?gWzdt;*O!Y(hK+1q=@+Ccprry)}8dX5WT%U@dj#5r?D?om%LH;5BsXz8jInx*pyBy!815n9?g7!*jnv-746-%u)BQ`2Ln(!)Y32pYV)oqDWWJ2i$i z%~}zDraa2aS}J;nZBba?6Tc_UyVX?C;gez#hYFE%X(^By#oiX?8XMH!7YL+{L7!pM zOKQ%mCsa;MtXV8K#4V#E#WuG^OJ_-tx;H7h&XmfxRMk;inR%m*G#>gM`%#jn2vquD z0UQgFFH9SQv(h{GY9)Oid%Gg(kxCHXZe1;_%&7 zO#Tt^T9PxWsNDrflaQ(L=Mq#@E;)q)yl7FiYGn6qd(fO5CBXT(R2#ZcT#mc_4Q+)7 zc>`~teN?#NLH1aB#vVhH?%rxN~5yH0Wh=)V=0AD_d#E5p})A6M?;dvPC1d!(dKMi z#>gC1o1VCqNp;R=6&c!A7P-+=YxHbfJHP-lN6CgW`Pada%p_+A{&AJ|UfC?GnC%nv zh^dARlF7Mp=^El%#KS+UyN%RT@)bRhDYMmZyq)L;h@4THSXh`}P4}+s{P2!00qLPT z>$v00S3iGj-lNpL^1D8*FO6N)#e7m7uX znKi|9qqIvLI#yIl`abmF9Q-9%@^<(>6$nfMWawGG!C1$#jHcHhnr)kMQKtIMZBaBP=ckpie-QFhefQ>Ae}7y5w?c!P zi`1aMR&5nMCLYJquW|H zE(x3soYa!bt1%7mI?N1I#R*7JFYwIHMlH)ag@g)%<2H?pJE~8G#>qO2SkWQ(N+IlB zhb7Zf;`Q%Kb9*y9CBW=@DO>n9t>bbhhUc~LX;RY4#wF=|{B_fCLM}3}$)EW6C@MHNr@#}o@ zYkR-FYg_z-NdB7t9IW!6O4dsxMt;Oy+H$--9P1c5ago3lA2?MQL`H9yGn{Cyt7&7G z#L8nquZO$MVh(SJj-XFj8#_X%RdKDKa+rlo_TMG- z-|Bxau<83t(^wa190%6igH_1|!VVr93#YNh_9E;s^p;$l$VQqLH63%r)p!RPb5Qpj zLAhiuZ+7CL0?T3gTz`x{T9I>xLN7OPp~hG&zL@381p%4~pAtWp;O7q@W^_Z3NE2NQ zap>Ms^2}mr=D>I=!+L;sNn2JooAT ze%(wks_in&iicD~H$rHGHm<2Fzd*WnHQ-CM=$v4ctX?RM?yaUpP2I=3O4^gRl==5ernWt zY(L0a(Z%lJhlcEGVlhLZ+Qj&g zax*cggvE0D#bhGp^!MNxUuly$#tZ7M=k$P##U8SQ?Z+!=G9i|~TgM-G&OXn9+OA-!SKwYFIQ^9BJ0@9XHazIk!2@@)EdDckY4($MJN+&kkk zdVi_MlNiTlKOL(kFdtel@2&kcdFxrQbi-CURXA?Ls%`Z~u=lF#cUe=}hohB(S;g<- zKaZ#RT0fg z`sujymoDXNl_As@g@H&vy&G=IQ7Tr2czHKegT->T-pUJ}iEOezHCp z$A7v${)0G8d)fO3q4_DB{>i-WONP11;OqIx)mmrTSk_R|b&ck`u2$5#bLIdb3Ep{$ z!shwdxw&d}vt|wbqw&G;qrvND;V;Hxe$0<@2f)t4Hj+G8-(=l&gI#`^?Dl=m?TlK+ zwugB;+KtynaAxIun}2p$3OMX$jwH^;a1$VP7#$uq zYaKnfMExPAyQzsAw|p#5#&|eGlUdOmRxC-WOe#wE1r6MnjdSC$5h31lO%5*()`ug4 z`}mv@|J?l8DFGA8$*PU0-w)mcd;G2Yu8CL?w@w`d`$Ar2!t9>=dS6(Pws^AbYbUK* zwnTroI0R|7&V&*&gd%c2FFe{lHaUM%ymOj9_FnXA+>z|(J+C{Ue73D!wrZYTKFgh6JJ@`;m9;scr9O{Cms5;{q(IfI5GzD5Pf!CZ3gI1nC5qAF zT61TP`R2M-9~{WNesY^b>kgsX$4M@~xqZ`iaRY6EfI|L_%*n*qTmF*?os{fIW@8y$ z;;IBkQ!d;+g21`yBw*wHpZNHeS>ai>N3QP3G*ewGTKT&e=tY}Ng{;|w-(_Xr{WR@s zjxl$S@!lY%pSxOr@rBmnY8_jnQHvdAkiq)$wvJpL=bPYF{KP~_SlfzmpL$%a4p3*@fYSVIUzIxv!^k49%F4#*JdP*a5$UpRRdu%c02eNQYgQ()wZnJ>Y>{XDY4 z?mFj|j+s@)*)CFZFYBaJUI8LJ|F%Mr1**`)YOb6bvE?Z*vRX^$(YVs+%OBUWz{0uY zs_5^wH)f?gHM%o19~I+AHNaKXk2qN?kK9Q`jy+jL;Hvhwe{d_gkY*}!Ttj#%jzvdg zB#mT|w_lzy&_5)LBOnB6giu7|HFZu~%uqOV*;067Epe?T4Y_iKf3=Up*_#_}v*jS& zlg(j!rrc1{TnXHpsz1ZZ5+2My!Z!y&5!a$w(G}bOfd)mrI(EmVbGK_4hD83rR#;mMNC2ga+jnydd+psG zLZEHE3jUVK^qLjn-ie)ebLZ_xE>rFM6XiNG6!nlQbHIb9Bws+c3agiPOUs!?6g70- z)b`n;0~)VtprDPEd>%oBbJ&Sow#fCTaw*5y`f%n0=b<5MwDqLr=q~Q*!hu`Mz=DCn zE^3DkPPO?@dt2@^YvhI%eluu02`BE?R;mbnp}QqBkA)_YEk~ZNJH0HY%as}omy9F7 z7R>D$@3pD4>vTdTv%)1m(@?E$K^1cXlw*^@@kz1_8v1@aW_A}H{?MxdfoA9|v(Pyc zky-9E-AXlpLvQLsYXN?l?O}@cqK<=1dFLET`#xUS6QXe(yX_&ZfEDpxT6Qtotq@8L ze#;QEg=a>w>et6OGgoq?HGP5u6k0-c4THS=?CTQIcqDHmBu7_vQr1}m-s86}<|&tC z9ZUzXZMRpqq(R(IC)5=ilRJh&+W}~2$u6W8yMg3R=-uN5=bGV1M;wwP`IfS!k}GyM$F~CogT`QPak!)+;tTWBe@g#dE51MU(82%(FwEc!M%vgmOl@5;Bc0Wc#jBFFNdwbWLBLuzB@DjgEjrYb%EZO!mDOkhQ!{^(&2(ayUtfSp`}%* z3~~;jzcP~i<X%ML%aL6Mba3!EDn-ZN8+YJm4ZhR~bNutyQfW62>6eFfzcO z`5;gPV-uNf-y2!2aMYHY?4p9aH|0^cNQ1pI1(oC8$9jcDem@>2($DH$$(@yw! zU&{ZpAHt}Ns##7?Rj9jAzNMiB-Utg@qvNmBdPnyGOU}Zm7+5Ky(%_-tsWw z*Zc@%I9jvM`PE*+jE06MSiytj1osQtvBMY`Z=OF!r6TXXI_R{bZgsv)u1N=cj8qen zNJ;)7JG2<4IJGQt9!N2H)SQU+p2)dLymTi@W{UOD!|8SfS`;KtpE{$F^AW+>Gt$&Rhn)21Il4jHdrB#a;iRtpd0yB=If9<=!1*5 zQI?>H8UIA2g`VEmyuiE!9-;%2MKno_L>Ag$2qah*XvsnYoo>TV&7B+*MN1_=j>RiPxm6kM!|WaJog5Qd}6#EJ`c^ zvC}leQIxqSQ{U8?G83k4xfKP^{$i#3fw|QD@!2@Fensc$jC#pLG|R-pGEYvQi2M_l z))A&>I6rohLM^`VyZGPd4uzu0gM(3y7(PKE!HycPqc|1^+eJG49+xI1^%}L~a-jtj zF0($Jz~>7bI~Mu1ZYeY+X5ctsdNTR}aT8e<7loxJj7m&k;_%Vk4X3AjQwrgCkOeA+ zXR3#tZjS)Bgm48(02%$5bl)xQ!pR5s_Jh5Q=RGH}CLQsl^k9k^pRsD6myJHc!Rt10cJdg||8%7I(Dq2z<^Eu@1B zjX@7B?Jnmq+~3_NR96LGc)rove8ZT+YR9|`jt0)zZG^biGMn3^&bZ%LHrTcjOe5dE z4ArJqnkhX2u`^&vM^MI9mTy0q0 z34O#rnz_PtF{M-p_%<@Z@q;UJM6Z?VHG0_0Ay>k)Ofg9+*^^DY7%@9(mV{{{RVZ>K z1@6#@nEHa$d!Om8-b==fx6a=(qfa}JJtSSkT$YC4WEmDdCeJ8KJQ#%`rC=+H9H;){r$E#ncka(ti-Ta!ZKSe-|hSfum#w zZOa;{W-E3|t!Q(Rj0Ob;;q1aDEz|gdI6YDe{I$fCG)HWGOtGBPq}hOZKK7FOS-{8U@r}s9fYo~A>E0r7D2hU`@~SS$pHtXDLNj3DzCqCFqg z`=UI}pR~vmfNAGT=B`}FyRvl!zDq633Etd$6D2q%$Ij$DL4aXHnJC|W`H~PIdU|!l zEw6?1Qx8=&k){e~f1}-Sa&thLBXJ)5DQ@igN0>93!3pTzWPJkrrr<;bxQWAVz;Q zAq^@cU^*P6um>0HbuRv$WN|`?>MNb zy-c?|Mx3Ue-yh9Tbg0aeAG(hb*L4fKOpFNM@`unxoh7O$O7LZoWNz0%yzcES4wNFy zOY1aTailn0@U<*Z|5?*o)+T=f6SPX{OdYLGDSuIrlb*S3sJa|WJs z)iyAB&@;{pdF+j$Xghs08E#{zT3gH}ck#X^5_U9X?>a;ddV#+DIoplWh=VAs|PDaf~*op3Aw^6!23yZX# z)-dl%B^TDJIkHI>C8iHeeUsYWidNUD(aWjjy4vAX3|c_|?&MSUCJ82Yh??FV9kV=Q!=fp?a3E&aNHHdZ$QO`|~C(O7}?s2|0u8qoN$EL6?uOhczK z2~9cE#<1F!%N%(+!v@*>Lu^I}5l)YyUZcdlHtwWcmpRKTFT@d5Laj~KgbuK8I}t4c zPA}qJ3&Hry^FL6-tReqE-RIJq{Sl~Ya%ow@NEEbSE@61~EY}-1;F>#1=l>1P zjZS@b);T;A`87As;KC|6&DqLNzsNZAk&?+kj*iz!s3^u=(J)y>m3y85H-^{`i~VSg zZZO?q)gQ%ra+4#K-FKVCgJ!hDeD6q;&tgnvt*FuBw=P*bth!MOH&b#mkHTJKQlV&0 zlay$;`a)|SkOulsR^=$_5ms*Yh=uL9v_W^?8jF^jE#51J(Ed9FA(@-=CYcSu>@OC@ zmNA5xmPUdq8lq$hOYaf@%a8*K%e;%MkGt#J9z2onkotL_(A@qPW`!E8&K4cNOH zw=_jP;+~Am7nkBWKe)10ZH1UMP(WQ5IC8wFOz%1SJf?`~jQ}(W z^^QKcqFz~6NZz?L9UFaQaQ8#&BF9OZ_Bg7wI9zRH7otpT=9Z%~2zK}oj~t%HHbn=5 z?i)HS<(WR6h=fl6pz{*8TfEWY4rGU`-_s5?Y9> z+)L4K2ZZ2J!99Fz?RL=tC#e0*{sWD{yqw!BmhYAxX6S6}uOnHl22NLe{n?cf%>lMu z7q}okHHMK(Kpm~%Fm7_)cxjoHNVvAg^Wp6*?V_+(WuT-UPNv`p0QrjZE@v-$L+Y-* z0pDx7SnQ;(qQWslZ&D|yqLZy=PM)}}^h`TjnQQod*o@vS<2!tU+${iDAdPxEiozU%YfeLX z8?eYdzhi!=AlHsT5$q!AjC`D2YU#S)hQ}zST>7yb2TS-ZT^Ez2P^hs&z2|O@-oh0 zliG1PFSfk<_0L?7@kXYiOVsM3^!LzUgQpC}9yXr~@F+063R9%)j+b$_=`i|v@f`BR z&xGm8Of0ULp_Vt-_7bD+ocNAhypvMwGPU=rXlmQm{OYdTiZFRBSK7eIaB&3QO5`I% z7v(es79`r!D#Ie8Wg3gh(~1+i)HlcIdk1e+_tV0mE=FgcilPL*OS^;8iQJ^4D^3qD zgb7qx0PV_ zN+=T!x|2pqq#F&(;EvQ#zxak(p_cg!Rc;q}tP;m3H=*BA(_xp;MWc|u$T3V%@+_8( z%9p6!*08pQwv1)laU`cZsTZ4U;(`1! zS7*O*5ddcC9uqXAo#OYnI?IkoZ7+e1LbFASfiWo~hufJ>Y0W!;?9@vbZ?_`S2j9<3 zDa>0t&(c40OZh{QFA`3Hqsz&{Kp$A_<8Bslz^<5DkaB0QYt-P4$~JRR-&t793@aI^ z#B_hmwbb?6utDCIXNzVM*U+WQ)Rd!89Ml_mQ$YYjd}rNjw8r2+Yt&RZiKVZ7I)XErGlF7HFy4k9Z5bsgt64gWWGZ<~n zf4HhEp&QK~jf)8Geo`z%MB&BHrNU`qNoH7uZT+6LO>XC*U!CfZK6zHoq`2th+E$w< zutufll9;Mc9v)Z9Y1M$7F_mNe(2I6_aajoogKQj=J=EIt<=Fn-HgU(zGYZlp$`Lo@ zqARJ|v;9Ox;vZ*FC`Il9>KIQQhLa9|t}jpG-iZ_0<>l;nrSX@g6XbvA93 z#s4su#*a{52{%-*K6}_UJB)?J6hI+O7ADQZKSCUDz_nL~!L?(2| zi(VAdp9wnarKt`z9OMSV3X## z9ceANYEQ-&>+p;M>Cn9zWEt96M>0C zVj<@KTcT7ooiMBg77Z+-Urtd{Fklj2}Gtd0_CMUiEW4mygNuKsf0km!7~RYSEx*qP2ltF91RNC^-WSjEXk#1 z+KL$#+G3_D7J&zfWh?mCPfuVlL#h#HozuSR1e-P=$RgZ~yzA$pm3J7{lbr@Tmx2Qd zx3XZJaxoaz?C#R$Niv-pgHi7!hq_s#tG^?7-^N2lTbet)aeXfx*OOYXzl~Sg) z6REk;dDNNg)LdNs)VVVdT+>+9&JsKfq--Go**#Zh@ZdX_jEeOhQuajAKgaX_8vr!`x8&&fUv;Zu3oQ|d}-!$n-rTv2kipZrYt@f{wU_TEc? zkxnJ>HIa_Q4S7?P#l_1Le$@VDQI1nr3~yCTX>uJs6%Vnlw)PRvexSn_k>5qHDN067 zGUd1B7X!4zoILD-)PP%Chd5_drk4uiSwsmsDU|OPI@9j^bV(x_DH97i^oa+<8NV8C zPjTpvhnJ#@gaesAxnoS7=zS;qr*kdo{a0OjNku0R&vO| zLgV5orc-l@X&R@C9+B&CAS3|vEWE;n-NlXxr5x zJbQ4=BJbK`4{f?Kf*xv+UvikrTxVz!QK0O&uUhF|=e8{!&4zAOy=EtqC{V;PC>+xc zm$cl1)aE4Bs)uZ}%vN;*Ml$wZZvz(gADCU*olm@I{%{Q%APM{wlQya^1h=P~g2RNd zCZC;$VzzUM!AXM}I!;CjNf3#eHL%Mxe0zy(GYr2C`Yillblhd&K0>zLeaZ4gO{!Ck z8H{?)#`gIG z-G!z={V%mB22|q)0Ny=9vbUA}cy-<}Dy%q01%<1=6fPF9n!HxsP-!d(^b<~VBllK0 ze8w6Fu6$HKM6sI!c)Pstc$(%sa?{1zLEKt3(Qe_Q{a?c5}8O{hA7v1afFjIKfdPW^=W9eFUv^9(vfu zL58uEW6Er-KeP>7Q<3J*sx>mpE2)_~)*j%(Kb}jA@m6#WTDIdJ)9u-mB*hEGTwBI9 zWGqsFon z%kj5mboZR0Ha!07XEN6c@J@5W_)+iPHFp^wXz}y6F!4ZJsfu5q9@bEjZo2Ypb;o*Y zu_i9(qnde0t=kuvV*j1SnQ`$SUI571P%f0z>B*928jpJ>gxL{tomErX6+&i<_xtT& zD%|cbL#rMh?Ia5Ew;!&=926iYgZ>qP z?*ishb5*hn`4^3 z6X#K2AgsC9&cJ2$4qj14p%dgoj#xfmWSKxx&iS4^&S|XT**tlc-NI#SD4qZH$6~$` z6|a<6zYe8%GYV+vEFtGQt@WnRWh>Won@;o1CM#w`1vs4qvuvgCDgV9et1Y5;B9JLq zFd&|@Qx<%uAW2G{z;5N?Y2U~kLM8vm_YV|j(rWViUL>y@CWa|#5VLBFlFxU1OAN}F zfW}O2)RIs-`PYz}i(m;Lg<0;wO$Mo5w%kva)|L^wG|*HSi(5cac>R>1o2918R7>?V zbqB}7V(J6at|gAQmTC)VO0}}0wmO4LztIfG7`s+q57lO}9&7rxU3Gw!Dh2bLgOhZ< zW?6;KmJVmp1CB_c>>*L6x3Q$dLu^&E-!L=Y!%n_?AvIBjY01wpeNfn}wrNbK6QX&=epEJKjj;EFL{J4TS>i`B^Tk*QV2O> zjvjb+Bc$$)wJmwjmtAn5l~M+A`c}@Qe(5BD%g>p)6EHjr^Fc5mZfvLFn8!T_l*%2Z zs(91*q5Xjvjp@QcWqN{mu(E1#(kQCs$Yn4vsQlHgvojmS@JaMewgkV?AO=6yBJkjx zK9|z80v_|*1ZjalgAC&sP_B-VS95)ED!NYYdrs9ZJ@GjaDtbC|)9uhg&hdDy_FY-_ zUZ;hiBDucTp{wQQl~CX-_qnfP z4MCvp2K5HbFxFeUV)Quq_`rMXQ&VIkCn#d^x9!a8CNnJu@)rHkNAsUqPfeJaW6ARh z_*q`K3w|;lzs5q=8Cq9IrWjn6lNTqfFO{r^1R33c0L?34e|nB(h)j?2o=ydwJ6V!F zOh(fw#gSFDgvwVg`f}DmL3oyFSiV8$_^C`pwh6p!ax|4ZQW7qK-7K96ywNLzFPU>W z`n1dH)3R?&&3`(3%MCBCmOi&1Uw?TN@hG-6^64yV(`7$1xn+@=eXAaiIX4MgIA1#1 zjZbu1@nbAc)(`1u%)FyVn^G~Ls)ut}0sw~PXWKuDAb}FDkwN{-yfv`kU{!bv`Kz$- zQal4cMRzGrN7eWgA-k){7C z?J=oBeu2rT98A<7A+~r7!$OH%F)6>LQHf{FN0KT_mOl|SAWh}K&&g+$hw)myXH$&& z(ME7xl$lG1Npbf7Fw#h~M#q{ljTM_2FPuaNB@9wCt6ufWz-VU-0>fS;s=I{DPy*kR zBBCf;?W=WkmPJH(MzY91Z07(QIqO?$`~&>GwIvCL)6xcqt35nDjKMY~vf(IPs@m0> z-%zQ9JmUmr!|IT9VaHsPWuFG(52WZX-&&&)?B_R}b@hSbx29cZv6;7(lCwit&9$=L zw+}6nlSg-DH{Dc%iiCH|tUzNFa>??{R4-v>WZm8V#ArUO2~yOm&cT;fv0WD5kP5w; z&Z@ICq2XN-JAK;Hj|22$xTCtFo15Tt>*Es9%ceutnEiXa(h0C~#NZT-daeNH&SWd~ zm-RomUE+7T#iZ$`rdu1v4;}W~$-EurcOk2Nr2W22NS`X$bh1Z5SU0(2abw;QJpDc6 zKyH~e1sU73(z*A7?QG}it(*AG=Qu)cTcqJSg*#iql?-Nt-!Eg_xD(dFLJNz`jxKhV zuCSq@$11LHwcd8tUXI?D!LmpDZ1PwAukIYdWVzQ*s3Tx|5~WSNB`g12~=^CWw% zXk^fwHXCbiv*sDqht~D&yIIm(7FE;eYCmPk&YU&ET78i!@f;o=cq(+W6C5*dp?9=W z>v}ZDI_*GyBax<>xy@Fe+FZSmz=D3L!kzb=H1pooLx+3PU3055!lIlxQib-}GwbAg zo<#G)b0^@k_r#Zs$q)>k0iKKCyfGs?eI=g566b1i_Hj~1>7$#=04+#H2wInSCAP|1 z9|2)K97}SikbW;5OHF^Hsqm)vgUQ+=IdE5)Q6bc`371FUAU~qHa?@)~YnM@XwYrwRrvb zAmG7-H7p2cWWGj|SVT0zVHIGlRKuEJ$zg*eLqx@<=pV)vMm-el2USD5_VnvP956v) z?6^tZw{O(?k`yNpdi+^!sO<}krE)2S!-&Gz7srk#`!pKKiw!B}^wDQV$-P5P_aN;i z=ARr+tnL9A(f!21rGQadh~5#`^z6HO&2On&f_0nfk3os&2sp{@svOUBWuKCpBgjKZ zuJOEBmLtqp!Hyfa!W*Xg>(Bd!PWlj@NhsWaV=tyk>+;1q(RjOAOvH%u0f|tIqE-)a z-oPyXFzu1>@Fwy4LbYas3Z+8o0hZc&z_N1udOg6`q-dR(&ItC~_hj-rRUE+OQaiKAuM9E1qgGk-4c= zwD2yr`wvt@;A;ANGFK@ML_TAsx$vhm!H|Igj`gikyHM7ar66S-v*HDyojaWPu&5bQ zv#s}Ga>j5IJ79Xh;SQa6ld0*uD%W`lXWF%Hk8q>gAT=(5dveLw{X;LL4HJqXCfR8V z=@Hs{7!$KhR1c_ZNLd!_eFY+Itsu+dnfOC(?RtACufcD??D^LBMVO zSdJ>(=qstLRm!tH{k{HyCxFS>)(MK-7>v!}xAG#J>M|WE1Pxo{8E$BUwm;CH7L>Yv zv*G1JQ!>8w0e9FSXOr?-@*}KIux90Cv}88*N6G9087$B2ui&46yg3fm_Hbm_hWs3z z5t1&GU4eTIvC=K!XzxCkw4E`MIASufFT@@!3@Y`%4maA1wq*SMT|3-`Vp-%Pao&m1{2_6NJ?IO}ek=k9E(3=qCV8P94_cDGEdD@YtSiU79`&bTWMk(zRfzYE1 z5-hiJA+qdOU;ASYK_ zWW4j075YI>+M2LGYr9agrD-W%-p{vh$K*Okt;oyPE>%DLv-vE@y+^s%EsJEK9A?ET(lM+WY^T~M0H95qC*(Ya`Z#pyHXc# zeh45tf2_X`i3ErcQKrmwcNO;=+R*e$E+1N=A3uh6_p;HTq+rJX0|f_?5GVksn$9tc z^2YrGMW*Qk)II=<^jELpfQZ5!tmDiqIZH(Njy;DQVX>yg%B;+GKB;fkOGjE1#bFt}$NpZDua9!D5N0s-(4mrK5l*LB^k*MJ3X(=EZWTOu>Y_ElzRE zF=F3TH~CSyB<`j1$VadAjr58b8Q}LejTLzhNFQtroQijXqumb^O*OLwZ2 z+-YU3@gX3McPMK=hTORfgp|8(D2&lqOJWfx8vHyFsQNv$l*G+KN9%}o&4Mb?Il zH1^5qx0NLq7x{6J^yJ)OY(rHq@C8E~vn(yxOf=nf?{+-^26&X%j1nrqj_9u(P8Q`nGAjIa?&XrGQ9ObtkSqh{YXn zno^Dg1rF7QD^e1v%Tq^3wo7J9l7ktB(}gZZy@=)DtNXz=6SI6-yH;gQ{E4C zRZEH}bV$Imz(K(exkFL54b7AHlOpVsUpg6Ec2_$^=|ONAF>lx7OPFH1&DB2|6d2{u z3Kdx#(dtLy8h$`ixWuqzlem9#G9F;jkioY|*dt6~sq^ljM6bq%Ac6Wt`DQ=C*1d*Z zh7>=?G6KRm+J}95nK&~Oi({=D9!K{N25^Lw%?PSNlIBxxlWtxzCj{NJwhiB;{H(CD zLL8&<&FY2T7UMK+N0d(^N!`cqG3YRi+{b1>{zDGsOEoSc;FLv7n<4ECrC6(E*sn@; zgN92FV{+zsNfI`L^N-yg;*&nV%T#j>=oz#nn6IKol%PSFy*6Z3b!0|DB1k`B{`ND@ z5^E?3VUsFKviC0u?otujEIx%EC8QD=ZdD^3Dx|z#ydearAI3FCy!nBV`YUIgIonCH^v5mb!zR z^8eDGgXK!76oM5L;28lW1`zeGuMWZLDKHLFCq&qYB^vqA;j!uRjZoMTk6122kX!J7 zr{xOLQ#jD#XjH@@S17aOLk%H>)#2e{62V%KaDentkS5#0Eq_26K0=aP!3%%C19P+x ziDoPN42TLZy>ilLt=a#Crtauw(pRRb&; z_b^!yl09S%cZqF5Hes-+L~ia;u;~2&)5q>wr)7>X$iWY+6=?Xs#ERxnthJ4*zb}gT z>c8ARfKkI{>Np6dXVyhR|Y^fdK*Uhb!Xd3LE`*(~*rdm0lcLQ!iEaHa?DPge|Dqz9F~y>^ zDM6`=tMSoQ{&FkaRn^@iu$#&7WPD|~+Hn$DOs+KtRx9w=SuiHA+97_~QQp%{ac zye;pJvrX@4y`%I+@P|eZ@tgJX)9X8_dbbuM#hFYmT_P~jgAp1X3>OT4?UdQ z+l|DhRK{Mn_y-^B&4hAeBehA8m}1v9eqZyhFWpXU<$UEK6@$pr8P-vm2`4(i4X9H; zxIW$sY#*}`=TveMVM5ZR<0FGC+cw3}m|5HXiXY>=6FF{fSI|}tn+%8e0)r@6?1Dnq zkOc=g3Hg&0jA-PK;8bkNt*@|=9er0pijvyCYzXCou5!q!QX~gxXluUdp=@WhBk~Wv zR>J@R5r;s$(W2!cRw74^iR5%ENGUgME`zVqR#?JjIZ`z~rw-)}8Nkdm2g+ij2vhfwW)`%0m?DXz`@37PfmPa9SC zkO#t#k9m8-l%s^KUR~MSAZ2~X_Kr^sE%`Eu`zCfjs25EkziF%zYKz|JuZm7Uo47Yx z6{_^%F3r+!w8rIbj3m=d8nI0NL@PEBQg|AZ-uz+=$Cd#1;Y1MxCwKjXdVEC!bCfu~kxgn8zO5F-4T*?LC>NZ)zeY z#{g)Q_UA-@NP;@D*ZkSy5w(Rt->>5>5FGEd8;U~OlnXukX0FTnYFf_4H1EjLP)`Qe zev5Iz2Vnn?eR>Zju9eQF7#4YB_yDhd{NXl0po6Cis;AW|swlJ)dyXdq<}q4gFNsCB z>T{KZ-$IvB((O7JP5&fmo2kuOpJ$k&MUzQ0Ad8wxPqxI^YjHIyT0ud_JI#&B6N|9{ zd?%*}gVo{`rYa6}!K?NB1@Jh`qRZh*5z@`s$xJ72vLW+JOO!U3&Xc{w{1j~O=$afw zS4#2_N%>j2+0sIY-qk6{2PiCJn@7>bp4rslkoJhkY&+(=;!5BL<9m@=pEB$&mlGFV zgsU+|g{{Bp=1DoSzob1n>3MhctMO;(0GVt~L`w-m%ivtOB8&)+lB7#9&gDd^5x|V@ z-H%jCWR;zxi)3co>Rcsf!`KD&zEYXaGpW&bvxn;!Q1VnWUfnZ?ZiC&=XeKXOGhLI2`fF)2d-D}?;7pY@;DKzH595vYC7@@^iUBZJhxD0XlA*%}vPW{ExL10@{Ipn| zZp-OKHR*dV4pM78U;FEKL(b>^bw?n?V2C5qUAyhH-m?hv>hr@)=19QH;e*e*o`rKK zRWhfp2@PSXfzbDYp(?=$58NOJmkb^&J3-406^tO1V;q>I=Nf{v+fE$G77ji}nh7%= z(5{uvrj0L2;arQ3m(HV6jOkI=d1V%YD%}P-%LTaQRat-rhMfo}&nDzbaxI-)k+3nJ z>+yu5o%VCLRs8|NI|mK@k?FQID#}IVsQ!V7Qcu~(vQ70)_(av_7?Crpz~ofC=-XB^ zu5<%l3I|wX3*$A5UFDtZ;zJD<=+T9+VrepUTJq}%f@bHQ@-qywjW>~b;VdUt%Awg| zy(6Zuej0|*$^AN{9AB-I1j!LDBrpiwiQK9@B2aUaZTiH@N-O#VO*;g7>@E#zw-_wc z@|}h5M;lWoc}mVsRmMK6L62Rs2|RyH9b~~OV44|28{6nN!=yK$7CbZEpw)aPjV-^L zBV3jf$EqtUYbDc~27{zO_dBi~fp5yIZcNm8vPq$alQGL{cDMO+B+Y-;a)iI+grpfU z#dCBB4O)4TO%Y3pNH4scMN1CT8)z9h!g(%~Ez(K8guw9pgs)Tu0b$gBr=F~9{{)<% zx>mKEIA&thGyUXh<44bpV*ZFYusR$1Y3|!xfHNWSAdpDCSpU+KKa&KJX6Gu&_vtCc zx+XU3r{sZjj1HN%kv4^oAVPwu#jxF!zH=;(6zQ$-{zCgHwJg$WmR||A0;oeCe_HZj z<|+x04XN080#X}igez>K3gn{+sG9X_i8J_fqn$UE!etyM_-rain_}pE%1uwP&awPd zy=(LqG5cvWEl|}+HF|c{Bo$zc=KkHtkp>JO~rDv|h93t+5qO8*2ZWWaVVdEsf) zS$yVI`?hh8PzZ8MV@y0P4}{OFd(+lEaVrx)KDptK<(nm z2>z^jii#%2fJfEL>`T$na6dtRVmlQo-UqO8PL}yjLR-HK4j175SSLswVB;(9AE>a* zC&W)tjPffo@*+kPbg#f6nom@1SRKwos=>RDX8rlgpuSE5XKW*mgOG94Lh+FvJt4&Tp2yOITB04oeeDt8+P#b zYT1&$v5Ii^`V0vcqle*D8LVHjU{|kTneNG6cc135oy-KNQrF|Sj3{zd(*eN#`K+Cd z_oMpmUe&Lf=Us#J@_!XJ{U4%ukj?CWk2C&98~;@%H6&OH{#_FNwKn*Cy??XyH|zQr zlzron$DP|(%15v6_Q&<%rS8k$tY1Rk7Z6;&dNrxk=GHp>+Gt;UYrj9Y*|-iizFgnl zUj5nHQcKbZLAq_E=$&tL4p~4{LJw^=Tk$*LgPt~YU!AtU$D8W>H^==y{4mu)Y40l^ z{|p5KRE&@fpIBe(zP!i0>1H)cJ+lSJO?}*Z4lF7vW->{juJZYqcm3fM`6EFQWE1k= z8wEO`w$C%gOp<@20RQs?_aE;0|Ei$v|La~uV#<|!U-clOFw?LPyEn%#0Du2C3em;> zcG%0lpPgWePp_U_#+*ZB!MfY$W;ktjs zo&&EmyyW^g^XgBVb=5iLN}4`S*e$X3-6w))1j;<#crR>7xuvY!l6=<#&fs8P{G!sg z&QA0NYCq+2af*k~iv{}pp71gFRk&?C^R9rs;L1*&c>|lAu0KZswHYRKZ|6TnYO|kv zf1hU_{24E_`Ihhn<@rdH8&RfZi@DJAXvfJlc1}4@{1p$nCe%Dt2}7`o=jE`1p~<&Kh~* z*AxZz-P2gy{f4c_(rsxzeEM!2YR*6xL$7d9ED$nlf^r^{qEMgF7WFR68<=ny%qNt7AgV#ei8xx73)+>au;RtJXG@nL33 zMP}B7v`u*Z2WoS+Hnn|gx%VHa)EdUa@we*W^R@TZo8zCu z#fdS~wL2nS52Ea7oMd_^_UyQOpUqSHa^~bnPty0UaPsgvkI zT~X)NpIM*RrV+`HZB4%>39^%65G0YUm6~n0Y>}i;QYM*FAC#4CiJK*^9qgKFImBZK zYV^=nl7jDbY?0Clt!xMqn}~8X*fCBpRUIVG{XxS%j|OSKJu4=KKWFe(|IV#Qzz-{I z14oB0nM91Lse0gK*1t7tt3;o+r*aj`@U`%dgU^gsNHdGMKyq2sdFZ;|B%ihoIi%&z zyzuMfJe=u@MLy^~98=1s(P4~JI$*O{Jn&zU9T{3{AkCh?h%pj)*fYr zf4MELruunL0^HG>LdNmu$8igq3DAg>(JN-y0WZ+QTVmLDRBv!zG>OhNwkDRv(~QPN zcX|~|_E(|pNgZw4CWVfT1Kj6=vK*aXG=VlhAu9U@EzpHtA{K6%cNIjJ1i9k0vHEk2 z4L+F85XnDoA|d&WynWim0gH3oHDpbY8`FB%PJRpn9{_DXZt+1G!Xrs3oNVONXUEL9 zj)*|U4b=0Mvhlb`%*GnYA!x2)IdGh`(tq$<>J^|}rwep-HC31Nl#FyrkFv(0N)Xt- zF&nG1Kj+c4OD1&IrgncE+(@d{&J!gIZ)|O%3B;j}I>)AV`#z?Q71&AQVZTI>HE@TV zLZD7MP=l=uw?3p6v~98OmC2Fiz<9!DO%I*_ng4qg;TNLoAMgX}nU5kV39 z;pjEo{>s!6*d3s=t_t2I$-AbO)aXU}0M53Bqc9<_vg+1={qy0^Ie>IN~HsHCwsr+3mA7tSjZ%VG zLCf!@Lp8$Iw^DXpa;tOH(><1hQ{$F_e#4KW_k>W)I3-^mZZP|R9@?`zO}ak&uBHrH zU`#3|>A@-{0}qx*Q!2*yzmk8L>fi;n}ix^_t?WNf0;SyotwBH?0!sX6U5lOeZ8McLW& z7x{w)o+4?GgXpwNTXZOIu|~L#Jkt6NxR1j}RnEeX`f*2gd3eS+l$jq4?&uZLX*29p zzWr2}4|r}-HyE1;cK3?0!2#dv`Esjvrv@Z~uj5YBDh=_Oh`|UV)L6JDO=uG|aU z{0gRS@r=t)5rg^BHbnc6Ru^TH?+-jtq?i3pByI2{Vs!)()7DvSOk)kR zgs1c0spGWF^Zxc_p-&^>hWgmv*360_=?9e*3NWOHI*?l zk?{eyE!vXnyOl#W!({#OQVSoAM!@NCx!jQ}rm9-)*fg}NpK{iW`~H2uN+V5noc85` zzZ;w|a@;A30ELeGNO*hLD}5Vm60i>>h3Rq^dc;I+m$J9R+%Gaxhl7o=6?g-;W zN+;Y>%h8yvTLk0XM~mLK(%rjEt~RLhd@O3cfHf(7aSf3N%5JS!Ja(y3#f6F2AZ~zL zxs1?1s>bd2L{m>)6v8E``ko(9sl+%JAVFnDIy^1ZTHtwU8LLtAw?yrz zkNDBqv1;!kI*kUvR)|E8qqVn4Q0VWR;yB28iNqkZt?~Uzqa(3COg*uSn=U<{MEph& zJmP_-f@q!q$=V_L4DGtaH_@8m2F6ZOO`U!xCDQ^kSzx+WFY9kp`5`YEza=fMq-!mP z44K5k1XKs1Ed5JB0}|RWgKSeCA(@uW%P*+EmmyV|=>DF-lda5;UCg{*okwNojRO_? z!!(%s2ggws=XwBvKGQvpMU+IIeFVUU6wx3gP1${IWb*G)bbs>=|7r254qK2{bY_Ke z6qTF&H0WN7;O;KTC_ERP(vnpo{&IA=c>@VW00B>PKHXRe4mv~8h`yc~&p3FvJ!q5h z`?bdUi;Kbi?9Y;>Jgs7hjs?BPW!I*r8oT|;o{W0(V+|Qy_!>Zx{d$K{wv!*iI4i5s zLBNyu73fOu^3L)wNKbL$pui=y*u#ytc(-0IONft5nDhX>&Dlb(MC=FKI1s?7D@a|5 zr!!0eIc+GJtc|6kozhr9PEcuodHTO>ce+CZg_?#P2aR3SZUZM-=W2cdo$XEtVfzwY zXxI|FN9JC@42zjy#XQ31{$Iu9Qty`Qsx1&8VJugRe=&kyF}>!?pSiUYJ)0oJHOTfU z^#?ta9|t879Cf7S6q1aEas37q-w&>(?knhxB2=zELcj(B)Ta(=^y}%b|9c~W|2IKK zGkmMXTX6u8ebl_SOrqE4dNau1s0ES+>vY>Sc7kNnC_Y+KO#8Kpt^2PnclW~A-k5d# z&8YcCH{Um324|-Wo283=cJ9o*p2+PCdVLjqd|ceub^Z97?D!s(?q3Dieyi$i*=seg z4StQ;b_u$_tsL(<&WAidO>cBhbdLw&GG5kPx*&635~6boTKYjL92P*0P_+>2en|)) zhV~mhaN&YVkFF_L8gako-8!~N9@>XMSay^@QgcUy~o9K z&3$QY0Lz(EroD4pYeJd9aS%2iZYAn8@GC;|4a7R*KX+s^ZiN86D3F#QDeiEC-!W>K z9n}bIrP*uFu{MNJC~YOLarr$K`jIDKWL%d~)0Y)ee4ADq;2I5}z2z67wXu^QJzDV` zM6$e~qmY>klrDybnKZ__nCKUC=$|;x?)a{B%w!9p_4Gf|Pc18@?FA@awhj}FA3Yz& zHJO!lU9TeZ%bwSqdiOWDR%`T-rWCcTyTE4HZ#R6teJ^%*Hb8Ar|HVGn+4@R6zS9sS zXo`Po?Kb^#K2u56@li?3$Irk-Etl>7Bfm~BPd*QgRa5Xf?7-}klxRvVPU8~MNJi|c z-c0956aIYNXv4V=67K+;`c0>kRwtF>gXhHW!2y7Kw<#iSj+@pNgV>v<_#nZ}&<&o_ z-^?C1t;4>)kB%*P4k5e`Ci6j*e6M6%O8x@c0Z-|&OS6TaJS!*E)0Pb_9;PJ$~5JU7+!UnqrD{YI0vCmAu`eJ9+xl9EQul$OVdm0lyM!2!vx{^iGhT8Xa5^a-N=}q!@Qx01eqTSfTxx$=!F<4J7 z=Q6OVM~59!t7>a4&@c~ifCaLyrU6~>jOTYIk|GxMV7Sa1l9=JXx%%)vz( z%fw*%03rb|+yAoTY?~kkv+{X#92Tk{;wzvcGlR-J8x2#(Q_0*4$JMb17Y7hc_BRAK z+wA3jrnXx6efso{p~c8)FnHTDnxP zGepz0!^z6gu^Z+dP1gYDNk$XPvrgv*U>nt|n0Xl(Y+zdfGH}J)yi)pc0*TP;&T#Jt zg1$$#kA72Pe=szEs6ISrFDI?m+PiJXcSP!Qx~KIou+k@mrVO@b#3a@4PHYnW$N(82 z>0RVX-y25Vn`ZMCHGNlm{w1uj|4<0x2x&SQ`K>vovgCRw$ITCYb1W7GViOspHqbxO zqQ#cIuLatVI7(CH(SGX}R{4mmR}Lc0>6Z{=(eX955uo4Xym?C)mMY{nD%&cVf3k5` zLFf)@6dWPGrl-pqAD%~t={hLwS2pSum$UjnX0?~dQdz@@kyT(Fe|w1Lf+hfsr>!(L zKzf;w@rHrX+|@eU{-=-^LJd>kd0TwX05VUPos2lS8ZQp4xr8MH3Y0sxpgYO zoR10+fzSYdyjpYEgK&yq24~lc{NGOrD<5-0cMmQxC96o9DXjLsb2R-4{#BUoAG(mV z=jF)N60}k&@oe}!J{Svk32FJN*8P`%`42B57%~4#VP#_U@vYS7j2ktNa4!7Ujb^2* zv?$-sX#<~O>wR%Te?^g$aR0aZzckPN@$3`)pNmBMCyg53JzuHDcdeDCkE411iCJ)G@xygkpZ?rDykV5sMCQY6VCs*U z4@vq<*Z-yQrDnqN)v*D*m>_-l1Y0w;7zsm(+J*|_K0V8FE2Oe%e1miTI}X*Yp{|^Cte<0Py*2Cgf$*<>!Hj{d(XSH;!&v!88{t3Vg&a zO0v`qbBNj#)?^llsQ0uzwv_1mzA+}z5nFFzD{%Hi`4_O{o*HTu)|&ZD^=VG{hq7mG z>>7V#`G-0$0(o<%T51*Gn|~O#Yd7q~>q7BrMjFrR4o`2-#~~DtWvKB`6$~`}FlEud z`;}akon5$65>cjSTVdT%2dst`tCSO-rOVg7rQxof6AxZp;{Fk+|1furIUpU2i0e^Z7NS;v}6y4J)hLjQ3H3O7Ih7F)ZjU+iNLka?Xb2joSk=*+p%zc^hE9Rc%Usz= zd!0{s-w-&az7|bOL8g)Qlf`)Prf~_6&kH+Mo%AHPS(+g#4O(03ea5cq)|e-vNBGP| zgpkSBTpV$;LoDzVz7@<^Rvk`_n*%u^%|b?PFU$GmVWaTealJCD5KzFKbcBcG8HUSV z17`wInY-vfZX=Dg^Nh}>0H|%C2>(D=HW3qv_pKBr?XD`rRZM87vRHp@m&<;aQ5vEW zQ!6x7rxwNL=;r&YBv8Boo0QL#ekaRfk|ufrCk`RQm}jwf*r+B9`pK*bZEPfn5~GXt z^W+&nnv*i=d01?8QEr@+zZ`B~UP`RAD+iej-j1GrXxf+&{ z07)* zmt(gwjNPEivvbJ$I67}wm?J#W>mX6YyZ#5(uAAV9H}U%=-f-(7`hx&Y6m0LYET2*q zd1QJs>$*3O#ni#(5*CD?iJNPx(W*2>20eK%ewb4(U|V_MA}iwS(aDu~nvP2zP_fj$ zWa<{OCF@n#`PuD|c8au)k#sm;tJSbT=P+REtpx*(B)hO}v@!aE8qE1egCf0lrmYf= zkQ?7uCo)YVvg&4o8~Xf$FC{0f|4>MKLmr2~5uG$GTe&S#_H%q0xCt_Qa`x2PrC9d+ zL5Gf~FsEErVC5tH6)DteO^-i+oD%*t94j;8P{#4jArMfkR%pwgx}`HX9-7IvTu@m> z!x`Pg;9Im;9SU!yD9LfuRECPpL1wuRRK9ENP4Oqt_lvu|zdYtRldOL+iF(vmW$P1a z*bpX6!4>#zX9VR7fK)f^Cj65VdzM&BS&D>~%4btstaY_n3OBy?u~Tm5xVsiLiWXdz zRfEAVWo&F|X3spnD_=sEv6j!q=QSl=m1@TANCa;wiE)te_l(Oa*Rpq-`6cEPoSY*$ z4X-)Jf1~C#w*p0m)?`lqu*h#)Bs;oLu&0dWp{6rpg?;i z*Bw?KzP)JY(d6DAow3fA>b@zY92v6RwNgJg?W>VXbYFZ`#t+(o7Eagrbr zqO|i*Z~9q1yEspmN-oVA80NK@L0kBKp0~3|ISgb#Dq_cdGLNke@2$%B%Or`yCy3KQ z9;lg(9V`q<-BP%Z=oR`XeOLw93q4U9SAN#vt%@8q&Vs5(3G?zbCzHbM)BC3 zsWsi|Gk=)`U^HVfco^F~>zMXtzq|C0d4u2x=0H*pJS zF0Pgg7OGHGUD(=xyCq#!?w-W%vGr9!v;eZK(5 z${|q|KWW~smdHK%lel(yvS5tai(!^4~9aN5diRoct19SW0v)q5S z9FQ`KCBjR3zAQp0n4?kRP^9npNj)v==`ZL#2fKl|Q%9pT;>)5Fm(@CCyt#QUoOjadlAt^46qgZ+@tnp8`Q4ff9JA4ydF$^O+-s%Y@))6Py`=%mS}dj{)={u>GmhcRExx;MUOyAPJX zUhQ5pIR^c}_n6^1U;L7jnSAcDRN>PFsb^)KJZP_}apa5wjsv`{F=6ScqCPk))>J8y zV)2aA)){BK)On?=C%O@N7|Ucr_S4K7<%OSe+)RTizQyo7JNL$>aR;V*OaZ?1P7lc* z>|66O{<`*D#%g84uwiHhT;Fz0G%SXVM`MB&GvVQTmcL%H?R9}W=+sij1VV;9jU7&P1R%1Gk3BiN~eA@{FB`OtCk#0seyGPNS{AY%v7kOA{p z*8K4SIw!L$t{*aT7&vObc|vey+edTXmrE7WFP18iPITQ1F&I4rPVH~_BP?Z_EFYq$ z19mJL*Urr|5vs{FWaePmSEluy7s)<{G0ioh4vDJ8q9)f+39$_KojIxoi~+{_#3f3R z+Y^JQ^s1U)8!OxevvP7mK_4CZqSyF846m6|T(qSZe|NrNRbvSa?4O$YQtvdHY(Gv9 z@(Bn}Z(-Q>!*yQGte2&}FhBv&yFane&IU>?Kwov>$@;uonUc)mG<(Gfk;rzel**sF z$obSRC*}#TMPk$B>~6Y`8`&2Kuh=QOSKWCw4ouKNWEeTQGL# z$HIQ{Xx2;X>WS%MS<4;Cj~e{scH~zTnu5hsxs;L?8BRd9vqy6*h-BZpuApvx(OLEa zVP(CT4b>aoy|3i%G;ZIhsjfDD>Fitr8+^dJoEpI1#4 z8l4Km+*t#&hD9upf%Dx=JaDH(yr`Y2m`OqyggGv)X;luJ?$lNoA`YoF-vQ97EoFwr^#>M3k!jftGw`|SM&QjeyUsrKZ?+6Z@ zdKx?Nu$HM?*ZuPSezuZZS(HH&&;{4Z4#J~rvJTGv!SQQ`r_Q6Qp555%SFxIl1lORiFliYv+M9;73=^sk!J{qYK%Ji~o1~Yp23uebo1aGKciX<<}7dEqUm2!j<`thd0 zX>;RA{)OxMfrA$vn?-27jlD@t!=s_iaa3_i_$aH1t$}t-9AiSjSLwYez|#@U_}UrH zw`(n-7~w5=6J$SIx)oX&^%J-#{C1`Q&!fi`Ufi0mG^&QgUaHQKCY>Yh{Cy62-j#rqjB?q|4!`l@NZ_0ur+*mCz z%DUOBdGbY0g?4jhsBOj!I077-KM6^-&7{J4-BQpzc)5k`B}fd-)CFGTD@U1?C>4G| zsom4T_go=WnR< zXe?IU(*)HtDaXjt>G5#J5-gLC)k=NQ@Yu{;!vVvVHbR)16Auf-(@pK`ZiWqBAgzFx z8Rr$mvUCGC8&Ml3W;*2?!$mBT-zSoCGMJsn#0|}deA|+e>$j!!T+Z`>q-H& z4D=_mH0)j%MZ~E$w-F>>{&MWPK~XoRY(!b)mDA)1m%q~GdbbKloDz>$>xZjaGQhvQ zTeMwLSd<|Xx-zcWi2o_IcBYcx2|~Bj!1koowkIrI9;f45G1%$;2~+xk$x91X@`y8{ z@wdD={mwa&d*|SV;eHS{C_!BD%%np{3xLOG=g%aO*=Dr3QDnk7!pG9LooQ|YwP>f3 zmGrjM!q|LcwFO6wRIVyUXQ^0#l9o3nlc@5UL(;;JSWEArj?@3}W z5O)K~df7c{BR_@=6=_#J?3RZ}rrsP{I1%K}T-!qmtE-MR^^fVKEqBIFL}4rY zFFi)3g-hwz61`I8(C^fq^9;0;L@DTmKEAugDFH80-Cq(qdx}oZ6%J+|S?WgTU!AWr ztV&AW;1#J>GB9WT}gt zi@AyS7MELY6}((Io;Zx1bRrxFJh|Zmy=w1w6X=+vIdtR9w`^rA9=XKVaX(|ZaIzht zsK!q)BtQGGVYz{41li&CKy!9{N0MnHhdcQGBg&rmt!rn=w`7ZniyWdV!jRS8!v;AV z-%lLN_}*4VIYYJ;mXz%G_KDx8R7BItqVY@$iHvytaoPE2c!^5g0^F@?wSTrpybRgn zA0(w0``j+2{ju_V;YU|2%^;bS`i7I)T2n%EO7*yqW3lkpFFzMxL}lzWu13WMM3&Ks zR6iC_hwj&A6GzEb-!ZH|DK?lp{AL^6FKgPL;+lgUn6r}O;O$l!tm@AK&ucSURO~#P zW58?|0Llup>bXo%%n4ei5LDujLRj1~(~#R_<1-ZtVEHoVSv^B#zF9cMILvDqK>N0( zeRxk@Q)U^TVMEM3i%C%UYP4mTd=PtNk0~fcgE^&kVU2V?>mC{4Oq@~(+^s9;#tXtZ zrW=g6y88^}K-K~YAa}Y8`+Pt2;p=jD0%2?y42SGn%gplR;6D_7Y!`*x-ts1_ zz}WZNdRi@&>X6}bN>Vv{?`Ny-gt`Miz@mbc~I zfB=$@hU(-k)DI#hQ;W^CD4^3(bK=T-Z{a(MR~*$uQ@_)2lft9lXc`7e_V$O+gn&SC9OjA*J^~ zuoPEbnQmqGkdZ&kx-9z3QPme8axw#gZ zkFh8^UB$DH%)eIMnA=7&$`MgDIw$V+p6a9k@VTv70r97M6a|sq%Lp-Akbx^j(Kq>b zTrmf-1J*hvd35<7Syt>diDokP$@`_~F2TMPf-fb!sH24(+9OFqslj6c%N$##xwRne=(Qb}4#RbRDU1(d!} zX>Y!*WRsy*gZN#mO)3zT;U0{#hnE&!t?ZMuSKNJ7DxUD=b62gKGjqsr9^>er5RP!a zMbi#(c4lY0UG@gg?}R)UUo_U2<3zJ`%=&CrI#gn+ClMnqBUS?hU7(*wp`gc=B#Dil zvv&;r`*xiabYs5L?^n4vct&o*4&eeh7PN9>2Az4?92!fcUYu?SB0-MLvUrZkGB40~ zrfx))IeBZhX1wOKCQqS1;`^D0ff>9eZ#{VJ{&z0`NRWCA<9fYgfrAgX zAn{AbtFh)%3Oza4xLAyjq|v-IHqh*w`EpNqHVFi`H6{~P;Dw)$r$Wu^8_chJI1k`B<4x7NpUA^rRzfxBr*H#c}ChHPb^tbE4~Cr+K*UXkfE|+Ev#H?1<_ssgj>r8 zkyUFH0(-o`1YHRi5x8pd&6{$}x#gF#pQG*dH+I!rr{yl|a`dskLADIqZcyG%S`@-8Pe@o@&+e)aw- z;M?xZNJzh*q2^X`{fz>XROtdkdAaPFw6fHwcbT3?Tg6uqglz>vdgY#vD{tLpEu$26 zq|Z*{Gu(>qX+IH~SUMNh7b_Ykrja{u9^Fnu_JMAH|J+qg-z1I6hW+9SZ{3igoS2ZZ zrNlBHb9dP;-&N%@d9-F^tu?6#dw9)>d8gBpVuL;(Zc|E^cdWd#h}SWF227|wiWTdl;-53FzS zNFwwMwh4Cup)ESC!QdpFN@^R9amR@9s4|=&acKj+m z&ub-Cyn2QOa?bdiPsdZ01M}%L*wc%uw5{b;M&==H!(#= zR2Fj5OEnk?*HK|HzhN`a#v*o&xfBq{ejv!t$I(`3l$&_AzIh~Io-_w-%eYFMnx~~G z+lOReqq~O4v^vHR%MsIfwY&>d08`-zqHEOq8ZF;LgxG?!yBME>%pIo!>1@JG@U{g~BFriNi(1 zfJN1sDm;S({Qz{ok9Rb6Bq*8n>h_*hOIlObwLt(n`O9tO)@)DEaL=~W&8wAz11TcO z)vmRM|2m2c(1b6%m4)0o7Rbm1OW4Iga+K&d>2REdxgmoF_pS7_*~})D*gg@vE?h(F z!O1OZ9|R|r4D%+Vf#34kF-LU3mU6SWX6M;6rLEj_NRqZ@7k311TG}M7AN0+>Q(7}i zKB6A*@uM418Yw+%boW*C@DoMPP<;=1sqhh9W;&z)nRQ8(akILncEL~TUUmU>7kS!& zT4Mwez^|S}T!^BQiCd#uQ%U&CN}%or#M9qxEd@2_t6a;TQBZP&5C5C6@YU{8Qtm)X5qFQ1E5&q-rX_VhR+9AT)~6Oq`>^xlz5=rdaYBlHbg8n4-o zq7X`9yc5EC_a0Bf_NPxP9-`>1lCJlXk)1LUy-n`z5{A$lgN!ez-D8;JIA@ZXjS6r9 zKj17GKh9xwNB|n#z7k`M=%Rs27dq4CFqM&VUC>D7e%aADHF^Fu)`6BY;YEsdu8raW zy3X*>L3LT`MItar&Vj|brMZlG06a4C<5X>bKa&U%cp3#4%sd6wO|#73qX!iW?Ad7Y zO@Q5)MRPLPTxMR2X)+XjZhLR*0aKzel_s&v;A!5Xi&Rch4j;8)APjmPayRP$ZlFRc zY%uW4w5&ntZ(?}fCcIr2FNdI=(B1XM{)7~w`6o@$6&1#a6cEb%gx>Pq2$;K(Jw}eC zm2?AbYhd|gYnBr!k1=qqn#DqYnUa|hmA;Enk}%q;jN=qq|M3*CV^BUWlKqj@MwE1FucwP>X$)%@G6aj5&bB2tOoMx2OlzEr*i<_8()>#HIr~6mv2rn)%#s&*+xRX=Hs*BZ`EdVqX$hK4}9~9-6<0+|Yg! z14atz7qg)3s~0IJs-&^8F&*39t>h@-R!gYlTz3tt+&e+OkxH(sUSN}>RBXvLz@lel**Oye?$9Ug49(2Js$bd2m-+Bcm)pWU zlCtuV-8mc8M(;Hfy!dr-N=-j!(yJmn7{o-pTg+F zc6Y6R=CFR!VbJ1-;-eu5{wuq}hq7aV2GS;4${67W)1k+;WvhU`11C%8r{+OY2Dp}a zrddBnkd0o+S?TeYYWbO0yW#68M!DP&0-;Q{%XfWOUCC}E*71iFf97{dGc$+c9z;G; zci5!^n`5FIS-pgd^9Hn9*UUvl)R11SzgD(C@d~~;dy;35RUAg8?-PH zO>xgEPuP0^R@-!Nj%F6=1IjsRaqYFY=jUT;3G9Y`&)*uhx3-m{*3y|)Get$-D^b~& zF#cWsVD!v&gm*nhpMyD|x#6yT+~^9p!*ZT}*Da2oGX3LVmQ7=u)her5WgUo2olX{| zwhWtGqup1GT=M3->i={P_*L(#<=kjffIBq^B!}0vEGCg2m?5_G**9>mbC;oAFrRJF z%sqm_<-5n+@cgT~Qu}KZpD9v4F1e48&YUoWSo)u4%~>pHnGS`CSd5f_+3I$o#%2Mm zgsgKVd-`leK69eej{JptP}}LGqfp=kQT03K29{cJf3WbmYaTbcZ^LyI&XpFpm!zkFwM9MzCoytBbJBW*C zlu-u&q1qwpXKL)5s546YJJ-j^=)3Xa|ApoGzY#hh+Q_dbGRKlqtMZ`lny?><5QW>svps{{BNTM$NaT>mzkL*jfNz9$dD3 zH?H^k)-m9D+Uq*=K71VUw{J4@_v1#rDfqL0&tKeLx0#Ut{^tMZ*Z)tuVg7c9Q(*G% z;GZUg|BIAH@2}Q}Qc>N9PgYgOCje8sgj#ytqn^=UO1j9Z(}(}kI5u_=VDx+T%Ec)} z?c1_k*bBYpG$WfXkL0z0k@3<^=xytTaBCP8qVgD5n55NWNDZ@~=UlzV%5qi_#pYxR z6;|$Rx%j;T4<`UUi-ATj>a5y+)UH>YLqdj%>SuXG+4R_x#t6RM%19o=u@_^C@vTss z6D>&72*bBnfhgg&i299aOS+4aXB=E}Jv*zU`AD8*39!w&y$ z=A4}1L3nIbd+^>c%|%N{ZbN=JzADP1|0grD*)A6qDmF_nXdEfX4S+K8F24FgXh|?g9WyqO5S9c&_viufWKmU z(&tVJNjX_&)~6p8r2M+1d{p{D0y%d{wE97+X&@iZ~d%FM7PpeqXW7E7W>`G@=XCMs_dHyWNNrIG1d4YB7Sk*Lsk1%_huL=5g;%n~h zU?+PPxXxD)J!wqCeKu**oy9`(hRRxYh zVTOhhBQYch`Wm}0eNW#eNHobelSU=`NfH7KXU?oV&9OMmJfk-crw07emJclC^0Ra@ z>r!8qB|f4=a~RGtXA+b$sK#gHT7D7~oe3JU-~TexGHvFPXi77(psV5F{D;;)zoXtY zqomFM#i?2TXY-HVW*=tW<`j~b+^mRq{)k6uMQ!}8IwYte$)la+)s(}YXCtMt4Ji{< zt41Fo;4)a;7HvrHTH3~APT>mGPz2~|C@?g9W2?q*#=$ILC*JQE%w)FiW)`Hh2M2dAJ+CO!>>u3Budf-f6^H3e_Wya3pMOyTc>mnp!w z3XOE(#9<`^Ji(91^~^@9w*rUmx6tMms&?~L_OSx+erI-`mg ziZ5Z=$`0STDdoB%ooN~0zM*D)=Y7Bw;O(PJ>R}5wMd%qzr`7$a8hN(W0A6UN>>O0S zSjU{6V#O6}KaVzy`f1z3$`|K2?vQfnuC)gw{7x*9OCzPVQ8VHsUTrKbGfKg4B-(qS zd05MrF^M$yijgFoI>@0DZ2&Bf-Oi|o2jV>yhv2B(iy;L=aLTG_3mO<{GR0Khn(&)x znDiDQ((KafgziXWd#FDC&ShIH<0EgKWni%q7(0l6p+of$cJjjs$I-(lb*D^w)zI3} zEBFOpe}4HR4sRIDn58%5vNlbS2SnMK$m&6!nw6PIaYS$J&fJMEjwoe2VE@o4LWr{| zw7=jOeA`f`j{ak+Fjq>iG{-*cVX{N7Tm#ajlERf}s}iErWM9VR#Y?}jR1L2t$%M5s zEY%wM%$EYvn%)pQ?EcDe6FHk9S(UTw!E>~9A}`uK*k@+a`)SXh*oS4D4F+Wj6|CA) zVlO0VN)qb`G#@0VcsSrYd^9O|LFHBZ>+9fSYhUFhZrXxpAQf*B({IL15F}?vwEamS?Sr7+M^@a<6-{b31dh&=2ZLokcncR?y zaLj7yJH>3x^_;81)7#Ou&M=sBB7Q^qN!pW&DTM`<|yyM`kBDH+?sjve37geU(wk3fORm2~`$|(9Anwu(=R4{Y z6xX>$$jSWJ@LOqvDAZh~eg9=zNbQb0Uh7L+R@2gfxRp9?SZcR`J2NQOslvlg zuM1b%q+Xl{tYZ>1wH0DOf%h>x>D0A>VV>W#UkdcLF(`s?^xNtOCh=FTz#N+FF>U`G z7Fa7+svNGmnB`4__c=nDr!?QNt2RAne-*CCUk&0V)6JM%^&;F$ju;`@6i+D4g4j8~ zFkZ72p6LjGcbYX>W6*xmy{mnA^Yl5d+?C*F#xuz%0(uxZPXr?y;V#j?A95BRd^`O)13muWN;W-|5 zb&50>In3}-?1xkV5U6OCQl|$B&3ACo2m&4E)yD>fv91oZmf6Ec8F4y@RvEA*_|)IA zb+|#jw8VzF-3an5wQ6cZR-&gcq{k_h6W0<6_!`BA?4Je}{m1mfGKsuf#w)Ju&j0wU zu#Diw2s8(wZT7pArxZA8~Q`QTvUi(t3v50}0(>T>o z=g7dPUL>V)b-yMDKgtHr^t5&DbECeOF#3l=m22-F931p$F-gngF?#bbskOUQf@A9w z0E+PvU}3A}_mM+sa#gR^FcXM+p8r#>)!0XJL{MpwIZ>pHqdE6%NmH!X8WSX6B$(LL z@b9oJnNR4N2SQ4LmdB^P2c9W2JY=0+btYY!r}%9*MIAd~OAJZ785Gs5=#BrOB z(_Vw;8yIZs0mn}HPLKduyis~m#C2cSy!FqtYRQRR;>)62;~&2xF~^(7?N{^se`W~r(O zEi7wklSaEKg)bRs(<>Tu4nf<1Ywi!NeKi>s3hDb=WV3JC8dmsjXf}E`VVepd3~UJK zJ$JSlKsB=I2y2Eehmu>;QQM_n_=SPk+$cYo)Kg{y`6@Glu6(*c~=6517Y{0FTi*$7R? zG;`+jvI5a0$3Xwcu|3xh`I^KNN)XxA0)b@=H@-z%Vjej)tDF}q{(>fsx~+fS4e{lC z(&vaB^|{^c{Jq#VayO?@p8+W(D!l|#VxQohgRS}eA^?jjaSFTQ0=kzCo_G}8uRTtl zqcTAYdB^G`<{iKDwaGj(AYfvBckCYujKQ?hA12M5Wsg0iQa{I^c;hJ&)CMw{rVh6B zhM;Vb^SBVt4xZdSY@t~X@|X7K)i(a>J5R&MNuh1-4nxR#j~liT5VnXX1AVcC%*wSk zsJDwOH(2U-*qE52|@!v9#Hv+w>Yq{|bf&r^SEOLC~z#Rmd@ z`8L3s`idENIQ1}g4u2lGfXSzm;yjCZ=|x}%O(P1C6t*E0p-q;)8X4gaSU_5{crM99 zDvn0g{3E_uYCrB>`K zo5|F$ej2KOc>79z7l*+-F2v+Evc*u~?eG~tOO|j5cRK4RS*Tq6^qy|r$y>RpT`fkV zaqJ*F{ki?>rmF;#Pu}HR_|)9Xz1-q6ojnfwUwWhuH-$!dlJ_(l%S484lSQWUEvfg9 z`{=yFHA#ccB#w+vo_7Aku7L!ly6TVEpuGHrOta6DI7{=c9P{ZB$G7~>J2@(x?_vhR1J7hb^EZyg>_ zyvbm!jp)(y=(U;qqYW=w(9e!h6u$E70~kmhmhqZGt?H9djU>LR%_tGZ2$*nByxol z@=xe#FQD6wn=Sny(Xda$Q=30W2l5X}=``@Ho5FlUTT}!zUux{ff|LP9Y3Y_Kn}g>z zm}D;R)xXkcx5Ap7@I7iKR^Pe*LrH0oQ<6tDq{>AuL;4<}Kl%Dnb4~NMo0zE*Xxg*c zFOIO8Pu_^MzNd}bZK{uX!26Cr>E{hj`gDfy?t~aYfm7Y*1gYgn6`dFfN2mSen(uLQx{8?c2lX!>6Bk1WiMW{pI-9MC9 zZ{tdJU*vs=_agqoKVDH}6l&So=+aIxN?OiI1L8W5a21vij*nuw>AvqIDc9%mG@2UQ zw2edorarPb9$I4^@??@>h2H^sHGCy%m9MfsyB;cK?oA=Z&LY)|{E|TC+813}ZX>J&D572gsRiX8+5P<8p z(2aX1GI@HP+n881suE3A1IOxDFi&9=7jZKV3**F+YkjIA?Yeu0n zQAph3Dfv$3*FqM_8_&)IQ^)v%xWO*lVl^jNRh;x-^^Ona{f|*1^Mi&q$Wlx#Pv3Ae zTi>*dA_{v$^Lwp0#C7>jZF`qyBc6>s+&yR<_F`6-0y@F8#!H{iFE5SB-EFo2{mV$} z?B^>5OBUv(b{l+ZVo#mUn?C-Uwc+vV+gSj7&-)$9z4gPrdflE_u0rd@+$fzfz$a6k~q)%pn6-f&RGQdNFpifr!~jvL>`N9_X!&mdq#npbKhnx=X1JojZJop!PQaN*Luj+VGUfhWWHiaOW0Qawjj!tFmH-4#(1@uKADY%;*hl+Jdp**s+Y%aTV+318dB3Xk- zWuLGaOWef}4jv?tMrH~E4eZEs5b_YLvgE=I{(uE-=YY3s(6XUKYxXXpiQKhs@lN8i zFI^K1>Sfsir0KnaVB-t~8W7t_iDogWIy5%dc0d1ntAIIvK$XiBg@f_H~M< zPA7C5xdmkF{zG{f?zMP!Sz^^#z5a)y(UclLz4j3Ng*qZWPI*BduvpkNT}L~Vb1#cw z_a}S2!911M(d^Oy?1%If8!yJ$7gFo|HD(TeMAg}fp!fEVNNSc5A7@}RmSS#}WOu;< z^NprT;ykdy1Sujm0tlP4gpvC$WMX!k-GArj7sRaHV59hOS&@E9rlba=`J4BnYNkW! z@<=1-50U#rjD)PTB9yz^><5(274YZh$K&5h{`nXl*LHh;dH%CU&ST9`G*+C^inbG1 z{rWMegveLyEFP>~$tShCpqQd-E@J-vPkQz&c^3}<3N4qSh_CQY?7l1Jw_#Vc`Fyep z?mi|wG}nRjkC=Af9AJmdHoLdXJ7eto3a=$_$)uRp>RHf-N!+-5q)J(A`ihi(Is|%> zI-GY;2;}`WC^^L%jgIAb-p1JFjI51*XI9ZFu1*b&JTRLI{-He%ud#$lbEFOAn-y&) zqv^xPmScTVL=bB1&tkoYYLJ1>?QKrQBh_mIhejuHY3Z%58@)O7v6*V4BJudwhS}$sg*) z|BD@0T^(T1L#JwX8X>>^dY(A}{*ZchR^;pxxPbYt3xdBA~-yk>s zcXW~edthMWYZLjmWN2O4f4vzSU&gvqd$i`&-Vy%v`ty>4 z<0_V*%KBrV-)2u&XkE{eo5chFl|^^k=K#OO;4M-UlVP`LjI{zUzsoeu(vaHLq9=-G z2q0)^10snL#Y^o2iCojw;CI7hOVoZL8XX(mP4u!$;`2%u_;ZA;f6b-oWk#za z;tQXkneA)pkd*#*?$`}n>nDY37VV}?TG!)^3bQeO%#@L|be7#n>jD;c#R_w(m&s}> zA@TM_A$@KnY`&3132IElaT@l*$)6-Ck~`9t$Htab6I8YnlHPtaw?+($;tSbQpBfd2 z8uJ;sOe__EGg71i*|`X0zi#QY-?~ybEy>RICH=_;mFj#d3gJEJC|yaJVI`GiJnq}~ z5oo{d8Tr*S9-^{w_&4~dNbettX4Ev^ z)bZ<35;NG!)nL7Vwb(qnk7$_(r&zXxj^ofaOlm7M7di}UFs@cmmC)I-Bgnd{5R4su z$@-N}9cR>Rmx8W7h#Rbm)i-oQXUYkvNMb72VvS|kNpsNF74YN&WL5GvyJspzWeT7% zRT}$Ue8soa?_AGMy!#Z&8yVb|cE2UFZ}l1Y{z93ZO$a*o>) zQY{ljy#-b}%#B`yy-&m7OxrC)_6_XJbpZ~e9oQwLrOPe4>C~lc)jOI!nI^p5`?!|* z>sC67du*l?qY?fKlPnmRIDq5Y-&72Hw(nA_EXKh~=l2k0gHp?9T7TQ8G4pM90XSCP z$v+fS?VV;4Ir*%BS%{<3%-ROQL2tNN;yArfKI*C3FYd8=@gYv5g z9dh5$@k2hns7y6-{%LCS zwO!FZ(AQ0O!$BfJElV$Mn?8~*xW>3*cEZRZ#WxyXe*O>Q-YO{WFZ{zJ!QI_qad(H{ zwzzA6UEJLxxXZ%g?hcE4aCi3vcY<3;e&ye3JH6<%Gredp&+VBr-}621=Y5}t$*X|o z4)Ho|hUr3|c|HE^=S5=YZ4N?#OS>v{O2XQ8D_5k7vqzm=$B_il7f)rjAe8`xQMrkl z@8Mbr)0j+>97zl=>Pceuk@t*i#ZhUSzh@g;e*SKr!_Y!{WWFb_xfwn*4mrh@FxW9IH_^<{(<|o5>Au^j=9g zo8)W`q}vbyw;9>Qsbmwq+MlGGS2PAz+a!#WYKY#T$%r?#uPfw>uH`sPReRfCv(at@lMSYb{)Y9 z)A>*VYm=NnW(1Dt%q75{I#&2qUBt)(GcCQ|flBi;Xlv?U>&3YQhzYHUn3%gS%LrK@ zy(2rCEDiyQKLOzN5mjgF07v7GD}v&!{Hk+wKCXsZtn{d zRsVl*k8C%_t^wP*J3^Po+y9TG;LrJ3KX1l=5EuOqDfs_b6cFA%H8=|B2AeB!H< zk&SP&{RE5sYvS24{=kr00`v8>ifAkG)Sd@@f>-94)_x*NYn}iyTMA7D zy$v4{&`n9O(C~jJ{a!x|LVT9xUEKvoZ2kxL#nt@lPwUBpM3-CQa7K2YU{CYwqndeB z8)ox^is6_UlJLMN8UDLC%Kss5v@AaqNU@n5*RN`ne{Fa={W941Ch~l=IMVhX96?~( zpyM9-Hs-&GK}%Iv4O^MK<%?EbAKa$3`BLR7w3Je1&40SNEVf5niC-OmESa^%{r(T` zUi3P5bTI9yW!*)rddvK$qasMw@o>GiZXs{Er)&dC_}3+-Sbo8Ux#ZXVr_h)LczXssx3|G>^i`Q++~q(ZkVn#vc;?4^GyWoVKY< zoM#5W<6XZt-yNx^rb>eFD`I&6=)5UxuFNk<)l4DNDwWfkOocK00IwjeX|AJ&u_+8# zIvjwpPR64ZYVY_N!Cx*(hHygt*K?kJ{MhZ_Lc5Fr%Np4v@9w+Pi2+&Cr==s<^smNW z%D;>|lA*7^&wejVw=H>no&T{UR{!0v^=VJTy7gLveB<&d{-@VwJ@U?pmaE^tzob0dsQ5Qt+y7!M1wpFpP_FNu* z@o3V!=(qL*Z%rfJS}|bVNiem-=~T<>u(DhMO6G-HUdoEZOSF6=I!a&>2TxD*qbbg97JCFT%1h5LVCHqJ+i&S$Q*R zx^(G}SL#kWF~Z$KVYyjbifdtDGXA_d%~~4<&jEYO$KV``?*6)jh0vRt3+@B;D~Jsf zQRc=V7$rB#!Nx=9&_zf2bg6(Dra0vs?Ciy;!fQU|m_`z86MKa5C;Y}VP445AWg^(A z5H(z)8)9FiZgd&1t=PIesY6mA1Vls~z@WXCA#=InIKfZJG^bGTr$VttBnOI;4tE;_zPDgm9C|gkW-~#E>W$4t+3w>QC;0 zy$7!Mes%PXhD16kp9+?&Mw7RC-~zJEEI$Z4Xhm>t(`esY4Hc-nEthcMq%wT)B@2ng zybN3*|DX~JJRRmkx47Kx4@mgKJZP=Ri;t!BIjynj(J4kzsqc5gy8$Fbf;5}28g5QN z1PG=5w6>F{N*m8knsBNRPX9d=5RS)xp3L)yK)5^RMKqERv~PmbLn!K<(kLVgwDAH! zF%yQzm+KgkoD%@d>H&niW?og};>9{y7MO5hnY~tZ=|q%zCYF8+FiG}VLopG0a`Ms$AVc@+dX2D9$7nVZL z+OPqfeOTv_!c=bfd|cMB#fEtgtUAN zJJ7x1Zu@2Hm>h>m)UO_Fot({CLb4J{QLIHh-jk@!!rE?d4H#`Zg z>ef-3X*J8$^gIl80I44g3fhPxtePu36{&|s`g{>^Wum{1?owfKKF-7=5R7;PtFb$; zbA6ecKU2Mu>w@Ve&I~G%gj#+@s~@R9FSaGc8=Y%7e5z?KDbu#xV@DvP`5wH`a-`fQ zT8ahoNKtvTg;S)jSwuGVyLx`efSo()*nF~L;rX4UcMcs>0j7Z`WQHQU6tK9lorhS} zJ%#{j?p8#Wk<+y6Sp188-&E;!G6HX1#jT)&KaCIO%S-Zft^F5O&spEmM=afyHiU=s ztituohW!ht2>OkBDduEfElith1BIL)baTRklzb+C;WZYRcBVaVO${bWi=rP5MP~G~;=!pYQa57sqP@xQ!lx&y~tE5|<7% zm!oNx+ehr-lw(22T>3;}l3^TDJMZ?5jZwvUFwhWv1{(5fQ?}Mf)NVI{r**)R;(Jn- zs^LMw-qLsylT3^#$>4+;7t}K7Sk7YOBpbTlmv$6X zn#jX%x@`GLE)oFTZ%DI7ANi1Bj8Mm`h_qB?kY$L(o6N*NtPu9GLmqAAhX@B*jNFp$ghKGeO%pU~)+rl;oQRVAwW$HNH zZv-gok|-^T;1$sESC6&ou1yE`#~5kZ)Er0g;Ej`XD9#^jrC^0r2OYTSpg6OX{N{)h zPSx7GwWUZxO8wOFVi~g1bD^7ZPL+33D`%5(W@BuiJMuctZ0GtlzPm-q&@ANx$Yhf| zM$sn{5aD_2kiC^eQAjp4c)?!rRrF*C&Wy{wN0 zA%S#8JFAC2frFxd7TCl#FFWfl|9zcnnY#NDUdN_QdITj3q7c;Ky-bK7Y~l<^BNP~` zTkOu6=y}U{bKr*01~nc|JDpxE;@MhRbDrWrjEIHPt|^KO4|TKL2XLVb3;sYWyuMSm z%&|2q9v}Wy!v{c0S6c%&UvWd9*|Mm(Xob?&PSyyCA!k4f0BRWrcX}U2Zd$Fp|NMki zwnCi`>Mgb0(t?p7i-j*4Dhln1_uH_g+jfC4;&Jj&^NzCY0jNv3zLC;x-<89%2+G({ zX>=@5~pVdxPI@6V8w0^$5<9_y=KK=B&M}Q*yQ$CZRrF&;td1L>HVjNAD|W z?f9+e>%Ehm^UXLQc~~}!mQeytAOe+^S5I%#BChHDtH_ngG8?9~bKL3{j$qN9kLM6c z(CVZqu;kz^87qY13N8=fh-?j5cv!Q10C5{I4uyPMNZEPn*k`9DyxifOS_`hH_{`IB z=;X8+Rg+A&c__bF(Ft@1J8q4GeY!hbi{LIdGP) z?e*H8T0;A`Jzec$T~LsBdV)_TQ5S;1p$|*WWhV!bA8;klqBKsK1aR0WV&sAE)P1t9 zR*GqC)%RX>6b8s_+UqYl65#o%vu9tJV?-Vd6EPm_uPYdRZ%|V_W(YfIy*FEaVVjey zNnRVW#G{Ee3L42938U*Nvaf7!IHK#ucu;x9MX*HaV?&{93ByHt#F4`_$qggle5cxO zLN5dVS101e!_tp2L%O&bJQmq~aTm!2`DM}GA00)uHcqOR2*ldIj`jk;N>L3XaHfaI zX=Y*ENbduvhPsiiDueA^R@_*w0%LJJIXpzhn$w;&SNUY%sGvjH&)InhBhh_PlY^OK zlc+}oX7QRICn;y>e&K|;8&I&h=HvJ;{9PY+t(y$WSYzij#?ZeSjQ!jxCpaDav&(_B40Gu1}l&xeWSuli35jy?EWlp zW6|f}yW(4cbyq_&_#w)2C?(Zs`-@+A($rH*T!y06q+5p)Au1n>_C1`hn{i=7rFJDM z$VOKhb{m2}t?ta2(lbEIrdtsO+C~L~V$@f6G5XVYuWK!aL`P#A#aQ^XJ{8vB+Jg%h zXu^lLXK6$M4&JyfAN_Q5Qn@^2H$ORq^u@C%gvA;IVF?yP>vdxOJ{03??=L?2kg}6V z`cZt6`{kt4en2U_Okj@l@HCnCaFRb`R@8p1t|lhC0s%ROP=`oPwi()zBjDeWe5pm{ z)!ex{TY4MlBDWz!ky3-QFK1=U^q5t;2vR!Ch7y)^F#oi=gjEKqFLo;tW(k56bH4Az zAQH|`p)&1UE3b3h3I=U?xztkDl999kZ2}QB}0jnE;)@qf-5k2oKlkq##g`wjW<5IIw@oe43N2E^Ot8`!cz{q zT%fEE)aMyCp|2-hmdz4p%Duk&Y&iBI>o$?(pdEZ^q70`=(588i#(jSh02t7;v?eN5 zwobB(XByAo&N3T9vM;rItITegK?kb=ru`kst(adA>14vs8D{7;eTL6Jp_2fZiIhz@ zl}uava1@X1kvy`)qYUWePjwN5)<%DxLk>B(+10i`x@G9qKAMS>$dvn7X0Hl&DA>H_ar~t(tG1ZA_2J zuDrNy99hovgvhdy)SLua)%ApwTGO*g)Va-|`kXH3z2vyn*iz6oJc>%V|82uiU06~ii9y8p;+z1r=6z=XSDzOo(J&QSZSlDvtDyvUs zu;nuLFbbuoMnl4UR!l##(D-fMM=5F1a~%y177l~xsw9F}V%a4!BbH6Mh)E4@gAV|# zUBb{zz=GcrNBD*wPZDfs??M@==SrE;`_sU{R9JPy2#2?ymnO8Mht>+m>AiyiqQptF zCfoAc0lvG`(n+h4>@E+(oeAaGNg@N=7B1dLBhEut)T^-OTOPrV+g={;?U4syPux09 zJDed+dX>LA)ndTjm%`y}(VlU4CcYcHQtIJ#w!P$e1E~F2PoYJ+*eq;>9TZ%20Bv8FuT0M-l{bs~7YC^(IjG zzqkp!<-?ZJn*Zk}SPp9_G+eU4V?#Ca!C5q%`{s*Dn^&oC`V#=^wp;rChkn-5?{EC_ zVW;TIonR_#m@KCRo64YyBuTip?o&KyvOGzuIvYR7YI#TQry$KwMoE1+6Kn4UPm$me z?wY3v>lZq1?ZE>#lo5?^Dd3v2GqL>Gs^6r^MtR!pru-uoy>3)N0p$RpFF*#f4#~09 z62r5}csB!FkF%wk-_WX_J{l{2Jk}~X!5y6%UJzCW$<>Y|vb)=ijnN&~tzck>U46OtvWUQM-w8sPd;|o>8zEU!DP02LLreeM z6w^5kmgoVa6j;v7gu%D!%BdP3_vNk2UliEJz z|M1YMG^D3?W^6jl^vr=Lx)8(}$1k&B;aMSvpJ=f6D(r5SY0%HA3=e+@ER-vve1j~8 zrH=z72hPy&LdjyRmK5zTu9y1YyRCSpWY5J<6Tk6Dme zcv&Z$_y1aSbd0l^*nzmB2n0GvX+#1=4a)tVKJBpTlTKul*Jp63vWlvEsidHf9$SGQuj1k_4pgNm_Orp!x z=DR3KnM<&&$+nvNJHl8D(i~)m5aDor&TbTjEGVvtwRS0fM%|$p*6HQ_jpOB)@nihT zZeNn@t0})jiL`@=gkz_JX{h`$n~0VP_gkAv1s~!6w`tM;7Lxt{M}_}?qr@bv_xRa` z{2$y}{jhzt<^NftpkMKoVRk;V{OvQBu9sIS8*E4~q55uj^Ph;&-o0MX|7oH7u`~V0 z%%SO@?sw!bq|2emo%OgxxXb50mgMUSHdp`kpXKu{mihJHn`sN#G5kV38@Y@Zx^|Zp z+9f{`vc)$K$#kF8j=~YPMNN7);t6WK@@62)Hrq;f@Pq0i)&6`I$ccjP#D;X4qtg~6 zr|F^{JPnmOoW`j|IJM?8zqZ=T%L!yeC`=h^J`!Rnpwh?)wXjQ95{-0I<pJ8;MbW`Cb$6k0bsHJYa|a{>RbuZ})!WxNXg;)l0JW z^-IK0|8>pn)46SyOZ^vF4~-%7?SEIZ);-!Ant}NTt8-F%Uo!oO2EV=rK7dXo$`1E` z%K07r+5dvsdleY5_~&QBZxhN|#(%jtk+Rm!r7i0^JIoh(zcu`Bug-1d=SnrK<)wDo zpKDw{1Y)Mu$Nb`K6T`G3CRD44Q?fw%$&*zE8>3=?!~J-xl1(n{nMtqUmB4NvFulyu zD}T*E2yN%DYD}m6ez-ZuMC5tsViwY?cs%>=MfmM}?NNbrcm8_$ulC3JYH=ObT7(JC zXa_#SI5}Z6{rC)S2ncl*hkt^YXBZ_I=QEsi8tnV0gF3l_RAjXN&LYidBU&=qg*@Nb zKXSpu_mL-0j~X{pg+XktomcuXcb(FFi5>A1{N~{6cE&zZ$RUe~aJ5&i;eL*?x*|)O|Au+NsnkRJ+_em-Cum zZC}bq^m!PUa4^IFYru2pA!gdPJy4PoCN4#+++ZrE?|xuE4H3gYn6Hwi_L+zj8w21G zi|{$cl{S`@ElwEkX*VqjN``|>G(k!Rc6m9JbZbvN9c#ehfh?0DGT)R|K00|*Uehkx zy+#w*ln*~NSB#S(Mv?bJX-!o708aaN%AX(~nqPvL(XgH&$hwTQWZXd~s+&7%l4dX{xX`MbS$-O1zuOE{72D zgABh40)leR950QHqvI@eptnt+(no)>YTVR`eJ4wgAy{*%3Rc(QpLJXm(9x;CyV<=F z${ac4-MlUr$;EHKXPPZ)ohICW;{&u5oN7SSj*2;6X4%NtQZ-NBJr(6m`>xxvdzgt6 z@ev z+_p+q-ug9^>K{`l6q8#K0Q16cgs|Gf;B`C_V5&{(&f~L2{iZSU(5Aty;Q)%VQ{iMY z+|^WhVl&l3?uE6q)`HJeRx~d02doUzvmb*b=GP84tS$%m?0B2e#Oh3Vh8F2<;^h;C zhZ789@P4)P^U+Kj?oQ%%D1vk_mQeBEYNzS7S61#ue(lLlj5453m|G_c(>iL0V^w9l z2dbHHABk4P4OMy{>y}TnIr|(Nr&<2(U9I)Zc5m37`hJdK`4Z$RXw{Pp1s}|;y^>uo zrsW#B%Z+C?jMQAjFBv5cCcBs5+)r-X1wAOWa6TkESL_* zWFswIU2hzW9ms?YD7rZ(VrxIPvehpjQ|xn&1X|W^8y_dOmcdgwxdvmTuB09C>2W6E z<=~Ajk1$?g{_-`!<>(i++4Zzn_{AuY=v+@sNT}kgUj?0^tU?X1y4+F= z9(?8L-QsEDEcuktkQym?y!X(?{>fbhA($zxOwR1^$Cm;|O^i^cMWG zPIa4K_jeGp?w)!ctK?Dqks-EM;mV+-HC1fK

qI`*rXPWjZTpbGj4ji^&YyJDQO# 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

diff --git a/sql-statements/sql-statement-import-into.md b/sql-statements/sql-statement-import-into.md index 86f90aa03f47a..309d6ae00473e 100644 --- a/sql-statements/sql-statement-import-into.md +++ b/sql-statements/sql-statement-import-into.md @@ -10,6 +10,10 @@ The `IMPORT INTO` statement lets you import data to TiDB via the [Physical Impor - `IMPORT INTO ... FROM FILE`: imports data files in formats such as `CSV`, `SQL`, and `PARQUET` into an empty table in TiDB. - `IMPORT INTO ... FROM SELECT`: imports the query result of a `SELECT` statement into an empty table in TiDB. You can also use it to import historical data queried with [`AS OF TIMESTAMP`](/as-of-timestamp.md). +> **Warning:** +> +> Currently, `IMPORT INTO ... FROM SELECT` is experimental. It is not recommended that you use it in production environments. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub. + ## Restrictions - `IMPORT INTO` only supports importing data into existing empty tables in the database. From 072b53c6dcd64aab5c46ca8df36463a03e812429 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Tue, 26 Mar 2024 09:30:46 +0800 Subject: [PATCH 80/82] Conflict data resolution enhancement during data import (#16720) --- .../tidb-lightning-configuration.md | 18 ++++++---- .../tidb-lightning-error-resolution.md | 6 ++-- ...idb-lightning-logical-import-mode-usage.md | 4 +-- ...db-lightning-physical-import-mode-usage.md | 34 +++++++++++-------- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/tidb-lightning/tidb-lightning-configuration.md b/tidb-lightning/tidb-lightning-configuration.md index dd060af75695a..e173df1cc0f0e 100644 --- a/tidb-lightning/tidb-lightning-configuration.md +++ b/tidb-lightning/tidb-lightning-configuration.md @@ -125,16 +125,19 @@ driver = "file" # keep-after-success = false [conflict] -# Starting from v7.3.0, a new version of strategy is introduced to handle conflicting data. The default value is "". -# - "": TiDB Lightning does not detect or handle conflicting data. If the source file contains conflicting primary or unique key records, the subsequent step reports an error. +# Starting from v7.3.0, a new version of strategy is introduced to handle conflicting data. The default value is "". Starting from v8.0.0, TiDB Lightning optimizes the conflict strategy for both physical and logical import modes (experimental). +# - "": in the physical import mode, TiDB Lightning does not detect or handle conflicting data. If the source file contains conflicting primary or unique key records, the subsequent step reports an error. In the logical import mode, TiDB Lightning converts the "" strategy to the "error" strategy for processing. # - "error": when detecting conflicting primary or unique key records in the imported data, TiDB Lightning terminates the import and reports an error. -# - "replace": when encountering conflicting primary or unique key records, TiDB Lightning retains the new data and overwrites the old data. -# - "ignore": when encountering conflicting primary or unique key records, TiDB Lightning retains the old data and ignores the new data. -# The new version strategy cannot be used together with tikv-importer.duplicate-resolution (the old version of conflict detection). +# - "replace": when encountering conflicting primary or unique key records, TiDB Lightning retains the latest data and overwrites the old data. +# The conflicting data are recorded in the `lightning_task_info.conflict_error_v2` table (recording conflicting data detected by post-import conflict detection in the physical import mode) and the `conflict_records` table (recording conflicting data detected by preprocess conflict detection in both logical and physical import modes) of the target TiDB cluster. +# You can manually insert the correct records into the target table based on your application requirements. Note that the target TiKV must be v5.2.0 or later versions. +# - "ignore": when encountering conflicting primary or unique key records, TiDB Lightning retains the old data and ignores the new data. This option can only be used in the logical import mode. strategy = "" -# Controls the upper limit of the conflicting data that can be handled when strategy is "replace" or "ignore". You can set it only when strategy is "replace" or "ignore". The default value is 9223372036854775807, which means that almost all errors are tolerant. +# Controls whether to enable preprocess conflict detection, which checks conflicts in data before importing it to TiDB. In scenarios where the ratio of conflict records is greater than or equal to 1%, it is recommended to enable preprocess conflict detection for better performance in conflict detection. In other scenarios, it is recommended to disable it. The default value is false, indicating that TiDB Lightning only checks conflicts after the import. If you set it to true, TiDB Lightning checks conflicts both before and after the import. This parameter is experimental, and it can be used only in the physical import mode. +# precheck-conflict-before-import = false +# Controls the maximum number of conflict errors that can be handled when the strategy is "replace" or "ignore". You can set it only when the strategy is "replace" or "ignore". The default value is 9223372036854775807, which means that almost all errors are tolerant. # threshold = 9223372036854775807 -# Controls the maximum number of records in the conflict_records table. The default value is 100. If the strategy is "ignore", the conflict records that are ignored are recorded; if the strategy is "replace", the conflict records that are overwritten are recorded. However, the "replace" strategy cannot record the conflict records in the logical import mode. +# Controls the maximum number of records in the `conflict_records` table. The default value is 100. In the physical import mode, if the strategy is "replace", the conflict records that are overwritten are recorded. In the logical import mode, if the strategy is "ignore", the conflict records that are ignored are recorded; if the strategy is "replace", the conflict records are not recorded. # max-record-rows = 100 [tikv-importer] @@ -150,6 +153,7 @@ strategy = "" # Note that this parameter is only used in scenarios where the target table is empty. # parallel-import = false +# Starting from v8.0.0, the `duplicate-resolution` parameter is deprecated. For more information, see . # Whether to detect and resolve duplicate records (unique key conflict) in the physical import mode. # The following resolution algorithms are supported: # - none: does not detect duplicate records, which has the best performance of the two algorithms. diff --git a/tidb-lightning/tidb-lightning-error-resolution.md b/tidb-lightning/tidb-lightning-error-resolution.md index 0c27bd53f6dc9..56126e88328a8 100644 --- a/tidb-lightning/tidb-lightning-error-resolution.md +++ b/tidb-lightning/tidb-lightning-error-resolution.md @@ -11,7 +11,7 @@ This document introduces TiDB Lightning error types, how to query the errors, an - `lightning.max-error`: the tolerance threshold of type error - `conflict.strategy`, `conflict.threshold`, and `conflict.max-record-rows`: configurations related to conflicting data -- `tikv-importer.duplicate-resolution`: the conflict handling configuration that can only be used in the physical import mode +- `tikv-importer.duplicate-resolution` (deprecated in v8.0.0): the conflict handling configuration that can only be used in the physical import mode - `lightning.task-info-schema-name`: the database where conflicting data is stored when TiDB Lightning detects conflicts For more information, see [TiDB Lightning (Task)](/tidb-lightning/tidb-lightning-configuration.md#tidb-lightning-task). @@ -119,9 +119,9 @@ CREATE TABLE conflict_records ( `type_error_v1` records all [type errors](#type-error) managed by `lightning.max-error`. Each error corresponds to one row. -`conflict_error_v1` records all unique and primary key conflicts managed by `tikv-importer.duplicate-resolution` in the physical import mode. Each pair of conflicts corresponds to two rows. +`conflict_error_v2` records conflicts managed by the `conflict` configuration group in the physical import mode. Each pair of conflicts corresponds to two rows. -`conflict_records` records all unique and primary key conflicts managed by the `conflict` configuration group in logical import mode and physical import mode. Each error corresponds to one row. +`conflict_records` records conflicts managed by the `conflict` configuration group in both the logical import mode and physical import mode. Each error corresponds to one row. | Column | Syntax | Type | Conflict | Description | | ------------ | ------ | ---- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | diff --git a/tidb-lightning/tidb-lightning-logical-import-mode-usage.md b/tidb-lightning/tidb-lightning-logical-import-mode-usage.md index ee2ac84758707..d7f53d5abb6d2 100644 --- a/tidb-lightning/tidb-lightning-logical-import-mode-usage.md +++ b/tidb-lightning/tidb-lightning-logical-import-mode-usage.md @@ -53,8 +53,8 @@ Conflicting data refers to two or more records with the same data in the PK or U | :-- | :-- | :-- | | `"replace"` | Replacing existing data with new data. | `REPLACE INTO ...` | | `"ignore"` | Keeping existing data and ignoring new data. | `INSERT IGNORE INTO ...` | -| `"error"` | Pausing the import and reporting an error. | `INSERT INTO ...` | -| `""` | TiDB Lightning does not detect or handle conflicting data. If data with primary and unique key conflicts exists, the subsequent step reports an error. | None | +| `"error"` | Terminating the import when conflicting data is detected. | `INSERT INTO ...` | +| `""` | Converted to `"error"`, which means terminating the import when conflicting data is detected. | None | When the strategy is `"error"`, errors caused by conflicting data directly terminates the import task. When the strategy is `"replace"` or `"ignore"`, you can control the maximum tolerant conflicts by configuring [`conflict.threshold`](/tidb-lightning/tidb-lightning-configuration.md#tidb-lightning-task). The default value is `9223372036854775807`, which means that almost all errors are tolerant. diff --git a/tidb-lightning/tidb-lightning-physical-import-mode-usage.md b/tidb-lightning/tidb-lightning-physical-import-mode-usage.md index 2b4fef7fb6b59..55c59c0ae2bc9 100644 --- a/tidb-lightning/tidb-lightning-physical-import-mode-usage.md +++ b/tidb-lightning/tidb-lightning-physical-import-mode-usage.md @@ -30,13 +30,15 @@ check-requirements = true data-source-dir = "/data/my_database" [conflict] -# Starting from v7.3.0, a new version of strategy is introduced to handle conflicting data. The default value is "". +# Starting from v7.3.0, a new version of strategy is introduced to handle conflicting data. The default value is "". Starting from v8.0.0, TiDB Lightning optimizes the conflict strategy for both physical and logical import modes (experimental). # - "": TiDB Lightning does not detect or handle conflicting data. If the source file contains conflicting primary or unique key records, the subsequent step reports an error. # - "error": when detecting conflicting primary or unique key records in the imported data, TiDB Lightning terminates the import and reports an error. -# - "replace": when encountering conflicting primary or unique key records, TiDB Lightning retains the new data and overwrites the old data. -# - "ignore": when encountering conflicting primary or unique key records, TiDB Lightning retains the old data and ignores the new data. -# The new version strategy cannot be used together with tikv-importer.duplicate-resolution (the old version of conflict detection). +# - "replace": when encountering conflicting primary or unique key records, TiDB Lightning retains the latest data and overwrites the old data. +# The conflicting data are recorded in the `lightning_task_info.conflict_error_v2` table (recording conflicting data detected by post-import conflict detection) and the `conflict_records` table (recording conflicting data detected by preprocess conflict detection) of the target TiDB cluster. +# You can manually insert the correct records into the target table based on your application requirements. Note that the target TiKV must be v5.2.0 or later versions. strategy = "" +# Controls whether to enable preprocess conflict detection, which checks conflicts in data before importing it to TiDB. In scenarios where the ratio of conflict records is greater than or equal to 1%, it is recommended to enable preprocess conflict detection for better performance in conflict detection. In other scenarios, it is recommended to disable it. The default value is false, indicating that TiDB Lightning only checks conflicts after the import. If you set it to true, TiDB Lightning checks conflicts both before and after the import. This parameter is experimental. +# precheck-conflict-before-import = false # threshold = 9223372036854775807 # max-record-rows = 100 @@ -44,6 +46,7 @@ strategy = "" # Import mode. "local" means using the physical import mode. backend = "local" +# Starting from v8.0.0, the `duplicate-resolution` parameter is deprecated. For more information, see . # The method to resolve the conflicting data. duplicate-resolution = 'remove' @@ -101,36 +104,37 @@ Conflicting data refers to two or more records with the same primary key or uniq There are two versions for conflict detection: - The new version of conflict detection, controlled by the `conflict` configuration item. -- The old version of conflict detection, controlled by the `tikv-importer.duplicate-resolution` configuration item. +- The old version of conflict detection (deprecated in v8.0.0), controlled by the `tikv-importer.duplicate-resolution` configuration item. ### The new version of conflict detection -The meaning of configuration values are as follows: +The meanings of configuration values are as follows: | Strategy | Default behavior of conflicting data | The corresponding SQL statement | | :-- | :-- | :-- | -| `"replace"` | Replacing existing data with new data. | `REPLACE INTO ...` | -| `"ignore"` | Keeping existing data and ignoring new data. | `INSERT IGNORE INTO ...` | -| `"error"` | Pausing the import and reporting an error. | `INSERT INTO ...` | -| `""` | TiDB Lightning does not detect or handle conflicting data. If data with primary and unique key conflicts exists, the subsequent step reports an error. | None | +| `"replace"` | Retaining the latest data and overwriting the old data | `REPLACE INTO ...` | +| `"error"` | Terminating the import and reporting an error. | `INSERT INTO ...` | +| `""` | TiDB Lightning does not detect or handle conflicting data. If data with primary and unique key conflicts exists, the subsequent checksum step reports an error. | None | > **Note:** > > The conflict detection result in the physical import mode might differ from SQL-based import due to internal implementation and limitation of TiDB Lightning. -When the strategy is `"replace"` or `"ignore"`, conflicting data is treated as [conflict errors](/tidb-lightning/tidb-lightning-error-resolution.md#conflict-errors). If the [`conflict.threshold`](/tidb-lightning/tidb-lightning-configuration.md#tidb-lightning-task) value is greater than `0`, TiDB Lightning tolerates the specified number of conflict errors. The default value is `9223372036854775807`, which means that almost all errors are tolerant. For more information, see [error resolution](/tidb-lightning/tidb-lightning-error-resolution.md). +When the strategy is `"error"` and conflicting data is detected, TiDB Lightning reports an error and exits the import. When the strategy is `"replace"`, conflicting data is treated as [conflict errors](/tidb-lightning/tidb-lightning-error-resolution.md#conflict-errors). If the [`conflict.threshold`](/tidb-lightning/tidb-lightning-configuration.md#tidb-lightning-task) value is greater than `0`, TiDB Lightning tolerates the specified number of conflict errors. The default value is `9223372036854775807`, which means that almost all errors are tolerant. For more information, see [error resolution](/tidb-lightning/tidb-lightning-error-resolution.md). The new version of conflict detection has the following limitations: - Before importing, TiDB Lightning prechecks potential conflicting data by reading all data and encoding it. During the detection process, TiDB Lightning uses `tikv-importer.sorted-kv-dir` to store temporary files. After the detection is complete, TiDB Lightning retains the results for import phase. This introduces additional overhead for time consumption, disk space usage, and API requests to read the data. - The new version of conflict detection only works in a single node, and does not apply to parallel imports and scenarios where the `disk-quota` parameter is enabled. -- The new version (`conflict`) and old version (`tikv-importer.duplicate-resolution`) conflict detection cannot be used at the same time. The new version of conflict detection is enabled when the configuration [`conflict.strategy`](/tidb-lightning/tidb-lightning-configuration.md#tidb-lightning-task) is set. -Compared with the old version of conflict detection, the new version takes less time when the imported data contains a large amount of conflicting data. It is recommended that you use the new version of conflict detection in non-parallel import tasks when the data contains conflicting data and there is sufficient local disk space. +The new version of conflict detection controls whether to enable preprocess conflict detection via the `precheck-conflict-before-import` parameter. In cases where the original data contains a lot of conflicting data, the total time consumed by conflict detection before and after the import is less than that of the old version. Therefore, it is recommended to enable preprocess conflict detection in scenarios where the ratio of conflict records is greater than or equal to 1% and the local disk space is sufficient. -### The old version of conflict detection +### The old version of conflict detection (deprecated in v8.0.0) -The old version of conflict detection is enabled when `tikv-importer.duplicate-resolution` is not an empty string. In v7.2.0 and earlier versions, TiDB Lightning only supports this conflict detection method. +Starting from v8.0.0, the old version of conflict detection (`tikv-importer.duplicate-resolution`) is deprecated. If `tikv-importer.duplicate-resolution` is `remove` and `conflict.strategy` is not configured, TiDB Lightning automatically enables the new version of conflict detection by assigning the value of `conflict.strategy` to `"replace"`. Note that `tikv-importer.duplicate-resolution` and `conflict.strategy` cannot be configured at the same time, as it will result in an error. + +- For versions between v7.3.0 and v7.6.0, TiDB Lightning enables the old version of conflict detection when `tikv-importer.duplicate-resolution` is not an empty string. +- For v7.2.0 and earlier versions, TiDB Lightning only supports the old version of conflict detection. In the old version of conflict detection, TiDB Lightning offers two strategies: From c05eb6f1cf9a1283bff8eb782f4f7edd670d2eea Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Tue, 26 Mar 2024 09:47:16 +0800 Subject: [PATCH 81/82] Global sort documents update (#16605) --- sql-statements/sql-statement-import-into.md | 10 +++------- system-variables.md | 4 ++-- tidb-global-sort.md | 7 ++++--- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/sql-statements/sql-statement-import-into.md b/sql-statements/sql-statement-import-into.md index 309d6ae00473e..db0fc465d20c5 100644 --- a/sql-statements/sql-statement-import-into.md +++ b/sql-statements/sql-statement-import-into.md @@ -29,12 +29,12 @@ The `IMPORT INTO` statement lets you import data to TiDB via the [Physical Impor ### `IMPORT INTO ... FROM FILE` restrictions -- For TiDB Self-Hosted, `IMPORT INTO` supports importing data within 10 TiB. For [TiDB Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-dedicated), `IMPORT INTO` supports importing data within 50 GiB. +- For TiDB Self-Hosted, each `IMPORT INTO` task supports importing data within 10 TiB. If you enable the [Global Sort](/tidb-global-sort.md) feature, each `IMPORT INTO` task supports importing data within 40 TiB. +- For [TiDB Dedicated](https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-dedicated), if your data to be imported exceeds 500 GiB, it is recommended to use TiDB nodes with at least 16 cores and enable the [Global Sort](/tidb-global-sort.md) feature, then each `IMPORT INTO` task supports importing data within 40 TiB. If your data to be imported is within 500 GiB or if the cores of your TiDB nodes are less than 16, it is not recommended to enable the [Global Sort](/tidb-global-sort.md) feature. - The execution of `IMPORT INTO ... FROM FILE` blocks the current connection until the import is completed. To execute the statement asynchronously, you can add the `DETACHED` option. - Up to 16 `IMPORT INTO` tasks can run simultaneously on each cluster (see [TiDB Distributed eXecution Framework (DXF) usage limitations](/tidb-distributed-execution-framework.md#limitation)). When a cluster lacks sufficient resources or reaches the maximum number of tasks, newly submitted import tasks are queued for execution. - When the [Global Sort](/tidb-global-sort.md) feature is used for data import, the value of the `THREAD` option must be at least `16`. - When the [Global Sort](/tidb-global-sort.md) feature is used for data import, the data size of a single row after encoding must not exceed 32 MiB. -- When the Global Sort feature is used for data import, if the target TiDB cluster is deleted before the import task is completed, temporary data used for global sorting might remain on Amazon S3. In this case, you need to delete the residual data manually to avoid increasing S3 storage costs. - All `IMPORT INTO` tasks that are created when [TiDB Distributed eXecution Framework (DXF)](/tidb-distributed-execution-framework.md) is not enabled run directly on the nodes where the tasks are submitted, and these tasks will not be scheduled for execution on other TiDB nodes even after DXF is enabled later. After DXF is enabled, only newly created `IMPORT INTO` tasks that import data from S3 or GCS are automatically scheduled or failed over to other TiDB nodes for execution. ### `IMPORT INTO ... FROM SELECT` restrictions @@ -184,10 +184,6 @@ For TiDB Self-Hosted, `IMPORT INTO ... FROM FILE` supports importing data from f ### Global Sort -> **Warning:** -> -> The Global Sort feature is experimental. It is not recommended to use it in production environments. - `IMPORT INTO ... FROM FILE` splits the data import job of a source data file into multiple sub-jobs, each sub-job independently encoding and sorting data before importing. If the encoded KV ranges of these sub-jobs have significant overlap (to learn how TiDB encodes data to KV, see [TiDB computing](/tidb-computing.md)), TiKV needs to keep compaction during import, leading to a decrease in import performance and stability. In the following scenarios, there can be significant overlap in KV ranges: @@ -196,7 +192,7 @@ In the following scenarios, there can be significant overlap in KV ranges: - `IMPORT INTO` splits sub-jobs based on the traversal order of data files, usually sorted by file name in lexicographic order. - If the target table has many indexes, or the index column values are scattered in the data file, the index KV generated by the encoding of each sub-job will also overlap. -When the [TiDB Distributed eXecution Framework (DXF)](/tidb-distributed-execution-framework.md) is enabled, you can enable [Global Sort](/tidb-global-sort.md) by specifying the `CLOUD_STORAGE_URI` option in the `IMPORT INTO` statement or by specifying the target storage address for encoded KV data using the system variable [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-new-in-v740). Note that currently, only S3 is supported as the Global Sort storage address. When Global Sort is enabled, `IMPORT INTO` writes encoded KV data to the cloud storage, performs Global Sort in the cloud storage, and then parallelly imports the globally sorted index and table data into TiKV. This prevents problems caused by KV overlap and enhances import stability. +When the [TiDB Distributed eXecution Framework (DXF)](/tidb-distributed-execution-framework.md) is enabled, you can enable [Global Sort](/tidb-global-sort.md) by specifying the `CLOUD_STORAGE_URI` option in the `IMPORT INTO` statement or by specifying the target storage address for encoded KV data using the system variable [`tidb_cloud_storage_uri`](/system-variables.md#tidb_cloud_storage_uri-new-in-v740). Currently, Global Sort supports using Amazon S3 as the storage address. When Global Sort is enabled, `IMPORT INTO` writes encoded KV data to the cloud storage, performs Global Sort in the cloud storage, and then parallelly imports the globally sorted index and table data into TiKV. This prevents problems caused by KV overlap and enhances import stability and performance. Global Sort consumes a significant amount of memory resources. Before the data import, it is recommended to configure the [`tidb_server_memory_limit_gc_trigger`](/system-variables.md#tidb_server_memory_limit_gc_trigger-new-in-v640) and [`tidb_server_memory_limit`](/system-variables.md#tidb_server_memory_limit-new-in-v640) variables, which avoids golang GC being frequently triggered and thus affecting the import efficiency. diff --git a/system-variables.md b/system-variables.md index c144c397e3567..387983a80e371 100644 --- a/system-variables.md +++ b/system-variables.md @@ -1625,9 +1625,9 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; ### tidb_cloud_storage_uri New in v7.4.0 -> **Warning:** +> **Note:** > -> This feature is experimental. It is not recommended that you use it in the production environment. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub. +> Currently, the [Global Sort](/tidb-global-sort.md) process consumes a large amount of computing and memory resources of TiDB nodes. In scenarios such as adding indexes online while user business applications are running, it is recommended to add new TiDB nodes to the cluster and set the [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) variable of these nodes to `"background"`. In this way, the distributed framework schedules tasks to these nodes, isolating the workload from other TiDB nodes to reduce the impact of executing backend tasks such as `ADD INDEX` and `IMPORT INTO` on user business applications. - Scope: GLOBAL - Persists to cluster: Yes diff --git a/tidb-global-sort.md b/tidb-global-sort.md index abddbf4cdef6b..3094178c46877 100644 --- a/tidb-global-sort.md +++ b/tidb-global-sort.md @@ -8,9 +8,10 @@ summary: Learn the use cases, limitations, usage, and implementation principles # TiDB Global Sort -> **Warning:** +> **Note:** > -> This feature is experimental. It is not recommended that you use it in the production environment. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub. +> - Currently, the Global Sort process consumes a large amount of computing and memory resources of TiDB nodes. In scenarios such as adding indexes online while user business applications are running, it is recommended to add new TiDB nodes to the cluster and set the [`tidb_service_scope`](/system-variables.md#tidb_service_scope-new-in-v740) variable of these nodes to `"background"`. In this way, the distributed framework schedules tasks to these nodes, isolating the workload from other TiDB nodes to reduce the impact of executing backend tasks such as `ADD INDEX` and `IMPORT INTO` on user business applications. +> - When the Global Sort feature is used, it is recommended to use TiDB nodes with at least 16 cores of CPU and 32 GiB of memory to avoid OOM. > **Note:** > @@ -20,7 +21,7 @@ summary: Learn the use cases, limitations, usage, and implementation principles The TiDB Global Sort feature enhances the stability and efficiency of data import and DDL (Data Definition Language) operations. It serves as a general operator in the [TiDB Distributed eXecution Framework (DXF)](/tidb-distributed-execution-framework.md), providing a global sort service on cloud. -The Global Sort feature currently only supports using Amazon S3 as cloud storage. In future releases, it will be extended to support multiple shared storage interfaces, such as POSIX, enabling seamless integration with different storage systems. This flexibility enables efficient and adaptable data sorting for various use cases. +Currently, the Global Sort feature supports using Amazon S3 as cloud storage. ## Use cases From 5e9a4e3a29ac68bfa09354279a595d25478c3d35 Mon Sep 17 00:00:00 2001 From: hongshaoyang Date: Tue, 26 Mar 2024 09:51:46 +0800 Subject: [PATCH 82/82] Update sql-statement-explain.md - typo (#16721) --- sql-statements/sql-statement-explain.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-statements/sql-statement-explain.md b/sql-statements/sql-statement-explain.md index 029736828d8a1..e99e5b1d12598 100644 --- a/sql-statements/sql-statement-explain.md +++ b/sql-statements/sql-statement-explain.md @@ -6,7 +6,7 @@ aliases: ['/docs/dev/sql-statements/sql-statement-explain/','/docs/dev/reference # `EXPLAIN` -The `EXPLAIN` statement shows the execution plan for a query without executing it. It is complimented by `EXPLAIN ANALYZE` which will execute the query. If the output of `EXPLAIN` does not match the expected result, consider executing `ANALYZE TABLE` on each table in the query. +The `EXPLAIN` statement shows the execution plan for a query without executing it. It complements the `EXPLAIN ANALYZE` statement, which executes the query. If the output of `EXPLAIN` does not match the expected result, consider executing `ANALYZE TABLE` on each table in the query to make sure the table statistics are up to date. The statements `DESC` and `DESCRIBE` are aliases of this statement. The alternative usage of `EXPLAIN ` is documented under [`SHOW [FULL] COLUMNS FROM`](/sql-statements/sql-statement-show-columns-from.md).

a@Z-R)~+V%`OFdG($9XfI>4yXVL1~lR(mb|0l6dC)8g(47lg@%c&`1T zfk|^uNu_&|A2r_S)(wl*0&H<(#vq3m%y%Jtny_s3IjhXj934g77xL0GYKX3YK{)7+ zMLA(I_b<AH6t@dY@jju=tz~IN-+gI{Ow;ssj z#>jHd)icZ2kiSdvR;%zr((5nlkA2FM`Sp|EMB9vJo{na=dj9^+d-b!st>*jkcbq4% zXR=!d_t(3Q(T0m*gKl5Iuv1&l%k$FF{~P4TQbT&Z>rNN^Kd9CEVcTjgv6Pe3sfBm8 z%ql@ajr7%h#xc#8%U>UxYN@xbfS&VF&6n%j_oUQYJ3$oJge$g=|4sYoevDEiz8MS$s z9-%bqMs&{v(O-t#deLTJ=@gws0!H!sS|m9qftlnP6cb2uDw;ZhKiTh*DEmjH1}OBA z4#(61Y#>+uQL_n+VC8X8$5X1u9y{|*fyg7!J{Mh4aWMj%eIkH>HE4+{6GPnKkD=%j5HqilpFgXLjGg*kC zx_51y3amdGEil?vFBzm$ELOpSK;L*Scga)BxD?*;O2(Yr`HUd&Al3a7w``64Wtp!R z>~Q6E(@2e}@DB9oY8UOnV*O7NU8d0K#y4B!!(!$bF6xmpRT%`mxUtv+q`~oBVlXrS3EjK3S7A&-Nm$7}val@KlgjpJ=t|svTAiiI|ka+t)Nh3(|nHs!O8fa`@-n)C0QF}6e8vgqxuMH&iHK34NyJPx6^Y{ zp;OUoW-=Jrip{UFsmbHm)UxJ9H1b&~E%9=&y#!TF^i9F**+|`CVCh5NLNQgO;P`&K z?n{77d`x=C=fm!@YveWq0V}`MuXLUl>pza@TPl%Z=kSc#s@Zkim-DEa8dkT(rrFJ{ zFrLF^IFdm2VZ9TSr96se!CC|h*^CtRE=T1!%dl1Ah8pQ~Touq6pGF>_nF~W7R+XIx zi8T|ZhhEMJZ4aSNmIWAU@RKG=Na;G(C)q3wmy=e;?tl7^8+F&`!j6o8DBp5*B#w-C zYxV#Q)s?!A{_>_z`Obq_D6eSi@ZOdg*77K%8^lB3MUy5{x61MUl=+V8n8>E|Vxt?K z07&r(ms!;x5{7`U!JPZZ%!PPq;0XNe6Jb!3tDa?EvktL&x@=?j!aSjd&?q78^o2p` zX%DIRa|ZqGvJD9y<_X)BO3a)OIA_~eDo8(Q2B$DHwn@OOe-5>HFSk@El~$2&RTyWQ zEst6}x|B<{5@rOQUTblit1cO`w2e%WP~iuV0H6cJ$?A5gD^Z%q(jb)XZCx|EB_7fH^sH{n!@=jG|(06ZM)udmPZOsMOTQfZaa6^Fv7r>A~bYLxNl zrIwR7-Fq-f{&1Jcj6EN#6AJl?LLJ*b(VdUM7bI*_Fd|36eMy1?(=qHyd@VlOMiui<{S9*t8 znfkkkQqc{X!5xwmP;jegigqht_iQT>7Fy2WF&w=t8Re4fWN;-+bZ;)-V`E9sSURLE zUU_bene)Sqns+>^$MJTct`!M&Y!L%jH>c&zsWREe4z5wLczNi`xTP65%GSQ*<6(sq zkF2Kn5~Bk?#sKTqb5__p$D?Zfb488@elt%q3dg~UJ|p#26Cp=JiUP2855gH+!_uQw zU~%{MThk^3h%{{{*-E89AusPdw`nsEjH`}*7(_9BF$U%CpIR2*#r@^yqPA>TmA6zi z&X`7NDvUpwDrHNUzBFQD(R^2lE48w1o$k4eSb<_C`3T4cZT%$nK<*V3j>slfyGep$ zLYvEfP-Z)zJK)eis56wxjRp9QCO&EuMc>+o+v()cDGi~H^p6SSv2;vb`7!ec@(+vi znt3*&vG;>8nLs#sJFD2(^3u{4ZSPdOljXbCQC105RJD#8EMdAsiy2Z-xtmUin(a%y z^Wr@sFojR8l-H5bvkeHYdGS(dtry-cXR({iYHhL&FG1L+2f5(Ra;5>YkU~l*+L-;g zAw{>n_N)8rt8zL7*9o$U)v@N8cqiJi$$|nH^SzZ3)uI85vc^D*u&&0 zbUyCC2@%8N8QpEi<%P3S)CvM${kD)S0n@4S+wrc>O_BH<%)nN=aN=gb$8Q#cCsem( zRG)i<`2u6P1~3@6{%wiQkWwevaN&1?d?kS@62%xz(|5jcA&5M4rHKxu!KEu)HM0)h zP(^>~ZX%TRH5Q48ryC`|rT<`ET)jT@l^OUjh5mOtg}7=u19OPx<{6_rP809;b;T~N z3JohD1#w9tENn0nMV8df!Z$5EZg&N9uyH zL`04Ap^1_H;|em~%pqni9>O`iId1fe$}`f*sx?o|=%`}1I!y8Aao!YSDxOi~@no`n zaU8c~#QY@1%L-#r*sQ3-$JLn3>3lHA;t>oPX;~NWz6+bHb#-uM zl4uSR1)>W=mRoBlmXE-$t+kF9hV9MAZ#*isl-g%nMZj#qMMcemWOE*ij3UOCDr8JX zYz7r)S@pA7dJz4-GSnn@W7KDa5T^A9oGM9X!wv@LA#jeU%G`O21#A8Ij%I~Dr%8%R zG;fT2yaBwn%b0C5g)E4vCfh8-TC0C~+d^AH0dJUf41%RiV_$L{WtW#~eEV44V_wbD zzuLGj{P%N+uS@d619pqL?+Gt#U}|aR_iTZekQJWqKJeMdF_y;0N6a(|G->*N9{+i@ zn3ns0vLx<->_e#{18qL%geQ-Jf!U)xtTki*BzilBl8C5?0JNi zd^(YSH{JuZ1Z8N)ws|tCw)WXyB{(#6^t4lNU@J=T1^K)#mSt9y>fDrt3O@0BnrIb7&qE!A0N5%>ZHrNyLwM~f=L3R6tmV#=k%qdLSYgFpTmW6xelnB zG%+Bpf_&A?i`8muvOeSKG{TK(F0?3(5qr2->JX^i$w5Uzi{(uS*3#-6)}x%(uQ(au zi970Y`mwvT`9(Tc$54f%>zn<>?-~k7bDPIf6An5OjKoONw&J9v?`gI|8Xt^6kc|$y z>GB%~{w(%Zj(LPng46gMEdukt!^h*R8V!T+B=LCrWS2$hquO5LbJY!J4G1v!tM2gb zhwWI+dW81?pW!dwJIvw@L#jqPC<$$tY3z&MZOSs{3AJ)36fBXDwEi3|bK#F8HwZu9 zDSpY$=tjU=6@jtU4B1CLWk0Un1;QeKJLuL-RF^9f0Dw8iG@lP*hcZle=rSyDqLP#{ z>rs}@C2cT!i=6=Jida&bqZ8zf8OgQ$s_G!Ozx1fW%K zgA%Of6TOEYHIfnR)TbiR$rllVc%7ndPRF*enNs#ce-9=y(W>YQcd2ldnvH zku`cujEW8R`!3M(XVlB>N1XPQwb)Y`{4sDhwb*Vh->E=xJzR}~Wk`4thvVyqEOl23 zNC2o(X*v1HL=la2d9V)F!j;ns!?n%$sv&-x#CIV?8k8>9K5CzI!33>0e7UE30ScJl zhqWs9B$cMf;X#|IA~S3Dha$`<7#thPT*S*!WC!exwLkuq1vgy4YKn~b&vs{E?kX=B z&#w*+lxLWfso9^?WMh)o1ToUqB~L;!1k3G|k}H{lQOD&0h|pyp*)RMf_fAU=6X8~@ zvgiFw#WeHO`-B=6BU?o1P$&Azp)^YyI|O25e}rqXKbD^cN3T%_ir*zYBrPVN!1FN8 zczWoxZV%VPfd@JaiNL+Ak$e6^M8Cy|#FOalqenWA-X)ggwL5CP)Z~BwBjcSFA31p3 z7~$&Fs=?5s?j#gM*fcfHbjGA5hplCu+TkUol{&O)?AAn@Ar$HU-xaw9*)bLqJvbRy zkEMk$as=^p22)dw{iT0#>DtpO1>m3t?U_t3C4yAer|DNNZHJH%1!%_fHhz}5o`#mL znM=@*cla}cYV=7-BJq^4VSm8ng|IPGw48u2)_+;GceZA6OSH-_G0K%%F0gfc)7Q7F zi$M4JNPy(C4OfL;5&Bl{K|i({y8&(=UxmoJnNyW+jfdrLTc$nshi&(wIhTC%qc3`w zGP51ntmI7-(6+K2WJigc=OmlXT$)+&|QxkdD7^F&gs z;2&mWu5Ux9wfGs3+LKa#*esMiK(R6F*ij_3x(DBG&!7~A1)Y61)iNB$m<3v>UlQNw zF@%=_)z6b~+wG*f&_$tyo15>xh^S(5oDi#6r|~DJy zL?0cq!#^|g=!?QT*)GjNNYo9#YnWF6v^vLa?y#jQGny1p$z)?7?PRiCFpspmT8~gwn<~s3xKG&ygsW zS~1ZP$JAV1flzsq=^7mW{iALEF!hmW^uWR3>d&*UlD3vw5%0_?>2~G4<0KHLSPvcs>h*sY+7D<6= zv(bW6o)Y0-49#mM>JPKLrkt&Ql>5h#%y8K_+7L1xGuLDZ{oIW`CN+MUq}HlnVOe8h zEUs#>q#0uFW-68q_G-Aeh(JV|)u=`(Grly<{&_PMx-}3snpYPSz%C1pUbl_0vS`Gl ziTUtb7Fec{Ek(J@5ck+rIEs)>ocfkUq`RtoeI{KpExcr!DC?VcqW^NC&NFN6LL7)P zAng+|~xI#DotTwew@?ja5QKQWr?Wt+! zBtEVzDl{pq0G<&diIZwIg1?D+HG_8%^Ea0Z@zb8>DVL)7cG*f)2sP`&yx_o$ALTZN z;-z+D4!nvmfeC`0ZKWEnWvEy6au9NRwN~GZ!*MMZE!(d8|3nBf8~##Gd@N5r!f735 z0hgU@PqDCO zhrRiRETU6j_t;t|#Jweui`n4AYTNkoeuzpL)OP5fSH?N49>gMBWbUC8&r9tj*{y)j z;y@CmI+3$PFI`gxufW29^s(hj!POx zO=kHe?l5^M$$<@%+|&*ha%gAq^Ql(B)Re9k{!)Ud-WW49L~pq-$2D%>xOzt%daq|1 zI-7C#r2VWjf>VlCf9Sy^jjWU-tkqQd*QD3{M#QIe(di!P7or6F(?msPM6AGcC0~{` zZoX=ni5im>-*=g0{@NKG?cK^>x?fWST{-Hghxt6+|2Fp8`RJT)+1{C)T>*BdHC*@1 z^!oBY1`c=iYg4g79NMcR zDL7+0t&b zdhvZkUd)a|hI?6_wOc;c4tr046$eT*+-?ORc7S1bLl|oL0OsnZpsI{t=@&b8x zF@Hj^*Icz%_L;<)XD9NW=I(d`$33QTnHVVwV~)J?;QN zkC+U+4>K!-l5jzx==(}OPH;^-Fw2-WYvxih6z)b043r~JYiwrk6&N4US8qG^io_ky z-CU7Z<}Y5Ir&RNeG|SP$z$=tOt%E%?NzA3Yk7c@pd0C3?^kcXazmKKsxU?K=-1@>` z?r2$KIdSIBDx_ybmR{>;Zi6;p%3M#AJjh|?JVZ!qhSt!-8YAusWChX0x}&l1|D`fd z=;80=SVcmk5BA8>>cNg@?z$rkMtwOX4eDP_zY`*ufV5*CFfjM;Yf6`_!Bb0_C8ne! zp>YVn$Qf8TDOYdL2;aq%r{rQ+u@AE`bmgOx3*D-?O)B4*EH3{ z6)kgg^b}=iOK%hQzt|pOpUQ^^%6+F%p#3Ou0oVn4G5n#E(4~3m86C3vWrSu>10%$n zlu(1tG5sBwMZNe1coyfJK0Nn;ecWr!2gC@CH{MvQ8t=B@5g#*`U@FDUUT zwaa-veWylDtziJTVP~1Dui+yn)bZt>6}Pp3}A#&AV`_Q;C(>C)|U~az^)DdIed9P=o$u_ zwT_dXy2k*EvulrqBn5mm=QMf<4ODeOp&5d#&kB^3n+k?FRMgz>2=XxAj(XFL49@ZF zSwu7Q9MmbFSUhv{QpW!6ek-Lh4tfgJ*eQ0HjOaqwOwU3H6X8gj8a5^51YuAdDrBEP zD)3$Tg9*Y&WF?!eYUaZ1tB#5kpFdv4Y|lPFKZZx)WTs(}zvL<_j`6sAx*lG*$J*$q zNPFL2M6ti$mxd8AU{TJCl4K-QYZr@m!iM*h51u_hohM(-+1T*%%=vqpXh*< z(~YFxXG@vp=@@{N8Z)ca<_YMd)p;ev(ri-#Ot=vo8z?i-(L8g1m|0I4vGHm-PXhsw zwdmJjwYQC^G9O8L9#{ZJH<((=#Con-W3#`K;hk*xca`LfxeJbsDsrr=8MfX9`FYwfk<4b(pz~21P4q45fO?E zGu6s`fpah4298v?n@00OBcf$Jp7p{Kx?|QiYH<_Dj+76GF3F@d)EDk zZ!ml`QX3-3$yAs2LC_8Sc2?x@BA3_Lb3ZSgxhO!;1Wiz%JS_}-vYPlu%Vb?x)4;|) zWL*jvSbI1M)M|{dw=+I_{iX8n!H&F>P!!35G8X9tJAX^ob%_SRy=BoOlNxQL+_ck} zu7pscVft^g!14Dj>V(vO>s2N5O=304)xgP=Vq~WRf!fO>8e>w?APa6*WuHIxSlO*j zqMg#48b3m7cc5 zAq%IQqVQYf!`8=%<}b9sP`VTIw_j z-}k|XQ3GIB`d4@f&WLqE^}e?bly1jJ{l_Ln_FFF<+i9%cweM&Wvdsg*sw&*@$+kNH zJpO_4jv$&Q)Rs=rI|=?-ymv@DtOw~7Ys&;3>+X6B^u#jRbiQ~X+`z##nLxD0j_S}t z79t0Z*uWNCT?xqFB*PWK z$y8J;^tzUJV%B3~%3gzJ_$Gbm^_x%ue5%=bS+_JPX;zf6ycO820!0-UK5$@&^9(cW z{ser62X6qzF>BWA!l;@U8{l9bmUq+SkdXso4Y?>{MR2G{CM95eND30lTq4$$CN^_x zhaW@f0uHaL@b4HBt!&+AasFW)oSZ&|+gi9xZiG`I=jo_J2Om>8o3MD<$hGMDcaYMI z$8w+gns)?ksghi%s+f*QvLsGqN==Rifx2_&`{Y)KQM#SRYg@00f$tm7yg^75n?{?} zU6X*!WziGilui%$Rp78slb{*kVC&#C1dSd91 zd44?GpW2H_ule~DAnRd?vBZU|r|(RG`RLYZY6Ur!x3X3~s5ll7{_gy7Vra($KJxQD5n0!R%)KbLYIy;oQ4~YDb+&HBLI^K z=o`pCH?I0h>*8QfGmlKO2cuUR!~v5eLu^PvdcG{lrA#t5G1~&#Xo@*>s^#EL8o66> zxMpE+F+wojb(bK_?2+RiHf=D-sADL7^T65wv zpIMblM?PFj7>(PLhEYe=`)>5<8jUDV@+W;9{l+r6sz9>KUl29n%&L@BdXhnP76-z5qR}xi$SZg`<3~n;?{76Prfx zl^UGzld85lc_g}d4w;{pFklwpz7|rmk~}~w7RRGV0Z!jvqIt|JmA0Q$?g?;hU%kyC!6WP~fFz{l+ax&_LAY9FCS zbivb=fY|_HgfXx19-~O$KE4r7{=z5+3VQM7lQWub;Bgf><$Uv7yN3^*C^6l-Yq=ov zuk+KtZxhn*P!H6>fPoJ$)P0Zaj{8J`8boH^GsJw2+To5-ONsQ-@ph@p>H8kHl6Q|- z@*n%%#%Kx^Fs6Bb($wQ2XZi;7@3CU6P_|F=gScm}j|t3z2`*jH?t4#xs-(KQt1xGv z2g0?!CpXnXfg_gV_h)wO#>?-yNUD`mQ5l>tHW-IIA*ko}Dzs2zm`1TF=-$EZ@_(%(P^GQ!87por>1IS9JQea;< zC}qc?j>R;^sKvUl4MMGPjm|p-!Uj&fD`-cBL4m)t-=IbfBi`V9lgtXy?x}N$TEeZH zXuNAVU$^^y^8Xj^j_%1;V2u)PUTGc`+SLoJBMqTFSmkS#CL%@mzoua)BW$5-jb-_okQ>hkwp||30#1IS7{V=S=^=b^E$SBpsJ}`NA zd|J`bfk`Owy2+z@FxG@iab5rnO5@b8hG~=o#XlIiFO_ZmU4sso z9!qL(>EaQf;~|a)C4Fw3mh0&GEEx-IAu3c-E)gija0LPS5w3Eg+BtqL53Gu^rEy%e z@U=nm-Gb>Jem9&_LB~@?N0YG8iDrNl>9rt{fRP5B;wmTgyOeWG%~9F3Vu@BEuapn- z>Du~EltX@H!Go-{N{q@agO?gc=bjiYJ2CDfvsZq**^;%z#|V3(y9PfUY~h11Mu1;G zIZ+J6^KUrEMmL}kt<2DKrOqU12?nXqCR5v5cvvJ0GE)*a41n8peS%p{Bbz0I7EBB{ zYn2DNR=U38P3pu^*m|~!3Rv@BPzS?<C#-t{NIxvIj&&@&CzTz*KB7WCpx;GHJ5zDl2< z2Ln|b2ZqZngqBLYoG8W&8XLtYc6Eg*cHc}Vz1uxOJsy=_w*1{$r`)b1I~;n$)aYSg zhy(IBn=Yi}{i^OcsPd5i%P8YyglIJL0m?C!MIKgW>q?`QiLx#h><3F!(?POB{9Z~L zqSMU4D1Wp?*8TejR3S$9XN_HR%^}SZw~D@}g6my;O!cAHl^4@=#t3;=1|rJ4DjuFD zr3LdIl}PE;@&4$Y5c#v>NsoDIhvphHxAavM*CIhgFGh9XNw-UL4jZ@)0c)s zv)06!-vdfi={s+-6LOYHqG58-#2YFwB3Y%mpMzz>(tJ%7OYk`^29Vb5p#)cqS`13hwDC2Ykc7&UG)n|GFc9Q!!B*C1T`Jf2coLGDx~ zR;ep@VuK$|*<6J4ctO>Yl`QFvP@~k+`flG!U`JSq0ah+kahjW0KxqpKPm?^?sgsbu zs7id+{iXGfev2rb*jdFeqJ$%$&*0956-oXm_GSi>MECHXs?TD2J`m2ekaG`@Z7=_{ zMKNo1fOJ%zx*<||E_HlpN|f3*jmcSV+}iSK3i;FR`J9h>N`~a57hTC8NkYfZf@jln zR;^)e=9+C)>glV{rC04fqDYj)y&l(5)b>_%rZM&Ew?R2;k3{}vV@Dn$%CT(yc{yV; z7IG&It9_}07}<+uJPfrGa(?{oG&eClO z*$i{}pB*$t51g>#+q3nSv8(5O?bp6OP(dJ4>F znJiT|TmVcnsgqQsO9EMJ^WDBRtuN=mGGm>|st6vJ5xqT|hwrXRl*{TK!LE6(EWdcU zgT(Jav|{;u7-q8BPJAQ74`HYd)=3!?)?-LH;`Cr3W^|7o?A! zrX#!BTQ$Kf8BtEa#nP8-R_%lrtyi#Hjb)*SU_;!Pu`$fY8d1z$!5j`ND>cass{CEm zS-2BBaWf4!tQ~#zJUtaIipedf!b2Ywg=Mr`T+wz0!dwT!>21hjb|2v2LLv3%4Ywbd zCt`->Rj^lt9g{3ia>z-BI)J0r2oa~xnfKl$Xlz)BNrKAAnl<{=L)U{PpcLSQ;fS7h zJzeFVjIWl%Ye!=5P_*`Kv}TL_Ctg^YpDUg4^?-GS3Zms>%vRJEdHn5^km=*!)a1Y3^i0ht+BiQ( z&WO!4ogygmEI1ZNNf}gGAW)nW(|$x-RyFuESHpjkH6R}~p#Kf!-A;thr(e*1!r@-? zE3YP*y$t!#sl@}5_D5y$uTgu;Iuq5{jc3kr7H-S_zVS1f=1_#hqhzD})*`2Ojj8Ky z{SY8i@oA^oK&Qxcd+g1g<08|w=hWFv(~zKY63xLD$FQL+&Jm;wd-Vsk@dZ6oD(?M_6Z`H?Hc@s#N!_dCQz zDYIq8FW-J;Ie=6N_7z;L>g4g|>+u9~dhO`Esf;ygfh)Ii&FHM4Pr>s`LzrRQj-1I% zMZ?q`C?8{b%SqdI{=!rkK%~gl*&@fYg+M&hX#97EGk|PR#|Hns3q8w9slW&ySPIIx zp7TDDBAam1Q=mZa7_&;?Ln^ggeij?nul64s*f=vT{<3v7>^8MO%6EAw!i7#tnj0ZW-q33@UKF8sXwiUM zFZD(Mx&~h?*sK4-*rQiS{e_X}ds8T*258wj+<64-m}UC3|9lXzORCwLw8dU~B{#M2 zO;m5Qao>oo(spO2apA+1>QrP&E>`t#vC<5X2J#pAPN09RP~cEAjtDQ&hk%UBxzLI9 z&pSm8K7Q`bnrD3NiFrpDlo+c!2(4jmxKZH@jk!A0OryB94Kl4s*84-#bY$dW zCVXqkCrHRVshhwyf*(x%%H zwAQ9#NI$tF`fPd|m{XR^xikJ&QjH)dJi5#HwC9uk^=EaYwT~6=NVQS}fn!s*olw$` zA@U3=hmWd_+yV^7;_tapZ4y&k#y>+L0NUte1{}@4+d)n!D-MA*0Q5pXaD&JXa2o08 zNs8P*wTC9W#zjGQR5DEVlN^FmHm-oQEL<%&#KIEB1@QvnOF}qF6)Y9a;qbEufzj(p zq8(RXS?dmZEnOBXA)8c}9jN_R{PA(=01;xEi_b=sCWP*4l`koJ{LaJTJ$z z>JW{#e|7d!53$w2XrezS^dck%Av)Uv2+)0s|g7>lFRffCGOW5XJ5 z=jq&CVNWd7&V8igc}_hZq~+g8gvP{I_h|HT&KT0V=YL@gyy`euQ-0c_&F`&der#^j zo>NpxBJ(dJP}#u8IG7?Hj`&EkJW@urmr(zWD{9`l%=W?lINqTn(U0m&h|N@>XpbTbQh~&sOClIy)<<4q?hp&Gk0-MiU`Z ztNJw8LRXFLIdFBwq`N36#9ou1lm}jS^Q%{oChrFpyWMpZ# z_1)ueq9)fa?)>5a;U$qR!?dV#G@oFpt1k$yxHvkJm2|*`pLpTWT&fyt(w|M+tsPr; zPSa3Dl!l&`1ylF4L;Bmh$m>td10(1R+F_vRN7x0uoitPb zSq>jMoN_Fe{Uzw64fU00?wA|wUe_KxJNb>(Tmd&=tZ{Wo7V`K`QU0x0iYBr!!_wAc z_B9ot9};^=OlD@h@}vErG?bMQkI7!bm+0tsUsb4Pn1WD}(1|-$^ghVql*TpWk(i?u zv~Y<{Q<*4dp=Ri|nDAqOqEU+xH&em>mNE3(G>=QFzmWn}zOUa5b42A|m}VU)q}#Qx zg66XG-b*8lWi_~xom1c;oX3@XM}KxmKvPDo7L0~hel0^}GmTiJ7IxTG|LgE=9CBPk zv+`$P@A$VUTsk*<=Y-@gh%m{x#qraW0*9>Ullg27!D(z8W(bL>D(H8^*fKgVbll9R zMbb4rCruztFut=xilQQ2rjq@~WWm@HymQQ~d6bo1x-bw69?2SO1N*%afA~q5ONIo` z9bzC)xT@EoVS@t4m0oU{BL>3K3pdK_(CmgU{lH_-Yp1aTry8jf&4G7Ho$Zv1n?0rx zqBLTSD{jLjiqiWjeiQRI8Jt5!g*w4LMq{F2`&`sTR9kg}1!m0Mi0)X2->)8pnvrq5 zvs9T1Wll`S_{@&>Vh|EP@S?I+tgkKRm|JB->4p&aJ0SZUTVv;=k)6K|@YJ0?2Nkq1 zIo0$+x9K*Q5&*8kN+CTFI?n1!T4 z*sAInC(xFvzbq9Q%IE?(PFkxmozgpG{&g~iqCN$)@d_SXQw`imDqbf}Sl@T4ZkK}Q z3M&p;{bC>3y2CHbwJc9-epB$&q`+8olp{(_XhvH?;-2H;|5-MOO%3(Vo?u(FSr2Jd zW5KyI{sFd4T5TwvwxL~i!$~y@U$vTgs08l2-QZLiEd7GY8)*Wx-8(H0a$MI1&*{;o z1UH&~Ite_Zl_bbrxq*IwDyn4+1c$lC?9CHG=s6pwTs1R^X;}ibTZTSdr_ll|vbk^) zHuRI=JWmSed=>-VUXu0<_pA&JJ1y;NyW>s(cU^F<(y~MY+R6xp;6RbYzOJMdCz4W0 zzmuTJ_}^TXvSYhu3Hl)Qb0JMwtYQsF9;mE5)|D*t{f>QzO>;n?&2h z#JL%Us={1Cg>naTXG;x2!Js0$Yh=yP{*KR*XmTw`3nR%TRLvuqIpPR-|7u1K(OF36 zLw^+>>6{RpA7e$09p%}k=Y#yP&?SWp#4%t`5i)vft5%KomOwb zN{-B0i}>^_xis}h$%>*%)K3CF!cQ(+OmT^rBkcopqlm#W8qBUPv~e87&XhGdUDafG z{9Wy+g4|G;Lqr|;X@$7@MK;|My^(CILL?tfm#&*KH{eS zPqy~Iqr53h68gWY1_zvOci#PKbNqwswLQ?jO!1{%IABa9`_k!4>s3pgUjVYn&tA`W zS*9fC*!G9^Yp;B)UcIdTPpjTS+i5~x_xE@1=jT-;)f->$X%?UES+8_;dLQ+?9fzIz zjbHC^zpvdN?&+lX&V2gMBKaS}`p*q!V`#4z`d^p^lc;&^0qvfNfHU&9uAg4q(whG! zqsyi8@ZGrl=oqL2il`!0IqVvJl292gKY93vainF*O78In4-ZN%f%)Hzz%mRnW&+x^Z#n~Oe+IWW&j_OE_v%x}80`nAx2Q|}jCpXKaZr2oxK{DacY z*W)yONql#6Q4><*m-@OQ_GdVNSxLX(B~47mD(}j_M{Ra4xpov&TQG0NJN`B#FIsK! z>L13BN{FH8k$Q5$|2NK$|8>yKGyw6X5(sZ-K4qGK_zSYc?bf*yzT*f(wABn*3WG!J zU}FJu52d(IoTew0u`{f_5uy#7p94eo(@h76hcLG_u?Ht3vE+Pr*WQ;@t)qXI#OG6U zzjC9k9#?6!WIZNC{D_>HI&|V}aac#oFbDo}rWO`5acjq$QeD3p`CV#Lz37f-D9Z$T z6H6Av!D01||MJ0$#z)EiPFM|zF-CBlSc`s4bbL}HjbUSr)*DAIo{j=8QMSLkyn_iB zzM(?hn%V*>vdpUPIYB+S^1r7&rItX!V$D6|ZB**&#tSf&0Iz=v#s=xw(y0e#VMJK8 zL=nN9+wxL;CXQNH+@(zw!r?Qcci=1Z``lNAg|CUE0t-3@s{W@BlzDee))g)g*BM8kl)9oKS_|SYBFF?VjKpJ6wON}4&tvI8N zy>cErB3Ks8=`>`ev2A93x z!+=u(%$BL3L0NqxeCVz;dKIBJ9dP@AgiK49e^)|m!W=XiE8ivJapS0Kp*H5ptXW() z&dct9#KS8|hdR;lljx$|li20az*Gf0ee_4&4AzaRnWXNLn^gi4(`KSN3 zG&O(@oQ7trn-Kch=3DW)d%=6xzM4odCiL*W4}liV<~JO@IFHPiu1i|Fw#f{yocc{nyv1 z7wybetbeRtJa*yNhOdN~Ux%-M%gO@PyGW$}QQrD5SnJYp>L>9}W^x6NA=D=6d;LZV zJNemw8){8WqCmko5L+^RU?`&dWx69*rvEs_{LFDkjGh?SidLBNbsJatRZZy6jPO@< z{u+^}vViimi5c=)V6Gkisfy|Zv?O?WrWU21QRi*L);wLrI((b95cc*Ljq)csf7QHW z%6Td@VeQ`j3*#vy#_TgcBTF{3;%jUA`{pzlfTZ;o#$QY5x76jc@YRd(Zu7snvk8Bd zW;`g0YyOS$PtP+g!QWCHe_(i;fF!vfw*KM)F zx2|We;i;+UCZg?}eI+LM!y3JsZ)*QdGvtHQ%>V9wGkUB3Z>bsm56?ft8g-fqc`w~p zo4=kIf4R5))>x_ZK8f`2y!raNaP}sgt|CI>Cua5^$$Y)iyj;ZYJ-ZqGbrUuJZ_eFU zuQ+9yaf0&;9RK0?Uoq>-iP9-0ish8;?@I)j-V<*vw>!9+arXC|ulj`zK>gMm@6TH_ zwIi6&8sq=M5Ey8GeO%KU{0rmA(!$?T)ELXroD`uA*e18|EBwyAlrhrvjQg4VkoWWL zv|Xmzap)mgGN#v7&5d8%XR)K8XTWu;&a$l_nH~Sxq3q&&HlHrgMrg`Iri=8bZZBZ0 z-l9?Wa!9&bPn{$-#{xo+gV)m+KPEE>_a}6=pwav^emto`nnuBZq#r*)kWa2}tNoyG zE^E~uZjj$*8*{U89woks@YJCm);Oqm8{l?T57zX>=a5h~gRrJ=>7k;`5)*Td7OT(| z8#lmyS$~|=Fz9^krE^4w3pdchdtbo!iJN3py4d04OjOxrDlY+;epjvy3TJ2nxsO+fE3bJc3T zrfCVEfn1xZ)v;3MN47h62P$iIz!vp|JV>HK8FBQcQ7OlDtH@Ng%~TwxQ7+lfGpGXdXA)lsN?Di(r!cXwSVib=0@`rU*gj} z^9+2eH6XsuoF@Y>c{%ag#_iIp+rf##w3qb(&gSNd9M0C4=JCvPU1aV~Q=(tbbo`Tb z*aT1h!pOWVuafcpd-X<@gQ=H7XR?WuN%%Sx>rs|d&w=T~1$Rwp|*?j!G}$;JV(2)1x4X<74> zZ~8TWg{NtDvE)CY$kna*l)4dc>}4FW%z&u#G_>sgWG@JO*Hcy-f?ew1$S;X0>$JKA zvk%|>gO%%_A`6=K9e1PTiW@jai&@lD>_{DMW2Y=P0%J?+E!s+H`<4Mp;XX>%!no0G ze?$;iGcG}vKH@F@%OpZcq=I6JMtXW6UkQromMvwC;y_g%hY?A&U5k_S zxt7*3L}Fl#+T^O1-MXcoldhJdS7gygC9hRWJEz(|syQR2F7xYCZM*J`S0j^&Vt2$5 zzkZl&z^tu=(T<(Vl&&lFXg@QD&<5!Exc!Bh(m(n!|6YsFN!pLbG*Kxht)3pGl09ZV z>zrh&d7WsgrdQK|#&)WM@old&a?g|jVEl^HJ(CQhwjyC8ug123SF-~+*kYvA>6h;F zeh9j7Ynp`4bL&)4kC0Gvd~Z5Lm7VPL6T5?9Gr2;_@t{}?fNx4`{GC7X^avr)-%vUDBV${k=S_plE<}`dG7IXl9W>2g(aWd!RI{nn)D*iW`V#CNF&wCoSuW zq(+nh^}xLU2~-kRPW84@Tv$u#uuSrU5WNunpf*Elw*ye=c~Q%B@4{Dv%-W!Q=!8@}U1wu0yIXV8IJsWVlbWdze-2a6+b2LZkjbb6Yg?;UKO{sUFM)CZ; z*~9bp`+QqfpV*gP>$k;ejT3a?)qMTni%qShOLj5%`=bV^Uz5q?wMJV@-4g_n0}l{w zwi3$vdRvDZrbUt6Q7@hA#P4J`!Dq=f3R`yBmnup?+O)3h`xpJ13y zK*RPEs3uKx4PsBs*R7u*Y8g3#`FT)bUsw{2zVf0_`e%53u+1RtEOxoqNQ&B|;QJ_9 zgr{|WZok^{5?SMI?_4;#{43*WozRV#^xmfI!ItFo=1W^D{YB{U=#q34{lnlY@v6{# z&bKLnz#Hk(_3<4xfAA^GR)$5~)RBoM*3U>?tQHE|ijq!k-t}-R zQ^>j_!j_WKx;u}o+1>+(SBoOP9D9t3Xnz_1H_e5|C%PSJ8g;pZy=#OF;4o|JXSsvM z3saf7H7eqHte^IA>;v7DRYsGdc>Md%#&C45+C7+G}s5PW9+Gu z87xgR3M^9di5F@-QsNlqv_+ib>x&&jXf(|j`d&Q)EJM9_Q+=watE%Vhu={J@2zzu6 z-cVdBS~q)q3>5s*Y;Ha)@}YTa6Rtm7z!q|(8S@NW2W{(G2ae6UQ3;8WN0K3=q7ZsP z-&o=E$SI2@xhqQFYzS7@xKXSk9|j*T6@imj&TVisE6(DgP;66|Qm|K+wmX89KWNRi zOIbc)pfQ*B3rKKIj(Og}T)^fOc~Ik9gb13QR8Dm;9t-~|OQRK4rZ+L**LthkLJh`Z zua$j+f&8^-js?1MPu$bYD%Yu^#iyA?vY02g?IY*1JLyAGvtzirSrg{{ZixJk>)^=_ zbY&5dZBmcTIt!=DyLW>fZ*WY)C+fqkR6juWw71EV^|7F6;R#yB(Qlo?coF+UQr1St zYvI^PA^X2Ds4v3H&@*}EmG5WC-uhD1_EOj$?U{C761$3d5v^19&40WpW}Gu?LVi7O z$Z*x_4v zxy{jU;{wyLl=Mp(+Q+%rs@q?e(Wk8Lf!dWM8u8jsc=4AUI%pRer^A8fO{Dr0XefPsKb7((zAw8~bmb4i(>yJMs^Z%|_bjFrkCnU9+bVm^Hn;o&LwcP_$o7=lI1xp57gf6L2CJ2t> z$QyjbvVwa|((~~%FuZNzIYDeZKj58YGvK~D3qL|HT8?{ljdKep=e<>#mz{3y7MxR| zhW5}o+=fqfmw`byS*f{$PR(<*Z_u%MJmF%X8mQ53s?C`;lOj4o&s}7BmJESdR&>g@ z5mRWYOJnc}p9eJTj&S5bl98&WK&3}HH9NKfnx<{E`mi@ZTj{!y+#=H^H7igdxu6Ww z4u`I@QbZn)yBFakNODSP(LcC~)rj;ZWuFFeEnIv2*>HA|4%hI#!aHA_Q`#C{rmi(Wh-hz^zd znvYR7Iw!Bi!VE>RJPP(eV-k@>h2#+CMm+Wid-{^`*iqx1lBKCkm}8QG83V@vVbc{a zey$i@P)nx>-&-rDUwD!_pH?xZ%N8_e> zghL)K>9_63sMn*_SEV7Mw3enEp}v(tt>VNNclVNZrJDT5ROLw~vLdi7AOWoWn@IxX zVP=}4&$<+`U!1dFojgZf=g}x?wc%Xxx~AvVZzcb5qa1fw(b{T}CTzYRhaKB$d5VA7 zZ2%`v4{_zpB1s%ySGM|Wn?wif+nrp?3<$gr*-{LQ%+IJFC*f#C;>qKxb@=gm54Noe znD60JxPv7U_~|3lKeXv4=yjt{a-GZ9y(KdiAdvCBO;5~llf!9hx>ov~+peqB~;10Utl|#2=xd@(`cA-%c>;ONJV~MT3I`i&10k`coX?u>1A<}#;VtB<&O{- z`yt9c6^h8gd{1yz@t6QcUsr1Oucj<2sX-EDUYRV!F)qp`8<|M{5Z!pu`(yq0-eu}D z5E8H39sxh;Hr?&ja1&lKWxaHdrv`w@9X--4VY;0-I<&0 zV%2g&MKuy2yH{Bb>oE#PuDdMdhC34cXdEvI@$H~shIj}{9(g>Gvc@YKk@N6*|6ZZgao&;c_EOV?CUQMZ$ZN}KK{A&RmJ(0LZO(u!8 zBaMO}89wY3yckxSHIgikMJ*#zY~4hub-YaxB~X&J10*e?4OiGBk6uYW$oxBr&oVX0 zC(`+JpdT?;fZakG4eMdTGVaDIha8-7pEQr*l-1 zEY_F&gfn|^Hi7)ZfYqNt$|b&ZGL2kb^Sf4gZFU_}qDRf{5NDKYLRN9G+!h%LY3=Kx zZDy?MbW713a%-Sx>D+}fXLnDltf9hew8;*gicfL)SX>er?D*k-FiA#sz-G?XA01M(#2jXq_nUh^oBfbbAkh51qm)H50U;8b z*o$R?T&kqSw8NxE3j1M*P1s7QEjDe~rwhCVX#JK%%RY)!i9HJ^_mx_YU}}KsUR%lW z#2QQI$e&5U$NFoxnc)uCPCya%I;m8_87OY22uCvK95s68V%s}AVW}J)1Qx9^?haKl zRkMIT!7eFM?bWu+pho02A?VN4&3Y&}Q%pR5H$LVWn-72EgvX=R#!c5orNm z36aS-uJ5_-$Hr7h6^@P6$mCqSp}i(!8}&~0TC0rj5(BCn=$iQUeI`h9WN6|JRzg}) zQ!sh?ARspe;W%kL6;O2wQbKDd&XH+i>=0DC2sx8CoNiNlF6(QlFAq)6U}W|Zkfkii7^jk}A1LgAP%U(PKf>I#)FJ4$pN^NL54c#X z0)_|Fc=>qn)D%>wl!F;`9rY5?D6$kv{DmIA6DM-IkBmZ{NQGFhf?b@9#%<<>A;ld2 znOAQ*of$K9k%V$AjGx0g_bEkt0s2DleSz=^vIJY9d_Xr!BG)6YmqV7_JDF2*D}U7J z`uK+MLNe>4?S`torkUbDnNP}9wSuSBFY6UwuheV|pm=E@|POFqb;@^l@J zj1Yu0;UszMC?uDV&RUwF(#k+N3!V1vD4fa85gpYL0UNP zbv>{?i`Q;XO6$szr!y?a3-YwNUlQtRrNAC!vE8c1)5edP|japQ>xz+oLmjb^4FD zll7MrE|m`~2?IpoO@fah{E?P)N=PcPH`OB|6%4P2`Cj1eY8|jEAG$p6rc3#bvZf!aLW`tTiw5z}jizwU0vCjF z@B__GBTQlrG|ViP7DAXL#wA$7-I$Y}jn8K?L!7YM*K%IqYUu`1)>0l?bFwTgSr12w z{i2%+Sjt7L5zJ@B7=#!hG$CFBpmmD;ipCK(+V3gxse-fiID45MsK)lCb|?Q~?e13~HfXEEusS3y3LZ^Q>HmJ(%EorKQg0)w0=?}lj>HY>r;EX&FS8Lh}& zk@vmUZI({+7QZu>8J6x>Djx7SqIMXmXED!JGrGD zV>d@?rZj&mGo{9o<(E7+CXW!b_iDIOo=8WRTOQjsOmBc?B?$k1h@ys-IJPiO#&JNl zMmsmu#GfP{wSkWZd8rkB)Bhx5y~6@+;IO!=`j%d)pVVl*nA-ynC)rql)dn%^cH{SF zSITGmuQe-E;Gf>n4az=~ovPZWJLg4N)}`&Xc7&D=5kx%Cs1}C=17pQCjK>KU3>mE8 z@@n~M_34(GH#q53BHk9LN@<=r-96IRIoxXUSA#d31urw3-Pwf>+idrBfbW~&1nl00 z#H5UnAqr?-bi2LDuAt>{EbbH#Nn zk|+M#eCT_xcm>Z@O%Sv49lDuAOpa2R*~S;1G(~M|5=V}padS@YIsSQ~134<2m<$ig zsYQs?Bf0u9Iq|$lz(th*6^B-7Nms#DJR8$mG|Q2++en!<%XTbKRAENEu~c{U^~bJI zp7uVWTMuZ&*CVO#>>v&y(I?n*uauvLoWLQT@oVbitMj^QW5iaCb z0gu2fk#`eQhS&v+789bS4LChDbfXSCX*|0*w5hfH3zLm_I=C})tNrWhLD;V<)D3Yx zIL}*7`0>u*yk`3=`sHse%C}yq9&CH)=Dgbl^rG=ntH$|fTffsux7~E$m+_WAJrgN! zgy9+;w_eY#KS>Tz@vg1G95-~;B$aO6NPmXaiepD9W`I!d z1&pHU|M^`qrCY_vkMi}kJhJso!d2e141jl0CyG*7f)oVRmS>p8v&h{(r{tCaJce99 zGk_ma$5p+nX`85h!e;hRk_f8m*D0FPtY!sdE#$KG@lktbk?6T4v?ET7jbk~7?pc6t zF^HlJ*({y~N&0SH({^{<@%CiHr-qL6LK5@@xD~v74a0jfi=46}p4FK4JRG`A1V7lc zzfE=YV6Pz-+n}-7g&+v>2+Dg7D09{h-3;GB)wSq(hTXHh>vFZH@T_KZO^gc54+)p) z2O5OMhhI_j;G#TU!i48qW%g70-S9LkmowF@+si*K9Cb5BwZ|YKEW;PoV-=~}`qYs- zd!<;~Qv34}pT~7g(N3RykeR`chdxk;ghI`e0O}qNlf$A$!>f9w5%Ax*+&t+wKmbvd zjKKPQ=E#HoX6rxLFYI@0>@kb}2I-m>qc0xp0o*@KMUwGyGGDW<&M~vQWuu;H1e%*{n2M zc1;rYX8{W6EZ{TwT#R>IO~C{4qWW>iSbW)>xfq9&r;S6Wo~@@<^H*x>jq8Ss7Sg@G z&ty%UVeW(c%CiR0mlD_!@oX_%{BR_92Afy}B`U$b4#nysFU@3DG|7gNt#OSFt7~@r zc1JUVT&+5GLoaqGxruc9FzxONaH0FeykhfmY%*|!OR(pZhG|5p`cNq12366OVXOEj z=Dn_IkhwbUrfT$?0*_?M1?hV7YMuucdOe}|PXO4#1TA5>l}BS)G1S#}3s1rg5OGdT zA%0zR*ulq(Ei6KC?ylB0hK=J`ZG!-FtX@;zSsUeBv3Sj-g7+7Oty?kRm-{5eNI`g-I-1eL;WJ!Opnm5lY!GD1nP&%b+uh zKNq>1mFXTe(fUg&{0Hd{T?I3DI?=cqfVRuq2%G?TLnUr)iHKSj3djg211ENi0~$4( ziXA;@<|o`g^rz+06D^httG21T4{IP*Ch!~*DjJPy-@M#olc#eqld*q_9jD~5D&5tG z;@f@!E)d)ZLLDZR>*P`61TpF(o^S_!cBs67KQ#E=ZR9IKFg5 z=`j2a$V{5DHmR_)lC7{zPQ1ZZx|QXk>OtItoXW^Uc6;&-8j9&@+!vEKxb>PgvtpnQ z-J~{FT5PJ3I}2~cQwr_GdOUYw?WC7zk(k};FM<$k=|abFP=rUOFTnL3wJJAec`(x| z>~0^1$;04CMnjKUA5Cu)_ooKaXG;C%>aLXRNZgS!v=$Z4>k{ANh)W#;;p3>yHe{F+ ztEP-G}!(hghC&TynWP&N}9nbOh$ zSQq{aGjy)ZvOofxP4)S0UX7&bZeg5ScNE#4dlorFSyS5}K)a-2M2wTT5U&jmaJ7ts zGzOdDSRqZ@nf@5jx3coQj2h3`hIFb#SJ`kg(H_oWKcQduUiVm4_5QoCZj#*AbNcWEY2--W1gx~;YT68F6919xsl?G|?7)9#} zX+LDTkXVVc$RSM{^4~gmjP}18c z2Bv`LdNa17$z={TY!(>*A|J+=C&MfGM9G}4w3jt07;Lk!YGwWl#i(Tkg07T7EX3Z6 zK2NgDT~h(PeSWhrph=!q?i3p`#tix2tEB~JaCdXUt?(td`$(f5oJ$ju0#QSc4Q`?Z)fBK^bWD~{GLJqqOFiX<;wJ7^ zcs5Hemr#VGnh9d$k1mZc(vWHf4$z!@BnIEGg`L=ir7}Cmfu*$U>t{oCzgaR` zbDR*|+a6EL*&V=+6w^ZKBR2;C)s<#`bXw~uXUq{TX5(9mITdbRX;2 zMdD5TE(Rx3nJiX$PH2w1ploBcU2Foko@F`qgexnu{%B{CvMKBUwwB%{YeMOQOmsU42<}pIOs}Wk3$w#mn ze!g1La8|%3s4?KtsZA@j^)Ir~X*022r=e{1-cBrEM)shpgZIm#N4ZDpOq+|9)YZ2% zkK5}EVQ9Z_i)kFBGM)>AtVv?Iu$r!d%l>FrOOfgLdk&{ZjxZz8C_sfF^5rHn_xbeHIi5qeX$3;1qVOPnIzKtya!*)xEp09kJ`C9?Hfr7bJ?R2VW+8 z%s6j+j-4QCUeR(E|52|0fielBow@YDZYM}KR{_>p!BPx~b$I3dZAJdH4j3KD>c8^gUAW)}Aj`P4t5r{>N zV{F#^(#j0W_d4oMVC8Bn{{)Ie2E#^sdCy|5G*exa4tSRKJbPxiR^xKB+$Cf$`k z8~q~UN6zyB833F9R@z&tUnoi9InrZ=Sd@q?o}SA%y+y&$B!5BJga(%kr;6U98Y|Cj z0Y^p5UB~TJoRPY^CZAa`8X8!+1qSp0^P(FzPNU2_N}lYDcsAf@@4Q_uuIVSO*quKO z;nSp6rL^+!j2LbgIlX@o-mV$GFIB;i1_5jhX||Bxnh7qQM~lw>iqBf#CXs>zn+th0 zgTx#3eN9&;W5zTIYxLE3*rX$OzBjrmNR2?J6VfFjeS)TSqYO*&>R1O&FC8osC<)vQ(!I zf8?8b88*ER|+*Dh% z0IGG27pv~nQQD3Oz{xLE&^6h1S=p{yEBow@R z!z(mgilLZqY+`Yha5b?v)xZ(AN!Z$26=(}@NeIjW;RIE;*a+A7XD}Lz6|Vg4ZhYs| zJFyMIWe7xc(j{4!MYb+Oo<_-UlDxyq##hwK0MlDGYyYDlxE(({P-C>U)~$0c@&3x% z{)<{ms+OrOSBUw}_C;(IU?`0|t=pmLWv}pO3&JwPEaFke9nok!ltgS3UT)qG;}z+W zGK{sE6X|G*BvDnWYP_lWNMozyv65!fwOmvV;TMje@^E7Q5RTuDcXfl|bPIK$VnwmB zK)=E&GRQ)|cG2szd5}7srQSbGhfNwE9<{K@BxoHV=MgbRD<~B5q@d{K?xm#9AdDw- zPumqnJ71&@L6EEan!_eYn(N3=?s5*{IZMt`@B0XJH-wD1u-HD zj+}fmFkWoR**c~>t1Fh#76y!Fma-VM{VCq*7RJR_yzlRdiN@;}yOEl2-lD^dIFGV(?I!2c}b5vd; z7GBkFcDTsO&Rw343CRj)>o+cl-6!)P_HyQ6l27j)rcos{C=;AcoG>FhPPlvUwfxRl z&-lT#`NBdXLg-=)^w09szZ{B*j$E9?F*{W^B|kkN2dx_k;zHHPj-F9{jx%3zc% zZ7CQNXZ+J?rTgV8ru@KS%-cA&UhK!rROPBXd{xxixsIa1D%*R4S_{b>Zb1Sh-s4z1 z@~)}&%U2R*Z(A*f5mNZ5MJDRNT8{6DB299!F>+*h32DnT>3tKlfW#Tp3k?-j)B>ZG zf;u)uV|+87hZBNP8uC;pUto_9{b1(F$ZMcq_aPcfwwFhJsUz0|^!Q2Ps2OY6Rv2TG zA9)mYN~*&cux#`@budvoGIVf8HSw4IIie*_LCHg5N(M(5tE-P$j8ZpxRaDC^0!SJn z^c2`ii*PuS#OpKG+vYGzoXDz`>oTQ~d&ExPqMX(ylIaNh2Q%^V{HudaqJy+Lz`AZb zTLz>oS``zWt&`$LV%SBbs<=2^|7~4-iu~Qiv3b{wf@4a3%n{69f_A zm^2xnYFVu#;AZt7jC+bb`X(zmq~O%VvHe5DRTqjqRZ`#{8M?!%?l_wl5Mwiqs6ka< zu4J6yG`D3+g!snEa*Cn_;l_{Uy7GKdR;7)H)ALzcO^MD#@RTt;y18%&W-+{HY49>EH} z^AOgJ55k6xUtc1#zRz^N4AEx`T&lYTkQmtCgrKzBGnM{rKNw{-xGDpar_? z>5B*kUFtNGd9v@P&5xV6Y>U%k?(2oIqZ`%tRIwMIi0UFSh9hl0w~nG)WFlmS4g@d~ z`Wtz~+vw&_rmE}&u=Wgh*7&22hV+*UF_`hxZvfm5piH>Bt$@IESH(mM>aHHHm8mab z#t#E|sOh}2^T$CJv0O%Y?QK;^`D=`Q5Con~a9IQQi8ope2}jJYI>n2O7DuxU{90r% zoI9e|CS#sZZv71WprKj)vw6;zEx|ffwp0BqAg}cx7B6u;LlFUUOydu3j`a!Pt7ble zR#Y?N&U8CK03DWRuZH{W*sQ8weQg z3fwBLPQQGlGDoa5P9p1NH)bA_!R>-|Y90lonk200o^blH#I_hrjrA8cKk`o5MG-Oj8wm|+<=eUSCT39ix9M%J!3 zt`OmqUo5Dx9FZf)WznvQ$DY8eQFjZ`Kptm;=Q~U!QetY1vBHuf-PzEfJ`k_OHikvt zkb9d;ZH7ByzTqxlrT!gxq)B=N+!y*Hh|a2I(FF5_*@5a$cgmr4i9?IacrF=1)`g{I znE69llB!{brCbU=oAJia1W7Vc$aCaq0v@90I5(puJw zI4ln!s*u^4yG6@({HQa(NKx%kY-s7?g67Ibp40Wp<5B77DQvT%M%a=SceU2BgOf(_ z3H)Slaw_jB-}Yk~Lqno7G0^^f%y)NxeF)@sJmQTxCRwFhtF_}HwWW@ROj`sLlI4>@ z6!azkczvU8o-NptEw9p{)|RYyI{O;R>LDl>R!|5tQNhy!U}bAVb;Wx4VXu=|exO;h zYb%)ScogVzS!OKmZpxTrli-MITX=F&+voscy5-<>$trVjkCB^HL35X+@=WaliBb79 zray#qhcyz!CXTm0L7a&>)qP&=%6XL!BYhjpuq>S7BWO;6n7|cYIWEstvP^hx8XXK5 zY-FVu7Xih;12zgX#)Dq5^Gip^0OV>?{ITt{Nd6JuZJpI~(TFd-op)(!_Ug#VZDVm! zo8PRBI4c8s02K}ggy4W6r;)-6+!oNiY!1G&Bw|wSy`!DIND&33iuH?lzwrd z!gxEMHH60WU_A}a)N38I&(>0PR+>}p+5U+v>slFMy^C}KPr~~PCiIF5c87W61VD#5 z$0x_+mMdN&4#%&UA}R@M^vxr$GRb?qtJdtd*&Rj;k*DstJn*A`Cqj)Jzgf-O7ZX%D znC6z3)OgFa=O6a2bE1udCe1*fN#vSUmz>?tx0=$m=T7i)cG#2G@LqpNC#h+S9aaIU+gR!SI~YAy9d?qu`s*tS2~AE#BmXBuqn2qseVY{l~E z*L2b%CW%ebUCHO}9HHbN-ag)MldqR%DwV81QvPRBlVWm*Ks))x4OGk4V z&~uvJzAzs$(;!E{{h)NokS+%l88dCKlWRpP@=MYiFlW<>^i!tk@9bsLraKHS33kxR zcko0&9D;L>(c8hXJS~`B4?ACCfCPL$rDx)7lC#^z_Q}@C0_ca$e~wxH)ZBYZ$eN>N z7hP1k1F?h|<=c-&k~9|(=e1;q-GOqZgFjAPGlbS!E3VL%2{@P@zI~}_QdQT#dBsk~ zQNIpkq-MV0#I%J%-4XX`%q9;0{B5u`Y;C!0b$I)b);_N6S|u+wmEPBE+0=OCP57zbI$boD z=e24puN*(CarR_*=tCv;KbXHu&0~Yx#o%XmcAGlhiK}}`J>6lb<@Z_>DiSg2rI-zD zZT>${fMv|1j(@!3Bo@|L7Gp$k3QTZZi^@bwY`}if7+WIqdaMu_^m^(TsYWSMPblEm z`@8g=fOxV0e=xtA+nrW_tKrxwNgrLLiMH0DznF-;^41$1+eN)+)2qbutU?^4RvSd# z{CTysi@8p1!)Kcf@?HSK09D!P{Or_8U(G?w1pH_tn2Rg~J84UjRNODdVX}jn)#dTC zK6yznskBD(rMNuX3aize2+G?noqw7mj_2A>DVD8-yFAkbAdSlZ0MT|$S^=uS)I&jC zvNn$Jw(;2PQb|Xm0DA)u8-PrAVvx+=nQBjq10V69qTMZW`2^x$L|TEo0x9$y9J8ot zt*unbs8K^u$IzmJVn&MTV`HM&!X)V05lOe_(j>^x0;iw_mpWpCHXRWkkw^nG)vgr` zFL|74zBM@E`CYpSJDg+ia|R3sR_Nkq#g!A6U?0H=7&Gi(t~K~*7lj|bdNo3X2F8M@ z!iR{yc2RsCir?#9O0kKP6jynKsP&csXd>0A7+C0&qk{OFK-fJ-9ZueTg2+PL3Yfp6&d2cs<>G4|?tKg#-t6{|wuO|99!K z^LlsN_fyoP@9uH89kVYR^5VBTJ2^JCdvo=n7EsiON%0@d(B|&Mc0pG#rj7*ZqtEN^ zKrqyR{h@mc`TFDXnhiW`>TiD%$K{{57Z#cb5K{{ z_2lUL+vNmwk9RY8PvXNY8**s&g_Dx<=TO&+_*uZ4SRgbY=K7P>$K&!@T>IH|ee?P! z!s{FK)?=BlrBk~Fmu7bklpmQaT`cDYeIg`%M@tgWNzV&j10`kjSZ^20UkZ0cAW-#d z!a&<#g;Kd8a5SCSkq-jcF(l@RnpHpIcbuRo zKCD<3NYW7Y!H63X2A`o=*y!8D1`N?PZP71hyZZ`Mt+WJjWtk(9Sn5L=3Bhm%odX&C zVK=_qTGS%~CmG?9$=$6=p*ipYdRVB%x<}4Ynn+LXz?IO^5LZh*QweQuh-!%;9t#F^r$oiF*Nt!vTC z`$=ljFAsxE1 z>X}wiAz(ewABnI?a)eIZJ%s3+|7xyrTZjHn`RB=NS&fOff^FlSmTWBxzbgD;9PbtN z>2*a(@r=?~%L@}cDm^pWEcvZO)r`{gOfNuelxJBDm^7`(&*xt77JH*mehE!9)kh1( zqUALil)J(l#l_GrbHY;A$V9s%Pds6Tw%)}xVVd2>qJd)NYTQPnWO)hTKD1UMv8;1f)rRYVRU@Ll z)xWf;*(V04Q+}Ov6u!`XeKvY|ftc&2HcD#J>ZE_d99sqN7(nh2Z*g*Z_LiJEF@7sA ztwr2y%UBneBV7T-pV%Ekw6eb!78|DU<2_$&E97ZrYgG;n1Jo49|huUy@+8^WRax^tN7wJOe#_k_L7^?MIM4p)HV4T z)4C^tK@4E*ryi4Y2jFJxaz(Hm1|-eC71ZD{Np$J>WV(+&;%Jub%DN?Ra;;a~OV+K> zw(H#Z$v4n*g=*QDv`pi|H@~7o_`UU82DztGJ5knRAX~2Gct>SJ^yn|AD{fEP>+e-S zexRT?8;)RP6^lNUX9X@Bt^;yYAN{>&XhIvgA{9;mNCGHZRDRxKG z7;RQD^q!Hats1K6d?=tJ!q2Cg@GKRIs3bBLAZef$J7K7H_?F6&Rh~j|>_V@BtJu@c zhDgQp)k6-p2BFCMV#LPzjo-#5I*8S^$7C#lBHv!)A;#yFyQuu#g$5NtO=ZzIS9H%Bi^}&&i;e`1qkm64cveV< zs`Hu(Ug;$+qOg5tk!M6;=_YK&+bYIbu+~xtdR~%P3TG~DKe_LNIj#b5@wz8T(+div z$mb(}?|?Sl|0MO%qaevkPGpj4T7%=br6N(#VCk?Vsj#ET+((hiqj+0H<~yu!vV0NM@SS}F+jE3gbmu%UuoJW ztVz?qJY?;IWZqf49k3`W(iA8R52nrvGQs$?d`GNmY!&ty3`Ak>h%kcQ{zLoO>8-wm zZnX1)T69W6eN*zlVuvzW zf}5JpuoS&W8Eig(aSX?wX&)`&KeDcgr!4Qkzb~Bta#yAr(eIk&X6LOTD`<>-&&Scd@*?(C($b2wsCA z8A4V5%x#=NsZ1_s3{Zk4=^|97bDp2<1Yra7P!*C?g(0pJ8Xy>}`+t1?m#1 z#1o^`ScST3MtBFB2`mMDN5@I5(8cj5Ff(jXM$W8!w3SqXULW+dX*OAAc8JdI7Z5B1 zPwGgWfN01;({b#DX!iWi-P{+k*pGUo#7J=-!h1s3fOn2A1C=qnJ^n|#d-W17lq=W# zxKW*V`tGFpvDcx&ac1XS6ITMX45d&qyyPjhv#)(QEAV9fVBatN&DHtwBzq+tPx7!# zO%{DQ63ATWh5nl#^u)7V{a!uu0~q&C970nDihR4NTb`4u3UQ+)x(c5M7noU@G%HpG z{$9hfcaX(`JB_`U+am*DLy%rbqtbNuJ!%tmQt2`2^|X^Uml`DAgoVu`=}SgD#}CJy8ommVgI(-bQZ$nW4cju#Pk zPd9lods~r?5XK(5w9p*r-c}jznTD~sxPoO5hKZ$oe9qd=hstj0%O;P}j)9GNLy^eZ zMXuldF+MePS%h@dBZttArXFkX|Lv>^s=A8DuzclMCF2yQS|};@ZjW(d5SSqoa+}FM zNYKh#b^jb^xB6!>O6zC(upup&`&ej9>rVvO@xtfoGj+58uL>E&vxQ!c@`w{nS->im zAoXQ{duU}Uu=ma4F3M{*kCSZW9oK2&(w2i)0NnBWTPm-6!0+=!AfI>5HGzOsX`-{^ z-M^Zx_7Tp=TH(`qP;4xl&G<+Jy8a?9H>>D*tS(bCF@;{X&Q$?39S@Z+ zzfrr;{?(3_gR>6T_6liHsE2pSOCJ>lUEyStdDkB*Q!t^`Epx`ahIsM=1+&)=(~PA(4kr2~Ri`x$v1L9a zvPKTJXG|!WDydccV<;Hebz2Im`osMHK`Q>=SiNz=BQCQgs@=|~tDbK5&7Wc0Z8!D& zH(oX#`&1?i8zze-T1{r2AT!%N@9zb# zfeyE|f|T!I{@|X;Ze9HA4_%W@ccVtVz8@p5tvxT#%Meq~x&Ob2!PO4e?QrN;zTQF0 za${zL$8Oi>|6tY{M(k^~zoeb~nOgkd%>FGRqM5mNz%r)wa&`NWl78zT0;NU%KY#EI zl%ltxd^YM6+}Nn$gCAN4mqYm?C&(x{^}JF0CNT_B|58)0pu+St{q9bd87$s0b>XgB zVD?z+Qdy_8oPWDoXC{RLHzNtEk=t{%fIHkUt_sh7O&svif85}}bw8*R7Y_ zbd-}?k|QqG*Jseqh5 zv%;a%Y$wXVBQ|#HJkq2hybl<1#P97OIK^AN99XvP2;WnusLuAfxvM8Hzw^8rOZUtQz65Q}=&y#ylcZ3R+qh^?mVT{nrTVMm@j&EX(@ zeETWo>BVE2c_4#oE1o}Zk9~QaEu6EA;m|$$2e(|q<{QGhsAiFoMYX#_zEES{z$QyC znOi6Eu^Ip2R9PIAnbvILy;P(fgvkZG|EN&Hx`KDmQ?bnUBfpH)@Ssq0X$Iw>dN@z0 z#=|CVkzKspA-zT@9M1eBE@D5NV&4+fAv1t#p8oP$rT|{2*+Bp$|5_4O4(^|9fvaTe& zV$+)$o;z@1$^yv+URsd+WkLH{NOpRP6?X+)fv>q7;n2IY2BFR4H7ZDC2%|dXFeu>y)Ap>S&+T- z(|{ev@#3<{*~Pa>SOH3JwIKiEf+!HPZ5Xio+6L<9u*vHPa3*$fdb--<&9`1PFSZl? zST*<7vf_$|3!zVeD6^;T-8N6_(lN)U$@x;{<4f6d5du0A`t3+jcM+Wd!RK_wqfw&wgjs# zQn<&_ePdVMSO|EMpJA9J%=@$lEr9200(B27fwJ9$@xhOBCbB~=)qdIoxR_OAm%_mBD{X=D=|;*IHI zqgqO%B$cEk^|TETO$WKsmW&035YTjyqV(m=Q68bEhdaw!nj{*6Otq-jc?Z%J_y*4R znMKzk$(;F+PNARiPPEv6u9E4BAT_#jQ_mj?S&+&@Z~=vA*e@(lbe94dgmaOBz%sSB z@)%R_OpBmGs3m?=ql4AYbZ+jv-9JMBdfZb~uLcpXT^oX^a>HpZo8tP$ug%G=*#pxsVQ>4*klZB2}r+rkPg;fYIMfJLX(L zhwxaa5k-8f+CsJN?jJi+Pb{A)jglEV=hC!*;MJqkF86pM=^~^&iDNPA!Za8Euh{b0 zLO_0c{($oD3mh(Rw5zX4zun6f9m4Q)a)sm4Kg}^{@+gr+>`4qX^;5k@9pmBF!RXIr zQLRmW5+HAwZ)1i4Cn}c(I)>#M>16lcgRk(J zZc!xjPX7EG_EB<~{MhL$WRpT88p;SsQ9R)^1uDBo>Ys5|nJkg_h@GA3NEVK0(53TK z>~x#}GxuuR;8a=}E2%^p>rk=%8ZqV=rg*YnJErRQPU^5$7`&OCwn>9TFGl68cOdP& z-rtpVED&b%g9F7Ll^WfBX`M;r?t4(r`XF&-kj+D~!~H&wd~bKReM>rO-Gn?%ngK5^ z+2-O_Dpgm&9jyw-l_Cb5UL|QxYzN60Rmz3t9xaLXge=)~jxK}8VPDw{Q$ojh_Nj!K zVah9v&DzpL_6#P~OlS%0uhR_k&*nrhL=@T75j4jn1zMd|u)hd7QqW*zQSW*p zT`ce$9PfGnfu3zP(DQ&*5t)vbe{zk*@~!9fwVw&<+3vs9Zz?6W%U&=%m`^Xr@sGNZ z%{O}je)ap8w@Y^h;*V=2%g72>tNq@Kcb%3bp#h3qiJHcsAk2J>RI zLjCT6d5@=eTf&Sy62=|>n3o+ig<~Nx8d-Pg^$zOa;)ywan+BbB0B~!6BVSjLWGtsY zKjPY&UcS##r$hy#uMhE=vpLqZ*E;+3(RW(M44rqv90AgjWZh77Wm<*a;?s;h!j_yB zCgKVg`4)1Kyx@Rw#u3qG653lE_Z}_;n!|$!IzX->7N||g?W1$-Q2)WDSn@VMN#AnF zbCjR^S3Z}gu`QE@@!wYl?h8|;I>3Af=jeDDhuY~}BNw01iZC)xCHA3mu88|@Aw|5H zFeN5MOniU^g|J8h^$9I2Re|J&WiqPD=c5I9E%o}@j0F1Exja_3cpYr!nqz5>b$i6 z{8q?4*bse05Y?WcPOhccjyl(nxSeFL-XtN#-0y=YYr^av7XZO*z(zeBlOLi@_`a_Y z?<2cb7`WK%!Kh=C_ztit`<6y;7vTTff>xGahJ!?V$WY-MU1k_n2@731=hUF0I+gLl z1T;==&C@Rm<9mta8o#8)H4RxMoNDxl7&i-?}J&8Biy1 zs9;&%Y9Cn=mGmH{mrZ#67d6cQ9ksI?NrW!4Zj;ZQSg7OYOh8Mw!yfQ0b?CFBrJMe1 zU8!PFAZ1UbwY5|YcwWov8WZ;_%0?mW?Cld$lB8AEfea>hreL6x ztKtQp45vI-7Z=5!iC>JL=o&g8)vBtymyr#@oW?|foKM(og^xY2&S8l?FVIPp+~`}E zDCgwhVmaI-XT{MZ><@0^fxmEAe-of@nUQ%==Ql!DPpEwJ4FGK%98TnCF=hf|^{reS zxH=cGc&lD}L?oer)zBH|XHG}9!uz&8=x6f-y=13Cn{>hWG%Znht8FOh+y+xCS)H@oLM7J z>lup}ps|NRBi&&TIJR7xRs%KpfPhN9`HmjALhWW-wmRSQX@)+{WR? zHMY*8t<-(%A+@os^Dj$1lchfk!9KkPR*vA;uWGvHK?8_cxdtSnKdxV>#1q>VZiR?* z1KaT7b?L75fVIQd-v;5{y<=q)Acw|TkS4ZZr^=(x`o*5?+~~F(ll{xpsOw;TJK3cP zE7tU)JPmF_GC`|Eu=deGy@0gz+L7Pt@{DtqV)t_WCwf=Kp4|MIrFC?U3v=c88WHqC zTm4IdlEeKR@33&%imVU&o*Kn^B6mQ|^TESF`6o-xD&3tSjpZ00@A0`TFSVW@ASv*d zCYMHAMjvW{DW@4Ex=^%KqN*kOUeEj4asmd{f`}W*ijdV<3V)at>UKSUB!V%QHV8rL zXElb(=q)};_Sp>nZ#N%m;)ZUnTn3~%d$$%T(wt6oPI7DOpc^>^0gUk{4tAp_Y46uE zOuccwRGU^9p; z`^~OyU5o8l&9u1Kd#?0Y(1Z2*_AYKN`Vv*%|7Z37UrD|NaP%=;Y4ZlSq8erz=76i_ zrZ)4EPTym`{wqE=+~8*F0Zbfhu)PL8dh}ec0zyxIlI~^#Ty}PJ8-rL4pM9l|aC-@Z z45;P>Kx&$~MS%z8cnQrkOm+aDpQ)AvvOc!M)*0AD9+_84xD~1z=2%mFb1<+y*N$cj zg-jW;isIt&{B8JcVyuOp!}svDn&VOLZrWf&+~}2F{1zc2vpnj>Ix8xhpV94nQ)`eJ z&YQ|IYfNWAQw8$z&Ef~*1^)KBKXpE)xf!< z3}M4c?BA78eFH_&T!_LQfFj*?9#6C;Z8DhvDtczFN=m|_wpG}+sx^vSQ}=;Qe(%YI z)=)j#Q|M^Z&?m4jyGm6Y;;%d)yN??qu^jP2e zQs4BvB5qVQ7i4>wMbx-;o2dMqVTx>(IF3k9TmqaBNSJoc>gA$z3uKy1|L4VqhEDKM ztbK+J%z6>4-G&{aMYIRocAr)w+H(0)Kp0XWt|_z>@ijW>-{wnZNIr=~FU9l<{Mb&1>3G;~lU zGPs7$jYdwIuW+sQR;XWE!OvA^tQ8XPf%}~hDJ@BC)0CfmZy`G`ct9wj;9np%AQ#|x z`*(43XQhvwa#F8N)Mw)(O%33V_}0ZaZbJGx2ssQiyP7kCQoqxONZ$HhWiM4a?k@V+ ze(>Br7!@ZcUb>icpShmuvQJknh)4XBS(ByA>3-8jJ6J5T^l&Qqip*!th}}xXSb&8j zgF{=7y_QcR`iW3rk37Dy^9Q!!R>Q%6FhWPB1g_N6FZ7`ln{Gn~TvHH^JEEV2gqiv_ z3tQ##D{S$`Y)!V&Vjd-N#(&)j^p$w)MSJ=KKs&}66Pi6DfwKSW5G})W{?{Qc!VE6{ zCZ>;-q!L+a>ZjXBJjR1}!dmP9Ux$bYbxuz#IXGziSe!Or{xRrweRNnWR^y6@vA(rG zv>25%=Bz6Keqr&f_w;!wT03l4UzGvgUC1%}epLiBtEfoYc)5-{H|Y<5UB}eR*tsVO z2nzI6w^C$y$`*J<#F`)I60%J|NCb)EJNK?xw;87r2l+^mWdb$+tiUQybdE8NchFBV zamX&^RM%`nWBnP~Tr5l#)moh|caYQ-%L6gBAr%5e1j<9a>-}-?(JDe3~uvDSk60QkQm1-IL{L90eF3TS=>v_m(h; z86Z`Y=$)@u;+~iP4@YM=eT{~gEj@mra$T2-;{x&wx09uRPR7YxGK60lNr_wPHrar1 z5O-KF?pk^qW$VnyTu1Lo+8S+=Su)uxD`D^gz`5&}RwvEZKZY&HKavxL5lIw|u@s^! zJF->XCSek3j>EzE9?DoQJoWZJ&20wUw#;9#Juz*9m&HKe><6KF-nTNE7a*wed|+DN zmwGcP#@PisPy#DzrO}Yfq>j{ZE8P47gA(GB*u`$XvAw+l>d~or&G~y?9Vj>C8~Z7b zk}30in9*!{weI+q;H%Zyg>jMa>sMKEAZ#HMX#6;tEP>el^Boq>Co$PVifaIM-AKi{ z;5^Crxejr>OHwbxtIJ4jXyt64SEwLUBw5l}$ErV=h%`xFM-`z9 zbS=){u{+9BPdG2{ z<9c`tj`@7j5xYC`W`@OOCozk^Em>qGFTMUo2`}w^L{P?KlnCc{o1W~-i^dd?v!sNRj6I4#mR!^|h{r*_UDUAP?SO&YG8Osuqt z?mR&pjS8=K1MjYTUK;`*cY0T1SlKO-XZ<5zzld7?48PZg>P$E%$1*JqC-v>_cdY({ zVHp0Pd_6NbyL|o<_WusJ&K8q*Ya~%`)(#%}`k+ur=WBCkskn{gW9@b1th177XUj?R z1eu?6CKJT=t7>5Mwj^4Ct)!cHfO&8emO73Uo9cBf&#O)Z)z14Ow9$Nvbe0A0o#(BS zxC(B8k4S#WM<;c9=ngnz$Vz{6KhOdj%GCd!!0|nwka~DI5RY(089JB?ej}`xIny-4 zj#INza|2IVe&LG-8)fjxAEdR~uA|w%SLkyXwvM$5dYx^O8)Xs(hDykMbahv+-MinaUAtu0BcsN_~x47T|Hn9p{XJ0U|UgBn$Um?InTa?8tBOtS6 zN=|w?JpH6}Mk(C{$7s%Hw1aBC7@m2yK*7n(S*&z36*&g27OLbT%CGu4DIRQv$26wefY*?}?EXhivOk|Fx)n2aWW}!rkh}l^8qm6j{x#QwB@WDCC@%ZJX8{_xOXPrO4 zO)s~$dpM4oMLN2kx0-sM*qr?yzEGeXz!1`59YY&1RBG48+M|B}+sbrL$I|$7&CTY~ zM&Rd+hiBjW=hv2pu4jYpwWjTdp32RK50MY8mBB&YpZ~(uZJu48b$uwv=nXPWs@&RA z{6q5c?%?IV%-g%i|K9sA99_+Y$t}Y63v}z!+h?uk@}Z+62*)|1L+Ihb?0BGwH!J=)qhIe1-sx`1Jh#mApt zJD)%QS@Yj~tub|6x%A&!aP}|g_g`E1_@SfwFWl0F*Q3{F!SwicPu=i>^F;}aF7pTD z`j5Y6N5@vzv&dh#l*NZSKlsZ)ql-t8PDdE5c4MO_sQ*(~cZg{(FMYYmEE3(-ad-}M=SK%uauEjcTI5E>Yyr|_An#*}sHKf}v02cS zXi~#(G>Uu#uVdOnMZZRblk3%Hq+#Oh@V&Tl^0!-%p@!HUzN0scGWeRQ!O_#mdV~D= z`~Hs4n_I4tmou-P2uY=}ZhZ%**@QG#&@v4{R|qX<<6I^`;%36JdiCmYfJI(?Y_6@* z;#ytB!HE;Ere$th(h*zuNT&#us7?dD&d{<6M=kk?{ssBoNNu%9zlE3#IMYgSj=n;u zc=`Tg29k=Tn_sMKv0N+iHe1VBF-~nX#^9+ar*}wE2==-iu=*W=L}M0(;{|y8u^mNl z2+PG*P{@!k+_uXO)6baGIcCVhYJh5%LH^WD>AaU#dTKc#OA}wNDTR;hLBYu24+sI126yw!)=opgevgSFUcA}_e#!j=$B4%CmN)=oGn;~YW;pv)~wr*6R zfH?80*Qqfvqre1LlO22v>DZ)$z9YM zq_8c5pOy?5uLVIUI9?NWy-nE1&)xNB-IZ33u~Rh5N+iiQ^x81}C~73}z<9C34hvLdR}%aQ(r%neA`YBP(twzgAw-wFE*L<3a4h7#wu}g$tB7(-Kg~&2v=8*H6}jf z2k{E%Fnqf2W68kTUMqbOxN6~v8XG4aQF-iOJ{>5d9$5tpRu>SAa=NE_=pZ1gjGaDi zF?wb4cZiH-zcogn2HaktLj;se=608I52_8xB4{dqw2tr~ql`Z`$M|PXvNaP-eH@-8 z%CTrgKxMoMj^JK$!`9)J7yVHNAIe&U0($eb3n?yAjF<@_$t_CSXqw#j2R@kEv7DlV06R#audfnIzv)?G9MV?#67mej(h z7)@p)b7yv`;e^-O_ge4uUK+O!y_ukEFzQtf>QiceJuWh-G&*C-y9-;R8({ zRk90$lLfIXBL5M{{q1)agY}CQC-1JBsn_(EcjeYQ%|*oQ?|MxLzI4dE=ONlh6DM3z z5=$kL_lr}SiWjhnIk#x^lE~{|Q0Z-=n+Vd1oTVNU~P)ci9g2{ip?imEP;Y6_psqj0XSn=6x-94QPyB2?& zv|rAS>FboZAIW$l>L!I|49-P(k06Cso(4nWtpnKUNGx*R=LDifzvO?5D)6 z6ukx?mzY`VSPI$eLnby7T6?qwa}GXFF0!d8Lm$KJn*YK9_Ao=RtfzeDFqE(IWd>M` z=47{&J}|(9^yk$VAfBo30b$c>l2IspQzljb+4;KP5WtUG%2^ZA^-m2``h8rbpEEW# zQb(a-fW4nyYQsr*b_4+jO+<`J;82SLdXN(c1kxG19!P$PwBkE6cSv_NnoVX$V-Ko` z)w-@Wel&IL)rd=5V24(YU!Tgvr*T-?dij*zOXMGi9d&XK+<{GOFeq%Q zjf~>>ntvT0uq+FTqQ6UQD76HS(v7BBPe`8gt?*5$CsEKlvk12^!k2*aExf$$#7yP` zAmek|EJk}}8=SeGs$ciVwEN|}2Ky8vW#PTPhg-MS7>&i+7}^z9Hs#8`DG=#H;mH?n z8RAGIqQh`q%es0N<(HTLq|YRjrMHB-_O!OfZ4-8*i$exj#&jHHG_)y-ilp253s*gr zEymoh)OJE_r6kAd3nN!>OYM&WtSu-pQews_$MtiJ)>#k8?UQ9!EHGzuP-0vT=vbXm zN`-X-Dys`wJJOPPYAkN{`U{vuua9f%T@m`)hGT5Nb%W)umgL51PJyNiY(Eoi1XG4I zt)H$WupSp;hDo{K2kJ$P7BL&mD=jKYFB2-aSgS1ugP{zzu7OdlP6W@N=@v=3!nfB+ zIX6kB1=EAV_Jw+!w(bRxryC=Eba65pvILX&-toEN^>AT3z`EMGH+0;Kyvp%0x!Vn; zWv!kSV1jeMG!M<;${?rv-4$*6%E~jXi`a9E!v4t8*2B+1fxBw0>{6fcl?xtI9K=5l z*!-3u47_c^pDKEMCDhS(ku@ccH$Rb4a)OOynV7R$;-EQK8+rZXNRP7FYMp$7t(~l4 z!PB{C+`)cJ*+wgd&C@LwZF1G~tR~B_k>7UV?emjkY&gq6-;z!e zZ%C+p5^{z`6JC=HQ68Q{VIm{E7=vOKC0S~^56ysIddw-DirBh2V&LO;%Y{AD=WOq_5(IN{{%%!~v5#3#Os44YH znpr#=bZZeWG}(_%5(GCi6?G1RVR!&O?mh3Qf6pt=NW0L2^`wIf@DIfo=XVk1lA{py6Sa_%Z$w>Bek}O@K zUv7;h$5=zji{6=RTP+IDzL$Ac;->f3=j*fCUyfu*2JS+aNSgKz*wvv{m$$AO5IKU@ zT0INxan`SrVL#xxW$4iK=9D&=-qMA85ge0!iA6U4JauklZTXyhkuZ_8gJi^rzO>|v zH~UjFX2N&FYo6blPj7uu8s`v5is=*`0^Au-9-fR~!uKy$`NKc}lxFky+8Kx3*m&+O z4yF*tg;=mt!o=dWsC+OOvQLP>Df?%Me2`5v%2dYaM)`@f7QCcu_4t0V7OhBDkL2P= ztl&GxL*oJHUI~?Xc@i+Zd(=ePi0w!XGgUJ%RWG--O5nevLYwS$;hIi}Hu zFtwkCUw(~ll+`DnvXLh*{~B|l89f8h0f!wc{A)@@BlJz->e3T$eg_kfj;y{TR04X} z{Wu(4!ld=@Y@h#6?`zl=^Ay6}&gIc>79XD%aIy>!<)l1!>7n4-vN29*}Bx;`(Fdi+`Q`$ z>2zM3ZvWrfV$>L+AMd<0#ZO;)mD5fpx+n@Oy-TLHvpYj680ra3yEnG7#M_lQ0#M`_ z8}u-YjbS!F|5gLYeLe3ft#$khmzR}veV6fJ=jdYY$C2usF8@Pd4iEeD&DqQK#Zh1o zR?XA~#DBJ!^_{f7Pj_{r7>>s)pSyGKX%iRBcIvqZwnU74IIqi(5_X3fNgA#Fg%jc7 zD2A;>#ZTN%t9H{OLVt#Ln(FA2N45XShPM9kviUH+Xarjn7xbt~<$X{#THE;TFwt=_ z-Fh?LllSz(4}0>jeF2p0^^i2-sA5f$+W6;~OMli0*qZpy&zqi|uIH+wuT!~y;ns9v z2)3z-@niO_{^|DhXXeKeDzkPfj&}>`|AVDVt~bWbi2F58^W)*48h9Ze=b;Gt3)e1s z@#q}*>*=R^*@ydu$)1}g?%#^7mpA9F;$z)R@_Oviii3C7;Gh0=$5lB&M>du(UDnf& zzR$O}LUXqZlU-Y-6XV@4&q1OcPg@23AQ(!?BhQP4FEt`#vT}&8AGid+YT(p8L8GwWgzM8|E7*-?z zhWq}TajamtwY-Z!39K5Bd)LL-M(b7GY+9w{(CB&G@>PqJpS=ceVgjxmsK~yr51t6( z?~f4r&Hf{SB=-O}A-?`sv|u83%GG|jF#pv*pKe7^UA5NE@Owr4(f1G_J6Z0G1I7mx zW>5sU?e&nD^Zhvna6?fdG<2qAc;JkE*HYf#VRp>ZXcjnVufZdjslXI}o0IinHH!H! z+~Fpyu~%V34&ov>ND|3@L;DGIT#BbzM-SFe;DdX(YrnUR<6G;ON_wO+=ZtTX&?KNx zM!g}mKa!rp>IGJ4)v&0k7)dbHF>YoeWZ;+dMFp7D@s^S@)ffwA_4B*(tzd$`@AkL(nM3P;$10$kEf2uCi<>OpGlF(b;+% zdVN!s-K!}ZG3@H!L<@JH;@X|mOBaq#Z_fzQ?RBCyzIu;}dR>cIEf;22EAK(3UC z`vN5p+TP_l6iti#nRA*VJutOgVR36qOSeGmj0O`lZT&#!`pIc&G9l}dFW`GZu}eWb zaM6{83X^lv+GDN_c~Z8q3ZSaCJrq3Xe1WmDT=daQC&92PpoFyeAgTtWv9G~P&(@s4 zz}8-sbgZ&iHOzl!t^qtbso?V{-LNNJ`UNZ_o}w0c_w{+Se`Ob*CXl=(ri@a>Yl(u7 zp9e}CFp!WM;Es}_s0}aWma)SU$~%?T!xxfZ0Rn78gj+d1HLS-_Q~ofm1>9Bo@g;Ky zl8d&UuBBbP>&vbW$y7eKFYz4~sAA_zNJ>a6J>(NDw_$Tzx%Q|;v_Rp1>7D;6{iu)>wy4wmPg2C2=803+bIQMjFN>eslJY^(%usyb!yGQ1R`7 z!AO)$<+;r=S>b9mO@$%#$WIT&;0ay&p;8T9{EK;Lm6rxt4Zp^)=n|FI@C^8SbP-zM`VV3S+*DX{<2;U%x57-i-Ar z0hnvfO)a^RwH_%~N0iQDXjt~HMMXdM!i7y18wx)NT z^rj%{7+tx0ag{aYl%XYFugu}>-R*`L>OvB0hfUl3j*!~VL2$7ciHCJX35#hClS!M7 zlQSd($B3x5_7|U`N}IOP!o{LwU4rMgLMl@atIC`td(VR)1DiF4K?3SC=@8SmS+$wg z)v67??s&VOxdzlvm9mBbvaaJ_&_ zoq{Yx!Xiu8EYrV1qn})wYyiWY>qY!@4noI-f_T0o;FXMuL%C#tw=Ri(FKSwmigk_a z`vz{B^ePK*ne9zTeGc*Wy-#G^qoR6zT{()a?nI--;Nv3n^!1h~ZYY>kj~8~=)9$U$ z#8BdT`erps4khHR;`?_PLQ+%rH30KFL>T^6-4(7nOKi2jhEw-kbmz~ZB5vNIK9-1! zvi##zc3v@quxZ#^C?YvmX5o43aAPax$2{pT@xyGUbgp*8?}jd0Xg|8U=UFj6v7INn z+{^Z%I(w?pd(dHE>UYkrI*DoRfyh9>cEIT~?IU+U{Udv#VMHNc^ z@iF@HJ?jzv4syE@V~Whndw<`!QA5-85i7wfp@DV*TAdksIJ1=)XfXaW3+ouTb+&{;-e7C5+4}Imc%<_W)!YwbZ4pt=_RrIL6kWmd*MK57s2P zGRC{MD{X6q#0U?&G_`yQY%a?h)0Sp&bSE=zUPsohlOhQnJ8}@M<2X#n2qTRIsEgijKxGd+J zC4IvQNoh@mnL#?)ob0p;H}qjGNlr73g!b_aevwiM+86caG0m1vasFYG?ebB#JS$Pz zYc1mPJL@k@o1phvk(T(j?Q^w+$I@q1iLC;Fuj&!hjDr&I`(u9u5|BM--1P2e9YApUg3NPpJXYr%;V{C=5c9{4Fb zo*{G_hcC*MN}OrG=noRn`}hZ#SBkqU=U9{)s4!-7k?h{mGZ|>k#SW#Ha2+7-VpB@= zNPj0)3+0XgT@y)@tiIHlNO`5kc(Lws^gEMZ9xV9-O$Eao(T&*Zpa}3neKzq)ZD{v6 z^ie`bF*X`5K5?xL&5~b7zfLPCc`$uWe-GKq3?B=Esmx5#C! z5v?h5>T-Ukw3C)ZG$XoL<%)puNF;kcMSwP6ZwqfA=r)eO&YM}-o1-{87ZevO@=e6fd@EK&tzeqo5rc0{a6Zm zbEWE3c6nC!mZ7;#do3FHTbO1Jfhy~EHi$RX6!biNP0~CzqWuBpK9wMB4G;G)8^?@^ zwle0E7sp=$G<59x;j*4jpz4ZW6x3{A9%obb*d~G6f+6mOBAMLtG|uRElZnS_c8TfE zEp3+@Ka8OLTdu36ry}5({WS@IX?VIt#d@rAOPpK$tSfuy*wsy%Ys4xG=ciF6O@RDD z9(FR73Yf)nNpOQOU}%^w#(P$$eYJPRzNIxGVEkQwV}c@|VZ+wvIGRP$_wG2O^&_>? z!?Uu!@c>r}JBT!$>s@hMqkK_Pd5o*A56DPnK%-dkM>(AY%A5ORxN(naJcFHYt`4?< zc=$T~C@Qmgq6|Kpjo0K#IzDrG&)kyQCKU}xF2Bj?W@SZtQJw}y7g;oH(5fxO=)=la~)C0#^7J-XTh zwI2Fv{WVm1`*C71W==&>XJQqo2fP8d4U(sdGI~p<&{xX&hJtfkvMa~^tEzrVSJ@lx zSSf7?xYqIrY(?{LL6Yl_Py;S1o=UY+i5!yNP6Fa8Q$H3I*RNR_NeH`)#2jS)wh9g- zUQd@Jo97FuwM9&&yKxo#me71xHKm4HSjX#0o*6pX91~gNi{vW?xqi;V`{3n( ze7T(}|H3V(6O{xRe~d70nbmZQj(YrAd@GmXCddWg&$KF{e4?OxLq02DF2O~p^t1>} z)k8^^)9K%3N-Gk3S~f8p3qiA2z>Q|y6ZUHGZhpD8w2B{NJh|n#)P$l5-Jyd?MXWak!m5^z$FZG} zE|-&Sm!!xK7r=F+^~{za9nYfZUf+J)ks>!)G*UL+A1|+T34)9y9YFqr@(o;ZI@X5P zS}j-fSPjWS1*m!3?S{Q^#f@7>ER*?X@?7faVX=|fKZ5UXCu`r6yq#hraVyq56{z(o zRBk7zX5rVbx$cV7PPD)zh!n_uqSQZXR8VtMF32izORRMJLq2tI7ojsl-hGxnE_s zcYyUl7iPqz`REM5U9qHUjR_{$3Awt}nmKV;`?GSlM5mbJ$_wyBt^a7AbU?{p^M|fW! zi`EuIxU?j;g-ul-RWm^P$m)`x+H%nLjinKMEKj25prLAfan>S;YIqr>ORqj&2l zJeZ;bn?!aJQbOzceZ%m1Ijp!PL#244#TnHQ8%ib-S@iNH*Y|g)sAoy3s^O$_M+*sPaX4O6@*OfAkdnE;)@MkPmh^(>``m@yi0sLMoj8e~R@ z)fF-<&T%#Bbd2sol>oU%)i_-f5_vjcwRLNRH3a2SdF1KxmvQ za$gA)^%bKlEsuSN5KU(pwFy`KQ5ZhpkEsu*gYYI!#|`Gtk|<~2W)91^${{` z?yp5Rp(KH<-lGf~svNnKe%d(oZN=^Uklpx()jW!Sm>Lw&PEjQ!Y<0fhkT1Rh7)?ZX z>fTOnr{Th|7>@3cR3ko^bmQw1v0RzV5o!}v;N;Jl;yR=P4>ozZOzW$EomE6#nzS68 z5=!M3me$vL%E=v-R&NH`v0i!n3a(EvHZl4E*yS%9=ZAMz7kSEvPsmxbxOZ2r$C&Sl zK^}299}+(NY?pqxp_#Pp(@pz5d;aV+{CmVz9Sz}NG*RM5C32(kazrY-n`bhfR7Qu- z^0N(ekZidxlTlNGH&F%enE(rCy-CSu&MRWnQ9A*)^`(Op2e_T?;D${_UCLAoJN&jH z(0DP-=$DVJaiD6cNldKF6L-4wj2=7Au01dT%PJ5g8Tft6+wO5EOBQNr}GRG3PIM}D2x%Mfx<$DpT9 z?CVRuh2bzw_%5Ac>N-ikfFBmBQnH@&koz17DL5=j%F zEGx_;u!#g`6Cs9(bpA$?=$TXA9Zzi8b4tl@jau@ei{9e$$9BU#0oT;U7nb~{sYd$# zXV09b$o98L?jveqKHr^$%m=uH2GGi={k+2OqxOG-`>CrNkrBDe>?AW+ihIN;?Jea0 zaFN;x^L3Ma2yaC|yi}W9edcBMPRxH?_?e@QgVZd>oeQ~2C}1lLv@%)#v%a_w8HId~ zjBvG7+;{i_^UN5A%WRkABE!Z&a}W>CQ!*iC2y5O&KFDa2)mECFvmMs`6i%1Czbh8g@Xc=8;N@_8c}f`q z232>x)TP`^hpzn~xMLHs*JsoqL@@AnRQSTiMTr)RcdB%oRu)f%R85mY7(uKs`L>oD zLp~EJnu@aOO@SMYQ>M3Fo8vjQ_HshZ{F!OsP8Ry&ogq(1q3dy$PYws2UJf;235*sH zY>gwk>nqNA2&tVOwV@8S{n1 z%yY}Y>K4S+0u)K;!YzYWdwVze>>XhB70r$`wn*-kMKr=9lM`<>QO3oid`iDP%I%h| zzOz~+Frh2T2ZJI5BQ{0=MFBV^#nz@c!Dqo}RBxX1Esi1uvr_cLH)8Ya99pb!bs!=d zSsE{X2D*U?nb-1ywq<}@eQbg&_Q`xj%~ z-H(92$rMUv{07F<@1HX5JAG^BBR1G8G=f)Vs|5ySC-zZg@g&}GjDnlPP&P=ZN7~Aa8!>Av^Y_{11rcYZ z+>quEMedAO*=8vIlghr0+XUY-{olFV<(w2BuS$?l{bt{3Y*J1g82?IufA}N1FTOvG z`#l414Lw)bESKQ$qQT_Z)lII^JQN?~364-6MQduPUL#2Knnu`Djvui3kdw$g5O^*B z<$#r?2Kf}IR5hH!k z#uqDF0}Y5g^J5ixT`as&NFYqDL=x+{F7RZnZ=>}QCSZfUXB2Y3ef3Ov@7@KyUmIHN zI(uXb3VoeNb_{m^rd*d-2fAH{uD(ETPOR520*%hrwzgKLTU+YhH@W_WTTj(JS??G$ zH~9;9V7<}$wgbukVO{4Lv{jH`qJ1RxCanangz4k|u!>EMfBNh4hd+aXEXsyx1`lk{ z^+B((FFM)HQcvuG@sl5RpZto7N|=ljsjEFdolWl1GDGj#o)`G)xH#AN&AG{zv1H?=ahIRiM>CCo$^f&K0z4}51tFL3~rM5 zDmXM)P1bb}uPm1`!)#eL*CpJ%)MSY`3^!6FTDR-sStEGIZ5;QzSujSXafBK6cJmMh zPKL^Nva<<(7^M(>v8!FD8G3VIbPPnOQW+WnPg<_(czv5@rvpfZwR_!$Lu+aClfZPA zAyyFvg|R=QM$>(Z;Do7u!f2c0-%1#<-?27eBBR1VBbIgG&M}P4>YqGL;WyX&%?%do zYd~uyAj1N2?Ez_g9-yFA8c%dXI_(Sq{=ITSbEso1|9x9rLkOyab%?*mDekh-8OWf= zKn?vxSt<7lpJ#-2r&M6P46g*P7uWlv%<`@@=jH*48K(8qMmnQLkY1tT;CAMI*ftq61&s|gKgdYo(3;UfU;ALRUrF!Iz5L5&hRVTgGI`G?<5BRAJwEdH`p+G+M5I%(n z!Z#CYpA^wPa$be=;|(Exfvb-nkJe#@N2)W6Tx^{ip;DKkQlMj`95)!k_ch}!LV*1@ z>NqDgTnz{oPB;lHfyJPE@~=y=3kO$!s|Y9IWYHrHUoSPG+ZGWh(aLV|c7Vz>Lj=Y` ze%gGf)hdCjMF!{(#ut4=0P?f~%z647)cW`Au;Sw;;yvb6n#}`3D zbt`~AEdZt-4hQp=K~-ce{7&-Ugnjg=;2h1u`Ttc>&92voPoRoxI^V&u1_6;#gmI%B z>_ferobj^#YLRs>j*=hs7p^e4rT@|i5aCKKOSlmRGz!%!;}s*2S5w2L{eA3x{@dCA#r9eO8Net{oox0R!Fy(J`tj1?9L!EhFukyIO=9(3dVH4!vI^qA%B4Yf>HePRL zx9)Sms}Z_~-N&yHOh8ikK`NL*1L7+>aK=p_?zz zwbq^<7&*z&gwJO0FC3J9MZfv~6iNy>3;i9ePeyQif`_8KW71r0;|1}V* zN1Uu@FEx-uMt4x}*MH0W-=`QS>txy4imXez{4kwAvT?>GqzW*=JRNJ$1;9rSz)S3H z9(0L(cpC=V%3v`GK4miY_ixgy$KdrQxlc(gjUV{4%d)0`;*({KIbC?AJ$Rlt>tgGc{x!NG1 zODOJLl~M$i7zJyE`2oF(ZW<8~B~5fE_>0E`5eAOD&M~Gr5;R(;`Fll4p!Iw81As3w zz?A`jpdk1)yf1xub*&9a2Kp=VR;Lw3Pf(EH7W#i5cJ{hUwa=Chw(8ghH18#gRfmFsGXhys`4 zj225Y)G@_&QI*?j_Uzwm|7VjV?HJZEy(z>e)c7fGLTWOaQD@mhPNRDy9P%|00mm>Nf!9N!x*(3zSKOi|Ft z+)ZOpQ@1TslL!_}9p&ZcEQ;anh;9P%HXvGO!lNRUx(G5DQWf) z`}u4QkI^yCy?A&t+?u)m()#rnV!Le1CkGo(>>$cPC5;jH8?Aiq+sqOaT0SYM8|vms z6=^_)aQF~ug8E>H1PVTtUSA|`h`Rvs1pihX=5fe=yf=a=fqky3 zxy!K7Z3wRl`Wj1G!?5loogzD2af0+rN1be;9HkZwyw$|SLA9&+9#X85NbLFrtlvJS zZTz&)Eq=qADNjrd*4wj(Sr2Cee}%+~_f2go#Ok(pcD6GD*B4hKglxzg+!ko*l;n}^ zhJxX7Yn~grxfNCnXu)NXP)x6n%OPhWuL-?0O)P6Xg&G+xBHx6+2uZ%9A10JbZs_u( znF2O24Kk|OMG(QGV$Z_XEtNxyWo1nZ43;)prxy4c`Aw4xyd~&vOIUjN>yjRB&es`& z^4eZ_2YvvStS;=V&%(n08F{mW0j zBIsWMt-&CO{|UwLrt@8p>%Lz1=1{30o+vEjCmn`YnzFA1-A1q2|74s@afHYmGrFeR zU!FNG?r+W>o*ggz@0&lj+V)-qX?L9mVO=c_B2u`4{eA5qY+FzX&{X zj6a>JoL>Y!oL>AjTma)_0i9NG9qq|z9T0NUH|VC#)|)|CaG0??NgJBYco>R z6y!2yTcu5uwh_O3gssiIlh!#l%zH9z>g%yT$$}}f{LAX2&K~mX^tEGmc_kIiWQ|#@ua`E5w z8y=L?%WG2Jsc9Rh>fxp6HT1W#47BN5ZlG*r^`#Q=+4|nv%f)*UyP4@R zW_#)CYFc52g&m+@_y;o=3o!s-I|7VVK$lGauznZhPrd%3yW=j4Z>P07K0u30MC}vL z?xk-=AM5x^_Hg1KwfiYqXZ=NXk48)N$54RUG;YJ!-*CNYW2>Ymg29mgZf;Ik{_&Et%v7Ws}SRrH(5K14s}7X zVm(xWE{#*k0ZWs(Bu8W{zU&1ex)3t<{yF*X-!9H80TWvuIXFG`Z52-9#_)@r_C#~m zN<47@i*j^L!tmx8eJY~z@=9q;AO`gWHapHIMHS_jl87jNzPk6P_usBmR>b^wvMPf6 zS|F#7jmXF6$U$D^)6*6K*E@xoV>+(1!ilY;6tVrRu9CVA6 zp3BI*rqRM}c&(&$+y2nTT`a_0sMSvEEQE$!s-|BSY?WoU%es{HeI?9rYR`C`L|b9oSB1*fT8Lw6 zeHLGxEuv1NLVkgC~m&>G@vW)kt|m`7(t`S)0S5sJ%*<)Tf! zcMHbVerj4N7=o&rGH3IVj_xDR7Rw0|H4h2yy-k1vapY0&<s3bW%?(1coq1h*lxO^+JRtU+<_b-<#mofb<%OpOSPR{f=RB^4$#eC>vJ& zs>@9z7I``;mh1e_a0#M2ZK64Xdv`RW*PrrP+#EHLljN=bgf#{~M5gn`r6gNsTQSfp z?H7Ypc`8c`forSE#`EUtWQW|lFF&>+-^~`66wBML#qtH+*IUlDIdi*6@654k>7u2hGx0!dR8 zsO&7Y*&uARcc?{NY3FhH+0T?ZdCaM^jm_|yv7wseb_$VilyC#I6;dGtzjN5SqQBz* z=;d_A6+)C`54Y6WB}x~JcAnzb0Jnin$E)y>XWCdkQn{yu(q~X|sZ`ghza9oWM=zrBi24B(%R~2rQ@zUS+*}UNlgg99W&DQ zmak7ENF36#P_0F9`McRo;R)J3y~D>yjUYv8wTACI98z}8lb#r0!euGn6Lj-5mdYRI zVL}pTO@vYs&G8AD)6BdM;M3^0hxem~;_I@mYq)Cr&C(>yiWEtEvv_@ah2cW)NI@1K z!^6=SSIxlq-Ly9^Rj_Y5yM2s{$C9NliWq~?7+Y1ESS#$n;%hx7%%dxo?d|R)Yv?YNh-`mfr z;yZFtr)mkHL=7wZv1DD80Ef-h5A?h30juEKgZlkXn5`1_6?kj|bQH_^+!re*qHg&9 zEWfi7?iAfI>BqcV?DG#HfiWd|=QM(C9hrI^e)I?>vq(>-$u*!yoy!YvtVzl+=V4?_ zU9=@kYupek{lmcFCwr0iiIg^S*@Z;o0J&=q?Hqo6c-pM=(Qk|VF~^rrmjw%>i5iE* z@aGaP;!7zz+I;HGdm8PHeT_!rI)-@JajsKEvw<8FZD9hO6wG~3x+K;=+pQ0qD^e_; zCM*KK=luvB=e(cWq)tqn9OR&FQsA7AWJC}BZf-&Bh1&0br{IP0re+kKbCq=?TKiz% zoCva83}q%NqNPK#5Tr+wCMx?nI)aL*&`UN6!m6fDsD~Q8IXIGUb5s7Xi!$UVR;nhr z$w1boBi+;~Kw_ywzZ}oMvdKp_hH8N`0p>?6*MCo%#z7hK9{HR6_vTT*gE3aRxHLvW zt?#$}+y~@@f|jh7FARMbD1xkxL(r~_n9~!`LGo*2?7@zzzUh9dLl|WJ3do10*?dFZ z7T(oQ?iN<;#l)atsA5mg4ozjM5V= zpMKnmo#(XtB*ikslrVAWb~`nBiG)=h&K}wTJQZjpogF$~jyR2lMJo7%ppt=J8RtWWl2?7p(=$jb3o_V;-nlRK3CI-73rbWc z(gQg^Nq?KR{wnw>h%fw|>L2c!t0PQS9ex@f;*2X-pAhZT4R#&wAOdVYb?YRv1X?Ho zSj2$c6CyvsE?zL&jxpX9k0s-g5lw44p-R9SK{x9-u$8$eT0cAT*z)t7CfeK$gD92g zp;d{PD?{aXDZjosS?J3~98VasoL+ITuhdu~vqpK*v}_tP-xyvZ3R;1=bHxkS%;0Mg z;gy!{WJ&UgE2-gmgiM2vHy;b=ON1+&Rfkop%uGa8y9K3cMeQbu@$$@a+p#WIpkZ_! zpK(Ck0ffg!moXz(fH=S1jeYc_lp?uF+HLW3U)%q|+FJ$15q9m`ctUV@cXyZI?(PHz z_rcxW85nec;O-1g2<{Nv2~Kb)5D3}4?=Q8#vwg5nx~h-5r)#R8UeCJMb#)n1Gq&vC zBqo3<8*@-j7zq7jNv9_1gPhzw85gt}8C$UEMd7))cF-=V6B~iSD+iFXl!kiveplfi z%PKE6z-0095hthqbrzo~_5>{QuEkNnX`doCieW|Bw_E?x@p?5e(Jh}d47>;LCWgb;*w#}b4PLqvHw645p1HHr(2t9V`H2O*yv^pI#!ls?J+qQOxYq;fJAs~Q@=#K-NHI;v?Y&6rw3Cmeu zbTEjH6%}O|egLB&GvSOn3S1!ymdKK$Y@!c8_h>D)d|M(+hNc4z`1yt}E{yOOWjFO3 zoh-q0NPF)u#JdKP+=McS09~JU7}soz9Xhqo_`%t-bDnY=+b#+=WEx@S2hL$^(*iuZ zgof8)nrxb_cL%KzNs7_dx-o6tL@s7hk}rL{)0uJeJXzk_hm@-Ik!Jx4OVram=F_|* zK*&&lF^ER14Bl@BrSkw72R#{7W}h&E?+2r+7aL>ip}Yv~@?I#%--6duHj@J#`445dyf%GkGZD4m+5CvQdMs%CrcyV=DX3;ijh0XK6c7@h@{`@!2Vz2Ufe~ z?lEZQoUM~I8NH-gUq1b&ur(17DU|;c6!anbeGw=y8$Ss1Ks)nYpxHYv|4DD)!u7mI z?GFPTVwZ$o>1t2?4F_7T=xyfbHn9u2S;nV{1W1aGUH=MSwiB+X8JVBT*BT=?PH~N| zN;5h~P|(d(mYmh=HgrVj+Lr2>zoA@uPm0!&&QFKVu?EF+%>>8VPRpoQ`q|=@StlI? zo|n7QSUR}_KnYn-EnZq{b!PuKkBkGxK?nJq%-Ofs-@=BWJfO(>9YtIE zkwd0*ual~Qj+WleFI2|tG@lM-SEiQCh^9`b9#P=-V>8@CQt!N}!}{qF1gc}FZF1;| z2;!8qx-rwVwXzSAZcb1{)_r(qKH|1RR+}`H6^v3326>^hv3^WBC%JNq+keTuoq_>A z3Q9*6nbs$!#E>~gwCH?5Ks=7R9F%IOH(Dujlu$FQHxf2}<=9M-`;lqFuqDZ6!*Ya8 zbv`IB*)h23Oh()A+Gbmg)Y9N5xrLAkS*O#HdNh#5n`2z#STZZMr&dnkx7~)&^$=6> zd7YAq(v=&1y32=E4<^S;#&suYksL=4h}P$}HKt<{OJ~O!HNO##S~PBuu_=Yu(s;n6 zhvSft4Bg$NP&%GB6;D1`A>RzYoxk80HKKNwby9uW*&~f2i(~cX?moZS>B|(l)Ohwj zww&&?dz)k=fYAY7k*sm?6)2Vi2y|r%2ESW#D}Y4VGyEhuYlB|7h%@KKxB# z)#H&_!bIOu9fCZbx^zUWMC2k4=2F>bQKcz4oKW~nYId+#I^h51_A8yikhzMOh;f;V zTiUR@bOJZ|+6jJB#XMp3t@fZPSHn5SlFGHBbbL#FsKPieU0OT#Bd}Ox(P=D z$RQ{H!*TV#>-`?0@&Cq%=)v*2^Vy67J*2ojCZ&IW%Y-FWe3SI0OY(TO`KPnX%Tq{5 zb?9^>x>+3b_VT3D$NjgVPxW&9yHL2@%Z$%fLi}L;AB@@I#Jlfzxu(;+YwNwqXvX({ zB@lFF+|oVr4q~gZU@<%F^TzlG(_|jMpjR0}H#?V8@oLVYUn4ClYwPV^y~>L2F=wwRgK5u?1Nl=XTk)=7waI$Gk)2+ z2DZ1rRj87yn1h?tPTqu{mBT_MtWCrZJc%sgDia5ktPYiF8`o(~yF~TiFIqyP;0Jf_ z5ji9zTf&WqmdWn;rVKDVzybHT)}%?XtU@I_9sS)$0f$%8l24&y#9z;{c4kir3|4cEShP2Y$^*OTAL zV+GdYjii?e^XMx5sGX6-1zQEb5zHs78p9>i>Knp82yoX~4_~z;7Y*nsIegS*YYL!xBG!&T=>mq!^wu1cOyO z!Rq%@?}R~|sMp#TGeg4_%_rR9`x`Zh5h8Wsfi}}V4Em5!2hQY0MQ(h3ziGL_IC0*g ztz=kG1w*~YjQ}5tM>sFm@*v6g+83`DSW4{07yF*mmh_m#ebL%AsqL^l9m{+dexDPu zMKdjjZl`G4Zs8nj@G6TWt1dabaFwJQEJ~dEQAfrB2^(DKir#C&sh@Zof4VzdKD)}f z9D^0t^{dK0K9Uo?tX-~hEnh0(iE4$s%7kZA1T7Lm|HF6ZWs45cJ!qG~9i;HB>^AVM zAX9PETnB>!4)dF%50*0iUdD!fg4Xv%5yEqd&tjY#iu^ZG@~F3&($1thaf%nmw49oT zKG)vHmhGm>=Kp;Zui(JuQLs#zoA|WWns`mm8M+Zg>hvFZF3oW3Ux}i&x%H@;wnCPQ z*j(9gkxqU(Uzn+Hpgy#Dg8b4bZphwnUq8D2?RzfQZ#J>vBXjcg)(?fE_&#VG&ULKb zY~d7mWLw#shk>RYIlfX)8;$$=GkQY!1)C^^8NYv~wj&Goa@M=H_W6b%z?9;1%RsJk zm)zE^P3jh{WhJK?z0DRkVz5*3HzY$erW`^*^6c!41)qc*4f%;}o!1!(X0Fd?ddk(T zy&~>!5XB*^fYtE^O!R0q@(0W$yXf_q3LdI7ULwPHaujz+dyv!A{)$f zg~LnfXmG3wsa|~03`Y0;S|k+pSMw8d-7rU=HrtJc$KY)+L)Sw5Q}npCrWr-~P6e_K z7hZljt6-*eW0|5A+v!D`Id!p28Fq9ujWG_y-+DNoLatem&vD)0h@+eW`a}>T*D2Me zjN#mlih76~y4Nb@nc`%|H`&kPRs&qi&TB{K`{r98TK#3m#ZfW`N@1yc(!2@I258t(qol;^| zz8}^DG?~pAjh27YCvXv)xaH_x5lOVFj_cCc25T))c**_PxdsXdFG01`bhGRA3d*2)Z-9S8~qci~RkDZCRCC^o)l7@RVrR%~`D+H_5iJt2<4k^(bT5XBTya_Db)@ zD3+-6=k>G_gN^v;D7A8oqQ=p>0f2O+@)dB4w3+jh+W8y8eD?O51N*wQLNvnk>YxMn z(BbC!*wY5wqek4+I6zz^m1YKnsDL@XEKX_L75<|+_QAnmI$4-Xt%{|I2I?}gt8b1{ z6ItHv#+^~21I7IIpbs_xX-4=Ko-G?MLh{?@-Ag-yBH%j4ET3-?1*8L}ZxSClY;GYI z6C@x6`ks0Zlhf5L0xn_C7%@Q(y2^VtSNqL%>lROMr154$j_7EwaC^W*$z<%T z&p77jv$2kzOfRv|1Nbv>ev_3A}*O|@m8{gq)`cf~L{ zO64y;e5L-x0}*(%jp50O2w{M2*xIuZya9EC8x-@Yalf8HjkID!g(xqZ7-65NH$@L( zTi2*cs5mNk7cXvMzm_Oc-0 zc+|3<7G7SSE}s5YD!*pZniOYCf00WJH*ac&RJ9I2^AQi&q^^OiKzg}r|^GQ4h;0YQx zzas>8>A_~Pb|>=p){2A@;5E2?0B0Fz*T=^<#LfIw)G}XyteDO$J?op86Sc%cwh=oG zrRCi&b7%P(xCbqMRC!9oX3AS6@{NPW4T!Bc63W%)4d$E#yV&rkc2R&JTm8|-?%oa_ zXoa(qV}7D~=6y&kpzX)O>s-BGiCLLZQ_CtD4bI{u?wGZ+$Kxm=Boe_8p@56m#?eOR zS0a6_6Y+CrwZk}CQib(Z!$A5-oZ9RyzC$l|!2k}hU+9!t{ zTy%doP?9;pEws(PR7sZD*e)y?PvBRIz?Cs8aY^>$RD~C<0pa8AyLrHDTdRl%P6YOgA?})y z{$(3Guk%*_(OrxTfEbWS#xv-57GFMKhYsi$!k}t8$Pds=zj@klOW|FI-4{DbCwqN6>kvqwIE8XQW3#b>SGr~}Y6f7}(+7RTLB+ZH~#;op8N{_y%wj8PLTCIPj zcVuO5aUjlJ_}10smM~7*P9(aYOhjdvZvW(bL>9dG{8Af4;^K?0o;15zg2vsHspBpw zKK#qFR!gBKAQnt1I1gE>FfzbJrcv^PFU+AfPwePFe_I3eChoqCM&7Va50cfcLFDc* zGY7n>!ZD{?oAvea7vvjUQIS;`m*oiD{BpIe7s7=4moV=<5~Un0bv!nEibiZ>2FVFy zt?*G(w;Iv?xI7gLm>RN6=5h)=ef=_6WsKx(6HR_Strqj|Ec)$s-CEnWBAsa?!YgcU z=?Kv3*NZwHCO$n%50r3Bqwv$D+-$#DB8wi*`QmJ`aup#@&z^OyF7Gc>v0o&yx-t|V zDd{p0IV%k%9wLUqk$HzO)hBuB8Xe}=R4PGvE%=u_@NFFziCh652y`p-*A?y?L8Q)# zh0V#HApY;fW;{57altjy8=3OB;Ziw|_)~!ZM&zN7md)53a{SAS=xj+!PU7tjl=siJ z_P%Mtdx@_Jn$Q$un}C>>w-_TomN40}DT7OvBmfF~C~G~=c?6x*&W{PlMpDgMwbaGK z3?tb(0li+T*(BMjrFv@ZF*&vMdgO&ESI)%QB5c)~EVdNo-G(}l!NR)KkHLB3qN^knq7&Pv5R;AM83Z7yheJFq62X25V!#-Q@-g=ye9&57mB0TIgr<}#O!-5=T z{YA$*c>x!5G?LAMgTbBR#bph`rlyO-0-opfeXw^OcRPJE>2!B)obFDMD7BeT*?>&h z44!X=>1BnN8`vt;J_d8-qHt_Y-t5*JKiA=HVRw1?1a|>RolHX!LleydMbk=U5Bo7v z^`hDLM0wjNt=dQl!2+#-NSCf_s9usYpKRE~#+$`zcYck%=6Z76uuhFPV;u0zJK&L_ z#(-nlf?Z^a;^d%86-j6M86v`+`2pP6(PMA)h)|!%k9B!0oB`qOV4)rSO^}Sx^4T$O zxSUYroz#`ckji~-(p?)m!z~j*)sVqAlzU)p;(S$B;go9H&%H>1iJ^_)*6EPZmbvN< z340JfSx7J8fqzeAC+fF8pGXyDqQE#{pwv)HK-?l6O$MdF%vO(tS3m^NC-#+JnIuN^ zoBD51x0>jpwZa1_t-V>6MEb?IzgwkIzmE1L+8fMD{2t*Ze&aIrPoHwIMvjZ7{-olu zn@FV#PG;AEP^$DG8XUN=)zfA|l#NL9X7$3Vh8&4gf0>gztu%Ic$X3u>d=%|qy@lb7 zpmZW-V5b_HU4JsR(Hq)MBnRgR#o2hMTRkMRyQTMIm?di719a;C979>LXwC%DLJ`lF zS2GQy;3oG-nujwD;J<`6A|eSlO8m!+0Yl=AKy^T3+`Qaw-2i?%ZLjy(Rc(vQn=fd* zT?ZYOd+N(zckp zAhkH@jdgPDaxqPsNZiA?G*tqk(On$|=baO+Q)?#cT$Gyb9MMhD}}~CSR>Mw z{Ca+)4TzubqD%kQ!#%3gL;CnVoN)G7i_d;Dt(`dj5B$)IuqEm9cW-&d!A@+t)Lg?g zJ{u8gT#EP~NJN`)z2&izLh< zUXvQyg#YMmcp0q~san?td3m5-JX70;Qo{vbhGRhy$F_j}y+bZ%h0e&OXr3 z;iV0Feh|I-k|b+R!O6p?Xbtb>#I?aZ9*MS7nZ?EDP)-wLx*=}mU|T0|g9DAFymX^A zqrK~qjz9Q5Swgh&2jd3osiU+JCRNyvP0$qE*8SMpSurPerA6n2rE$5k^Gwk&nhC3c zEq8b%&7?`-ZH3-4ppfRy?nRlzXhD-b(1uo~4firib;<)-Elg+ZR~$e5Oj#zoSgtS^ z3>=ZaPoA7XBxbAx1!Q*e1V$fv`EE;6{h%NK{ewhE9)uOYa&V2gaT>js1+8<*LK%j` zd!O;x!)v)u6&()n`B{t^lmGm)n8dhi8EUk2hsHeLG(xcQM9aV@e?R@q+XV>l(J{IE z#_VUQoO3(EInPE^c6qPvY; zn5AIgoA4VrUz%P&rDhEExGcR#61O zN(c4QB=}(ot99i=1-qzEYQ%XAE#B?TKofveG$%)aH#Vnh?Z2S0WMTdFb!PirgPNy<+QQuVW!M_%Q zwy_D~U8*tNoE?om5V74V93fseL{tjH>(QA4<;s-uU}X#5$JB>T+n_|B!@_GoL{A4$ zCRlLBR{gic>bDI(6ZGoD?kCw5Dy|w@c8=2v4_=7KVnq+NZRM@rD!4yy%+u-J8-4N? z!CdO0bQp^z-O6H2#<2ltGwVfKznPe{D;wNJmc)?L3<#Bw9SL#13mVM0J^EL>3?@aa zljL(VyX8S(>VPCxcL!Tve?xZ0<#N7BWFL*Rx;fK1SYcO2*3KacdPz=o!g~Ci01m}< z;3J283crKkp;!i++AN-(r+=6NpfdFGzI8yOoxY{DSv22h*cKOzNrqFUXU|k?@l`|hx44iG;Mj1<-R&Dc!z;5MUG;YOm0^@iW^WKgb=o zF^n9jqc*6bXbbUnw|15@IeL@;;(65MdOQ1x4p?NMOe5tw*?TFJ3!gaQdKkZO{Pz7l z`wvE@2j#ti^%ZI#67vs6i@UaL@G=1f516xBmmZ^R)zvV_L1zOMoY$sHIaolR(G-NJ z#!o3ld9pQC@kV2UJ>T5UCk)8-2KH{s99OZsI9KJnA*WhyKi5KHTidOC)vZlS7B^Y= z0#il%@5DckC(>JukXrC9Q#I~0{WyBoz(x#(IgAI!mo`14pwP;wHa`t`#jNZ59f z^+j!67pQ=BrcJJ5Hx=JpH+AR0rOi*bstwVp3TXpwxy^lo9`o26dQ|Hi{tMJIzNSOE zwE^)+Y~AJ@#|&T(Si3T}&5F$~@lHrMM&7oCR8ejdC!^w44lp42|jOG z4fCqov>h}b2(Rj0B8GtmukuZ#PNj7``S7%1l~A@7p{bt9D2!L8$pmZqJTKi9%=!9;8`%fu+C&@28U(e> z6QD-8gE4*a+|W_+CgIy zUhtKdZeYNjFyQ#Q%UL6 zfA|HD#QYPGj0SSJwTR5}Fv+(SNLJ)SM&4@=QZl+tQ6&^uCStgxPVo ziH9W6nUr?tYV(HPx9j4jt$vHWfn!cF3_7t$`g}Eg@=AN*`WQJ8Zej$PO*lA}`5+ z6}B|`!DeI>zLp89Q`c|bTwDP%DR91x-@s01{}#kBdWev3R$H|m`DkplLBpyjXfq_3 zi=DPvs)Wgto?+wkY3;xr2fL2SAU8p2=1V$@>`^qE34tf-^~>OG0RJ9x3o%8ayN5`Z z)h3f$M*pDjS3k-hnKd?RbeDwc#QehKBA;eB>aenDeduUC8|$$PwI)f1oM-8DGmZie zTXQJ5fOzX-j#CgB=Rwzxj)UUj0;F86WGP?WdlpS{nWbOu%h$C0onxEEhRTFnr()3s zKQs&TluMJH$>orA#T_{-eZy`^sJn->Ae%ZW8P~IfyM9w8sjAvo9=nLA zTP5K?yA++|WL=3aSNm8bMV7yLPH^MzMUb+&KrfNlW94rs&b>o!PIiTV9Wcr z07`dw`%9Kl#6Or+5Xaw=X=Xw}iyk?O0^j>?soNQanK{1fW&&^2(ahz7eX()0$bGS7 zwOqZ^CglLd3IXBB1~!7D)lkG?_AyN+WX9%x`@)^Nx5MSH@0uCfgnux0cS^0s!Ftza zr?HE4!{4eCgn${VLTa6Ezo+MYKeZzep?m5Cpi5@)B_9eF`Hs&j0_q*}79(EW1$eon zOC5=p$`7hU`ahzoSs+C+E3V|vjOGrP1qyk|qaKObr#K}Gjpj(h0OX#OBa2Lkr~@;9 zg+23>>+wzJS4|CHqL}F_L4FzzWtUc}$Bvc{P$@+_nYUyU z2Qk1RWc!&)CEZMi&Wgc$_r9)<3ZYoQHg@q7w`gUMY!1R;1qb?r=}pU@bRBpmbkc10 z&p@Ts3WO?jQr4enD=_`u!$BV>c;CmUM#wEN5iN{MIoVs+?*4DfV&ELm9 z*tl#4GobLP+jHqv%X^i36*A=H;n(MV#|AtL)2b)mHvcTlAt`DHxTTPXp~#MXF{K2l zK}sw0isufJ*_DhkqY%G`?AD4ZHlxe0^AS5kyHZ#e&aW@vjMIVLMz2}KlQ*Iy^-E-;vyuXWUj@g7zvmBC3t`wsMWQ7$KRSK6R$IX5TIFvX zg1dR$lns@Fc1gh?ScJp42CPyOUXmE?<6SvsnIZO721aJ8zIUzdJXrCmXwq@eVGwD9M_0X+Ne-I7%tulQ-uu|= z6-kF%q~gi)3TEzXMtdygdyda)TB>QfBlDgys9C$eQr->n-Kw=Y9aJI>i0zf<#2E_JptG?TJ>rzcXMuObC=m;OQp zlY@CkjN|E5lE1<=smj94@e)q0mhMrF@H0#}d~=LoGS+QM)KAopG`& z<-b2r!W+d2XQ4uj-Ta+-qQ@-8)tH*$>(Y}^`VsDPe0eT?PjAaeh5Qm$r)cRzj(7rk zCyCWP$r_oXGD`enR|U&51;i*f@$u!K2RglO4A zT`|jhnheRfY3i{%P$!4fi2=8h*!pgy&5d5qeet7?Ne(k|nI8?6LoL}qn1q>C7nv^E z0^n;4+CHfd&+uB4GQXsy##blMvl8Rxm*CK^wsa1AWG1Dba#z~8w;;pzKt&xFWWq+H@t3PoTa%)lj=dQ{&|vz5Vl>IgJ?`4Z-uJ z5)wJCKuP@^!?I z8iV9cP728h2T}eB`NBl*O`xso&D)2ZFM;DA-LfP}Q_Ow4aD%CGoRhq`Dg$B+nP0W4 zhZ(=hxFppvUGJ6@!NRTBC!OaTX_4)7E=P{_H8@n+pQRgFGZ|ZK0M1PwH`rBXGVvX} zBh)~mHT98R1#-;>y|OVHcuWBQJ#gyQbOwfGTvR)t87ibek)I!LaWVx{#N^>FI-D8U@njvz*=hLJw;krFR)?h->3HxKYf)bK6 zW^y^qM%Q#idDL?y0_VL#i~e0jDKiT`7m_ASRAIv68+~%wbNvvxXYxC<$QOg{^hO99 zBh&3t3P{ZcQUJB69&$K}kwysR>STWD{ngH$B1G%l*>9-D1Id|HlPa}=E1|YP&*b{6 zjz6t#1w77vmoS&Y0aMcFG?W80gXfxUb{<_v*Wx66z!v9_#rgDu<=p8n3%mJar7 z3?^w<+U$xH8BC2d9zN%&QQ6Nj&hKRDUztVJQg4e6#Y@;ZaNx^o4QS2g*2x|Y$-g;JDja=LVjTcx2ZL#bC*qTvY%o_p!PoQ;22SvR&Mt!~exEdrKDvi^{_?RSbQ6srof=dw zQDxL`@Krvia7zl7-qM{n!daJZz(bGocFAc%sk*6#P_f>nhC2e@`RM22`9_-wOB4Q> zgUXo}53jM`_5A~C(2+IS1gBps-Gt2ih~tnljjR@>gU+vsYlIUk%@!>~fFK#MN*6TP z(@k6XaUO`8Yk3iGz3|t3>6v}gsd&o4#VlPG^B^{vI{G{C@0Qa<(z>c>W;swoI~+Wy zI$kY37C=!BFX>-y;@Dv#f`N%K)SPHp~rbQsAgG(7Hl0X5~GNwkm?O~5EKC3Uu{ zV2V_zc^bKZq0k8GVY3ZQAsRQWsE){8n8`j#W9<^{^yG3k{R{#EyVh*b<_PMPcp*VwW+R4E}B=ucRuj(78s1MXs=p(5KQucTc3Tn& z-s%{Ny0wqCg^|NU09h)(jy=*g6;-<;(Jh=poLCp(z3pX}k)_1O>)ckR+gIu;G&8hz zoZ{pCgNY%`qdB<9Mzm~X@{9^}lvs$!f6FR4(5mI)+(>@rxa^GW(JJ)}_shoNodM32 zhE0y+3N&l{Hm3B920s_#U_A3P{DWE0nx#PT4q@0Gf@U_(vUE=cnHuBt{e$UM7WwP_ z6d-oFp7FjQ9iAp>yeSu!P|GKlkJ=<0)QRn0HTb2Rd1pAEy}qgE@*}g%X|^Yd)e|~L zazmo8Cuv0wD3b-dxaiY`K!2ob6c6BVJs9(i7RHjy3bn7vp%TTN`&i0?pKpNjki$8l zc@n3ij&r@ASXmZp>6j5?`2xWfRxvWx=nCa;GBpfNnbfh&0F|PFvyC#WL88TW1%Gjo zCko;T-?;0tu?_MfWwT0Et9d7k+)@-Xd`_u_SdOF?#wj_wSFi&LH@A95oe6kODXMb3 zCn)T}4qU+mSwemTHn03uUMl7lp|daN9}*<->2K?Zi-B$ZVk3CT8$5PHz@ytfwq9E6 zhI?U_Iv`g&)-Ak-lLx3wUpvRLT-@q1JCAb3X=-_u`Pt%q1Y}tGhL^p-J=>^;sUA+& z*6mcD9j+3nPOn5YtOVHwPI)d-t3VFf>_^U{vRTsOkNE1Ty`{UGKUm0-Y~b#1>f=tB zF!)wDvR94X6_`x^`P}E$llv1b{y1)LDuQk>ryWbam)ea~^~Rm|h{4()ZY*6$0rXtt zQjp8sJ)wKH$9fs>%JiBaVfd{Io@~+`ZsQ$BX)K8`$jQVrT`!GY+le#5Hd_)+>#glp zF4rl|iX^USCt)W6y>up%wp0Q7N?Wv_s`M8=tzCnbJCwG&($CxzFPb~6&v(0OBuXZW zxgJuntytzagERz26+Wi1I2uq#`*C*ws}=8Tm-{Q>=k#4aPaeI6p!i>ze~uZ=N{Q*; zn(cafcsbel8~D=ea~K@h6B7Ot{?CQW_RH-}Ux*~!t-pVyaf z>iz|N807Ez&W)cFTafNx3|(=ONAH)P{lWiW$lvsC4kdyvj-La6&hEOJo*iF5-QHY3 ziFE!p-|h<%327+wsef&l%}RL>v4xn{ZTt*26Sz8d(SI}B_znB}_O*|L`1#rQ>E(^= z=lGTO%I^NVzBAz2xFyTA|FmK-c;;uo6UWc}pA*}nl^DG}?|PKH=U29~-oQ5sax-y? z4?f~&FDq9St`B#Y4?n@rw>NJnff#4d?trVwk@u9`#6OtHjo=;eH}kB+ee=&86cizY z-OpmD{;#3||6nj&Ls-1sFP_A7o?O>9u0jxBUf(Z03WojNUU+yH@;R#4r=f6ge{yti z=kj+@+g*d6eSh}lcbY#3xNd&(BMe7gv28B){+4S>AuY^GoQF&J>)#?chrXc@wUh~6m26|Z3CGq2Q;IeRL-E2djSE%&1BJEgpMp0D``Z-I* zo>}pBJejwT8M2qcQMSN1KlM@GnLX=zect}EO7cD$5J6%k+?TW@zaqsIkvK||WA|sQ zJN{Tsm&wK=JA#VT-Dz!O;o3`Vxvn+iK~)~fw&}3 zcQCjOjdk(|Wm^Af8#|<*Kv!?LTQ0pjZ=6m!(CQ@StIRKt=L#UbXeTSp$^C#=qcuSS zU@RapU;L!AUPoJsC`Q1{TlF8Yj>9O@*O7Y`?LGH8tDNS&yr}o$4p^KhUt8jtZ&ih& zM;podMHSCL8rMaV%QL9~RGUmAH&!1+W$#;9?VTbkt zXU6E6R@gg14l-9CwbcIN`b2*2@aK;HQXuv*ZH&gXew-Hj+3wuto>I#MP~$?LJ)8W<5ixmlhs2h~^;~tE zuBqxjf=pm(dBz%@Yjl}D<#H6&&oWS!{E5RZv(qA*-)*v+0zdk}%y#D7_e}^~9-KOn z`A26ufh3DhV(yRV-cvpE=%NDYa>ZTjK8bLu!hqx~A-+V#*)x6b1S*>B=eE z2vKXMS3jkM+oINzFo&u&%|N5ttmAFxHq(-<(Vra!C(JCk8B_D4NRE@Jg%;C@K(w#zagM!a7$d+LiyieTwy6S_OFZsx=V75j&0}{~YNBKQpb0cObgm zGOrlWP`-dz%T&T_#-4xicbwLBqM24Lp=OVk6B;r8JZ=}-2+&|PXpb5B+F?J&i)cfA zyPj$+g+yuTs_qU9%*|t9YSzO2mJjAdQt3<0EmeCsyyEUkcQMx|1}4!EW0~aqcDCqX zz>sKhXAQ}|Yn7*&yoog9O)&dvYZXUS_iU($*rkOG!t@$4gt6W_Gw|I|?H1 zkuqqhCL-T3urhTf>)q(tHd_9Z_Tlg2x)k4XbM^FMDJyU7um70I23Y?bMjP zzb3jqXcC0FoAKZ;`Zv{vedzN{ic8MHFNjg_pRDoNn4BZ=m}!GAJRg+FO_!NW{=pEN z6paHX^o6rKwIY&8Gx_-Vn)uq9n)$!lSldV>RTULg5qm$jmABm=mbyASyDAtmVSbfL z1%XQBGK$m7)ikX@hSs4}&>%)M;Iwd3eK%GbC%)d)>hw2YDxbeY1NBZE_WQo1#SbFT zZZm1wE;l~INO}8qZuSP;cYz7aZ+xKM{7!#Qx;h2L-RB^=6-j4C0j;O$Z!dzVx`B+O zB`e$sOl<<)9fj1;Kg#;+`%WMJ)eSCc`K@U*y}bHo*bhg*(n;wh5gCIuD*c{)EK{q~;yN9_M8cB93E@qGFxHHBV>M@67CDG1CS2ULO7D zzc=@q-#;7uXgLis4IA^H8T*}9etB}hv%!#iuq?>>CI?#XvPV6}mp@AKoiVtF@2Orw z#{lxh2z4=v?XD_s$y*mqGx`Rd(sCt@dHJ(KEItl8i|pz~}em#RFgS4@C1knZ(+ zK8A#cTb}LI%l#RvS6SFMUEV}^^y~S2M{BG^p8J^z=lj_1G4k8s{?WN%9_1(K3N8Ie z{k%#UEI$?IxFaqv?E1Wu#JvDsTh5R&t2d*|fZD37%;Q6t94&h#Zo&U&>Jy5P@S+fP z!lz!Z&5s53oYSM|lj|lmC#W?0p@%rIvrr0aeP6ye;nt*Z%;gmL%%s!NaliIWYQj2` zUCtdxLy%pm#F19>G0rOJk&RMu8I@blR`6vVgT0KSpjEV3taF+npIV4}XxlSMap>7I z{-c(<`UECWE)pKYL#dP+ivu+{qoOU{d(>Ev25J-tgT{f zWD|L)A|3bD52SJnZOX2s9&3~FaIaL4{gM6GntXvx`p zKGbxa_&};jJS4WIrZyeQ z_6Vk4mScRAiDff5L^8YJAHUOM4cyz&3SVvrl{&_;C*>yW*ku&FU6#)_UZU2aWOU`D ziUd*rCL}(LPFUT4T*cfrMymN#u>xrRP|96%e|>7$zeX7wQd}I^Lo2Rk_w~3?0hR={ zG)P1M?Oc`W6XwzBa7s=$j$HE;2|}M*cJA$)a>{s_1|wX_G-|jeSu{*K9s9KXfI>VU z4I^$UUkTB0EIy|gOiFu3WW6$|ZEte;!KUjX3*D4|YsCPPZpFE7m@)A&%veV%u%EpE zU=lj?qf>T?#YR28^CJ;A0I1IEpjv({cI zHP*%7%)fw4)Afi$0IF?2W8TVKnJ@#KzA@0dT_mmu3hu9Yh&BV0kKOjSzC+qAvyTb4 z72kWTE}oxc!rg4S7LTHAOXX@0s11^+!-G$MVr+@eS9G2y=r`7=(fW*^r}878M#s_a z?o=_OI^>-2DjZf?bNejcZY$g;-575sQR~bTMbzY0sQ%LTJ&!_|s9|bOZUm9FdynpVrJHN6dxqsM* z7(I_zn|VCma3wMN-M#~TL;0;i)CM~<$N$Z{w_(Bk*zxvwwl2$~_t~S}H6+AVe0#me zVS4l*jJv9NgZmX;)O$?@&hp;WJIA~F2{gWF2oC1+(}&!@-^l-*4*Eaj7egWko@j1~sZnj_c|ATpCxiNBB!Z_&s!^8XEO_1c|j52S*_@<@cK#`D9`d72~hX4KK zzx=xYA1SBDGLg;k@mTMuJaH?A%M4&|Y2=YkW1}2|PILSRM zJhJaxGkF{JH}uaZ_yxo+>Lc=r3GK}Q*mt6-9lA!u;H?ba+nCb}O2J5u4VFL+zYvX| zb4#ncRMc?($n@pK^krq>4bisUK@{=9o2r%;8se@Jyv~}ZynKn8;x-`HvDyj!*YJYE z>0|?8T-7*ZH^+inC#po049Yw5G)*r2Z|24MvEiv#GVoF(rgMKY3nBVI0cDkB(l27B z_}qOpph=beWBz)AM`B-*o3$CzsNV81|24CWou;5bu~F`Dm6BxHw$4|s^E0eHNC}x! z%)t~O#hq0VJY9EEz$P3uayYk~6)lxa1zu|cNv!UyhfRNt`h@KG{(Y*HiVGYr<^4)1 z@~PP(iEBh!7u)#r=ylG(Dnd~g5J8_ao=XudRbIQ-v2KG!hoOLXqN~@ z9*hw)j9IuARQ52u-n7@A4Kwot>n(M;2Y7GapD1wl=+MW*leR`+5t8K!%(U>mGH}6% zH_)D#7|)>sOkzcJW$^nnEfy|}3Dsdim4e=|?@7@2T14=Jw!z)tf=N2R<1+4~J3hAr zxa>F0KB3k0)+g#|tX)^C35ls*>pWK95w8syw;vyOKlU?pTm>u#mBB7@%CAy8C23Z+ zkcc|)4@E|gD7?Ts(A&s)FGj7FCS9ni4$(_&M=?plD$diYDY+}7g&JC*)j9M}t;bbs zuKj~)u0d-3!mpBZj8KR0w*vD!$q^z4^~SB>3|qnj_g}m#<<2YiZ8B?D3oAV%uye!Pn*=2 z@$pL8W$dU9m^GrU2QUkf*vgGs=hjKh@R4Hcekot?Y)t~FRXIXCCySl94K+zeoQbaJcRC%0mV4y~TF)5?$ke+xdg9Wq$NS)?HQV;1N0UsR4n~&O#gv{hz z;u?$d$JY$MOFFaO61iI;Dv;-{PpV|2O<$^g(xQSzK;)uBC_bmC0%r2drjj;Khz5O7 z1d{_wWyo$V4e~w(hMwUlRS6%=`7q@uz|xqKsX?iABe|K~g<8Ri>6L7ZYP3z!zsq17 zIzMakx$^gwf^FD<{W)rC$p?Nt2~?KZqW#yDDhk>aYJi$M;)l^vTF?aR#}v`UFj(64 z_wo5S=A9X|^Qj9qWJ2O~V`GCud!G^mhliArcj|0nk}kOEGo zgp&pevUj8NnpWuYFL8*28c!Yy9iYzgJElq`9Wy?hGxiWC<7*jnS*Rei8dIFFi5}=8 z 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%0DJhRUEf>_tf*k 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 PE@L%iqr%;h+e7~YG Date: Mon, 25 Mar 2024 04:35:16 -0500 Subject: [PATCH 76/82] docs: Disable auto_analyze for plan_replayer (#16805) --- sql-plan-replayer.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sql-plan-replayer.md b/sql-plan-replayer.md index d849aafc9e3e3..c5a3bc5801b4f 100644 --- a/sql-plan-replayer.md +++ b/sql-plan-replayer.md @@ -143,7 +143,7 @@ With an existing `ZIP` file exported using `PLAN REPLAYER`, you can use the `PLA PLAN REPLAYER LOAD 'file_name'; ``` -In the statement above, `file_name` is the name of the `ZIP` file to be exported. +In the statement above, `file_name` is the name of the `ZIP` file to be imported. For example: @@ -153,6 +153,16 @@ For example: PLAN REPLAYER LOAD 'plan_replayer.zip'; ``` +> **Note:** +> +> You need to disable auto analyze. Otherwise the imported statistics will be overwritten by analyze. + +You can disable auto analyze by setting the [`tidb_enable_auto_analyze`](/system-variables.md#tidb_enable_auto_analyze-new-in-v610) system variable to `OFF`: + +```sql +set @@global.tidb_enable_auto_analyze = OFF; +``` + After the cluster information is imported, the TiDB cluster is loaded with the required table schema, statistics and other information that affects the construction of the execution plan. You can view the execution plan and verify statistics in the following way: ```sql From 1b37dfd9c850c170fd3359432a43141185605206 Mon Sep 17 00:00:00 2001 From: kennytm Date: Mon, 25 Mar 2024 19:32:16 +0800 Subject: [PATCH 77/82] lightning: document logical-import-batch-{size,rows} (#16790) --- tidb-lightning/tidb-lightning-configuration.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tidb-lightning/tidb-lightning-configuration.md b/tidb-lightning/tidb-lightning-configuration.md index 5504cd62718f7..dd060af75695a 100644 --- a/tidb-lightning/tidb-lightning-configuration.md +++ b/tidb-lightning/tidb-lightning-configuration.md @@ -238,6 +238,21 @@ strategy = "" # This parameter is introduced in v7.6.0. The default value is "16KiB". The value must be greater than or equal to `1B`. Note that if you only specify a number (for example, `16`), the unit is Byte instead of KiB. # block-size = "16KiB" +# In Logical Import Mode, this parameter controls the size of each SQL statement executed on the downstream TiDB server. +# This parameter is introduced in v8.0.0. +# It specifies the expected size of the VALUES part of each INSERT or REPLACE statement in a single transaction. +# This parameter is not a hard limit. The actual SQL executed might be longer or shorter, depending on the actual content imported. +# The default value is "96KiB", which is optimized for import speed when TiDB Lightning is the only client of the cluster. +# Due to the implementation details of TiDB Lightning, the value is capped at 96 KiB. Setting a larger value will not take effect. +# You can decrease this value to reduce the stress on the cluster due to large transactions. +# logical-import-batch-size = "96KiB" + +# In Logical Import Mode, this parameter controls the maximum number of rows inserted per transaction. +# This parameter is introduced in v8.0.0. The default value is `65536` rows. +# When both `logical-import-batch-size` and `logical-import-batch-rows` are specified, the parameter whose value reaches its threshold first will take effect. +# You can decrease this value to reduce the stress on the cluster due to large transactions. +# logical-import-batch-rows = 65536 + [mydumper] # Block size for file reading. Keep it longer than the longest string of the data source. read-block-size = "64KiB" # default value From a98876bab3b49338033fcd82309ae7d0ed5303b2 Mon Sep 17 00:00:00 2001 From: GMHDBJD <35025882+GMHDBJD@users.noreply.github.com> Date: Mon, 25 Mar 2024 19:38:16 +0800 Subject: [PATCH 78/82] rename `tidb_ddl_version` to `tidb_enable_fast_create_table` (#16789) --- TOC-tidb-cloud.md | 2 +- TOC.md | 2 +- accelerated-table-creation.md | 57 +++++++++++++++++++++++++++++++++++ basic-features.md | 2 +- ddl-v2.md | 56 ---------------------------------- releases/release-7.6.0.md | 6 ++-- system-variables.md | 11 ++++--- 7 files changed, 69 insertions(+), 67 deletions(-) create mode 100644 accelerated-table-creation.md delete mode 100644 ddl-v2.md diff --git a/TOC-tidb-cloud.md b/TOC-tidb-cloud.md index 5c46152b16969..b50aae1a4cdce 100644 --- a/TOC-tidb-cloud.md +++ b/TOC-tidb-cloud.md @@ -603,7 +603,7 @@ - [`SESSION_CONNECT_ATTRS`](/performance-schema/performance-schema-session-connect-attrs.md) - [Metadata Lock](/metadata-lock.md) - [Use UUIDs](/best-practices/uuid.md) - - [TiDB DDL V2](/ddl-v2.md) + - [TiDB Accelerated Table Creation](/accelerated-table-creation.md) - [System Variables](/system-variables.md) - [Server Status Variables](/status-variables.md) - Storage Engines diff --git a/TOC.md b/TOC.md index 4fc8ade65b8bd..ed8ec3c253e6d 100644 --- a/TOC.md +++ b/TOC.md @@ -983,7 +983,7 @@ - [`SESSION_CONNECT_ATTRS`](/performance-schema/performance-schema-session-connect-attrs.md) - [`SYS`](/sys-schema.md) - [Metadata Lock](/metadata-lock.md) - - [TiDB DDL V2](/ddl-v2.md) + - [TiDB Accelerated Table Creation](/accelerated-table-creation.md) - UI - TiDB Dashboard - [Overview](/dashboard/dashboard-intro.md) diff --git a/accelerated-table-creation.md b/accelerated-table-creation.md new file mode 100644 index 0000000000000..f97eec9d5cfd0 --- /dev/null +++ b/accelerated-table-creation.md @@ -0,0 +1,57 @@ +--- +title: TiDB Accelerated Table Creation +summary: Learn the concept, principles, and implementation details of performance optimization for creating tables in TiDB. +aliases: ['/tidb/dev/ddl-v2/'] +--- + +# TiDB Accelerated Table Creation + +TiDB v7.6.0 introduces the system variable [`tidb_ddl_version`](https://docs.pingcap.com/tidb/v7.6/system-variables#tidb_enable_fast_create_table-new-in-v800) to support accelerating table creation, which improves the efficiency of bulk table creation. Starting from v8.0.0, this system variable is renamed to [`tidb_enable_fast_create_table`](/system-variables.md#tidb_enable_fast_create_table-new-in-v800). + +TiDB uses the online asynchronous schema change algorithm to change the metadata. All DDL jobs are submitted to the `mysql.tidb_ddl_job` table, and the owner node pulls the DDL job to execute. After executing each phase of the online DDL algorithm, the DDL job is marked as completed and moved to the `mysql.tidb_ddl_history` table. Therefore, DDL statements can only be executed on the owner node and cannot be linearly extended. + +However, for some DDL statements, it is not necessary to strictly follow the online DDL algorithm. For example, the `CREATE TABLE` statement only has two states for the job: `none` and `public`. Therefore, TiDB can simplify the execution process of DDL, and executes the `CREATE TABLE` statement on a non-owner node to accelerate table creation. + +> **Warning:** +> +> This feature is currently an experimental feature and it is not recommended to use in a production environment. This feature might change or be removed without prior notice. If you find a bug, please give feedback by raising an [issue](https://github.com/pingcap/tidb/issues) on GitHub. + +## Compatibility with TiDB tools + +- [TiCDC](https://docs.pingcap.com/tidb/stable/ticdc-overview) does not support replicating the tables that are created by `tidb_enable_fast_create_table`. + +## Limitation + +You can now use performance optimization for table creation only in the [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) statement, and this statement must not include any foreign key constraints. + +## Use `tidb_enable_fast_create_table` to accelerate table creation + +You can enable or disable performance optimization for creating tables by specifying the value of the system variable [`tidb_enable_fast_create_table`](/system-variables.md#tidb_enable_fast_create_table-new-in-v800). + +To enable performance optimization for creating tables, set the value of this variable to `ON`: + +```sql +SET GLOBAL tidb_enable_fast_create_table = ON; +``` + +To disable performance optimization for creating tables, set the value of this variable to `OFF`: + +```sql +SET GLOBAL tidb_enable_fast_create_table = OFF; +``` + +## Implementation principle + +The detailed implementation principle of performance optimization for table creation is as follows: + +1. Create a `CREATE TABLE` Job. + + The corresponding DDL Job is generated by parsing the `CREATE TABLE` statement. + +2. Execute the `CREATE TABLE` job. + + The TiDB node that receives the `CREATE TABLE` statement executes it directly, and then persists the table structure to TiKV. At the same time, the `CREATE TABLE` job is marked as completed and inserted into the `mysql.tidb_ddl_history` table. + +3. Synchronize the table information. + + TiDB notifies other nodes to synchronize the newly created table structure. diff --git a/basic-features.md b/basic-features.md index ed54778107a00..0821d194c9a63 100644 --- a/basic-features.md +++ b/basic-features.md @@ -132,7 +132,7 @@ You can try out TiDB features on [TiDB Playground](https://play.tidbcloud.com/?u | [Metadata lock](/metadata-lock.md) | Y | Y | Y | Y | N | N | N | N | N | N | N | | [`FLASHBACK CLUSTER`](/sql-statements/sql-statement-flashback-cluster.md) | Y | Y | Y | Y | N | N | N | N | N | N | N | | [Pause](/sql-statements/sql-statement-admin-pause-ddl.md)/[Resume](/sql-statements/sql-statement-admin-resume-ddl.md) DDL | Y | Y | N | N | N | N | N | N | N | N | N | -| [TiDB DDL V2](/ddl-v2.md) | E | N | N | N | N | N | N | N | N | N | N | +| [TiDB Accelerated Table Creation](/accelerated-table-creation.md) | N | N | N | N | N | N | N | N | N | N | N | ## Transactions diff --git a/ddl-v2.md b/ddl-v2.md deleted file mode 100644 index 59db024d00c94..0000000000000 --- a/ddl-v2.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Use TiDB DDL V2 to Accelerate Table Creation -summary: Learn the concept, principles, and implementation details of TiDB DDL V2 for acceleration table creation. ---- - -# Use TiDB DDL V2 to Accelerate Table Creation - -Starting from v7.6.0, the new version V2 of TiDB DDL supports creating tables quickly, which improves the efficiency of bulk table creation. - -TiDB uses the online asynchronous schema change algorithm to change the metadata. All DDL jobs are submitted to the `mysql.tidb_ddl_job` table, and the owner node pulls the DDL job to execute. After executing each phase of the online DDL algorithm, the DDL job is marked as completed and moved to the `mysql.tidb_ddl_history` table. Therefore, DDL statements can only be executed on the owner node and cannot be linearly extended. - -However, for some DDL statements, it is not necessary to strictly follow the online DDL algorithm. For example, the `CREATE TABLE` statement only has two states for the job: `none` and `public`. Therefore, TiDB can simplify the execution process of DDL, and executes the `CREATE TABLE` statement on a non-owner node to accelerate table creation. - -> **Warning:** -> -> This feature is currently an experimental feature and it is not recommended to use in a production environment. This feature might change or be removed without prior notice. If you find a bug, please give feedback by raising an [issue](https://github.com/pingcap/tidb/issues) on GitHub. - -## Compatibility with TiDB tools - -- [TiCDC](https://docs.pingcap.com/tidb/stable/ticdc-overview) does not support replicating the tables that are created by TiDB DDL V2. - -## Limitation - -You can now use TiDB DDL V2 only in the [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) statement, and this statement must not include any foreign key constraints. - -## Use TiDB DDL V2 - -You can enable or disable TiDB DDL V2 by specifying the value of the system variable [`tidb_ddl_version`](/system-variables.md#tidb_ddl_version-new-in-v760) . - -To enable TiDB DDL V2, set the value of this variable to `2`: - -```sql -SET GLOBAL tidb_ddl_version = 2; -``` - -To disable TiDB DDL V2, set the value of this variable to `1`: - -```sql -SET GLOBAL tidb_ddl_version = 1; -``` - -## Implementation principle - -The detailed implementation principle of TiDB DDL V2 for accelerating table creation is as follows: - -1. Create a `CREATE TABLE` Job. - - This step is the same as that of the V1 implementation. The corresponding DDL Job is generated by parsing the `CREATE TABLE` statement. - -2. Execute the `CREATE TABLE` job. - - Different from V1, in TiDB DDL V2, the TiDB node that receives the `CREATE TABLE` statement executes it directly, and then persists the table structure to TiKV. At the same time, the `CREATE TABLE` job is marked as completed and inserted into the `mysql.tidb_ddl_history` table. - -3. Synchronize the table information. - - TiDB notifies other nodes to synchronize the newly created table structure. diff --git a/releases/release-7.6.0.md b/releases/release-7.6.0.md index 0cac1432d7e3f..b5bee4048eb99 100644 --- a/releases/release-7.6.0.md +++ b/releases/release-7.6.0.md @@ -111,9 +111,9 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.6/quick-start-with- * Improve the performance of creating tables by 10 times (experimental) [#49752](https://github.com/pingcap/tidb/issues/49752) @[gmhdbjd](https://github.com/gmhdbjd) - In previous versions, when migrating tens of thousands of tables from the upstream database to TiDB, it is time-consuming and inefficient for TiDB to create these tables. Starting from v7.6.0, TiDB introduces a new TiDB DDL V2 architecture. You can enable it by configuring the system variable [`tidb_ddl_version`](/system-variables.md#tidb_ddl_version-new-in-v760). Compared with previous versions, the new version of the DDL improves the performance of creating batch tables by 10 times, and significantly reduces time for creating tables. + In previous versions, when migrating tens of thousands of tables from the upstream database to TiDB, it is time-consuming and inefficient for TiDB to create these tables. Starting from v7.6.0, TiDB introduces a new TiDB DDL V2 architecture. You can enable it by configuring the system variable [`tidb_ddl_version`](https://docs.pingcap.com/tidb/v7.6/system-variables#tidb_ddl_version-new-in-v760). Compared with previous versions, the new version of the DDL improves the performance of creating batch tables by 10 times, and significantly reduces time for creating tables. - For more information, see [documentation](/ddl-v2.md). + For more information, see [documentation](https://docs.pingcap.com/tidb/v7.6/ddl-v2). * Support periodic full compaction (experimental) [#12729](https://github.com/tikv/tikv/issues/12729) [afeinberg](https://github.com/afeinberg) @@ -269,7 +269,7 @@ Quick access: [Quick start](https://docs.pingcap.com/tidb/v7.6/quick-start-with- | [`tidb_auto_analyze_partition_batch_size`](/system-variables.md#tidb_auto_analyze_partition_batch_size-new-in-v640) | Modified | Changes the default value from `1` to `128` after further tests. | | [`tidb_sysproc_scan_concurrency`](/system-variables.md#tidb_sysproc_scan_concurrency-new-in-v650) | Modified | In a large-scale cluster, the concurrency of `scan` operations can be adjusted higher to meet the needs of `ANALYZE`. Therefore, change the maximum value from `256` to `4294967295`. | | [`tidb_analyze_distsql_scan_concurrency`](/system-variables.md#tidb_analyze_distsql_scan_concurrency-new-in-v760) | Newly added | Sets the concurrency of the `scan` operation when executing the `ANALYZE` operation. The default value is `4`. | -| [`tidb_ddl_version`](/system-variables.md#tidb_ddl_version-new-in-v760) | Newly added | Controls whether to enable [TiDB DDL V2](/ddl-v2.md). Set the value to `2` to enable it and `1` to disable it. The default value is `1`. When TiDB DDL V2 is enabled, DDL statements will be executed using TiDB DDL V2. The execution speed of DDL statements for creating tables is increased by 10 times compared with TiDB DDL V1. | +| [`tidb_ddl_version`](https://docs.pingcap.com/tidb/v7.6/system-variables#tidb_ddl_version-new-in-v760) | Newly added | Controls whether to enable [TiDB DDL V2](https://docs.pingcap.com/tidb/v7.6/ddl-v2). Set the value to `2` to enable it and `1` to disable it. The default value is `1`. When TiDB DDL V2 is enabled, DDL statements will be executed using TiDB DDL V2. The execution speed of DDL statements for creating tables is increased by 10 times compared with TiDB DDL V1. | | [`tidb_enable_global_index`](/system-variables.md#tidb_enable_global_index-new-in-v760) | Newly added | Controls whether to support creating `Global indexes` for partitioned tables. The default value is `OFF`. `Global index` is currently in the development stage. **It is not recommended to modify the value of this system variable**. | | [`tidb_idle_transaction_timeout`](/system-variables.md#tidb_idle_transaction_timeout-new-in-v760) | Newly added | Controls the idle timeout for transactions in a user session. When a user session is in a transactional state and remains idle for a duration exceeding the value of this variable, TiDB will terminate the session. The default value `0` means unlimited. | | [`tidb_opt_enable_fuzzy_binding`](/system-variables.md#tidb_opt_enable_fuzzy_binding-new-in-v760) | Newly added | Controls whether to enable the cross-database binding feature. The default value `OFF` means cross-database binding is disabled. | diff --git a/system-variables.md b/system-variables.md index 615d8523d7c4c..c144c397e3567 100644 --- a/system-variables.md +++ b/system-variables.md @@ -1712,7 +1712,7 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; - Unit: Threads - This variable is used to set the concurrency of the DDL operation in the `re-organize` phase. -### `tidb_ddl_version` New in v7.6.0 +### `tidb_enable_fast_create_table` New in v8.0.0 > **Warning:** > @@ -1721,10 +1721,11 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1; - Scope: GLOBAL - Persists to cluster: Yes - Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No -- Default value: `1` -- Value range: `1` or `2` -- This variable is used to control whether to enable [TiDB DDL V2](/ddl-v2.md). Setting it to `2` enables this feature, and setting it to `1` disables it. The default value is `1`. After you enable it, TiDB uses TiDB DDL V2 to execute DDL statements. -- Starting from v7.6.0, TiDB only supports accelerating table creation by the [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) statement. +- Type: Boolean +- Default value: `OFF` +- This variable is used to control whether to enable [TiDB Accelerated Table Creation](/accelerated-table-creation.md). +- Starting from v8.0.0, TiDB supports accelerating table creation by the [`CREATE TABLE`](/sql-statements/sql-statement-create-table.md) statement using `tidb_enable_fast_create_table`. +- This variable is renamed from the variable [`tidb_ddl_version`](https://docs.pingcap.com/tidb/v7.6/system-variables#tidb_ddl_version-new-in-v760) that is introduced in v7.6.0. Starting from v8.0.0, `tidb_ddl_version` no longer takes effect. ### tidb_default_string_match_selectivity New in v6.2.0 From e15b44e46f8bdf518da32f474137e273d1ae1b16 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Mon, 25 Mar 2024 19:48:46 +0800 Subject: [PATCH 79/82] add warnings for two experimental features: Google Cloud KMS and IMPORT INTO SELECT (#16806) --- encryption-at-rest.md | 4 ++++ sql-statements/sql-statement-import-into.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/encryption-at-rest.md b/encryption-at-rest.md index feefd9066b94c..8671963d3118f 100644 --- a/encryption-at-rest.md +++ b/encryption-at-rest.md @@ -94,6 +94,10 @@ If encryption is enabled (that is, the value of `data-encryption-method` is not TiKV supports KMS encryption for three platforms: AWS, Google Cloud, and Azure. Depending on the platform where your service is deployed, you can choose one of them to configure KMS encryption. +> **Warning:** +> +> Currently, specifying a master key using Google Cloud KMS is experimental. It is not recommended that you use it in production environments. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub. +

a&a8G%8uK#EaY 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[RqhY!kGMAC@&S$Z()SM%D$tXh&s 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%0DCp3I-uW9>?OcGW>--9nf%5KiWkG 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 boW$=rhE+RY{L*R__&cI^OgH1;*|7fsn#H6D literal 0 HcmV?d00001 diff --git a/media/ticdc/ticdc-simple-consumer-2.png b/media/ticdc/ticdc-simple-consumer-2.png new file mode 100644 index 0000000000000000000000000000000000000000..a7e660bf9d4b35733ced5734b4c8b963bee4d508 GIT binary patch literal 122977 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 literal 0 HcmV?d00001 diff --git a/ticdc/ticdc-changefeed-config.md b/ticdc/ticdc-changefeed-config.md index 1e25ea169a4d9..64eb617a93c75 100644 --- a/ticdc/ticdc-changefeed-config.md +++ b/ticdc/ticdc-changefeed-config.md @@ -138,7 +138,7 @@ enable-table-across-nodes = false # ] # The protocol configuration item specifies the protocol format used for encoding messages. -# When the downstream is Kafka, the protocol can only be canal-json, avro, debezium, or open-protocol. +# When the downstream is Kafka, the protocol can be canal-json, avro, debezium, open-protocol, or simple. # When the downstream is Pulsar, the protocol can only be canal-json. # When the downstream is a storage service, the protocol can only be canal-json or csv. # Note: This configuration item only takes effect if the downstream is Kafka, Pulsar, or a storage service. @@ -194,6 +194,28 @@ enable-partition-separator = true # The encoding method of binary data, which can be 'base64' or 'hex'. The default value is 'base64'. # binary-encoding-method = 'base64' +# Starting from v8.0.0, TiCDC supports the Simple message encoding protocol. The following are the configuration parameters for the Simple protocol. +# For more information about the protocol, see . +# The following configuration parameters control the sending behavior of bootstrap messages. +# send-bootstrap-interval-in-sec controls the time interval for sending bootstrap messages, in seconds. +# The default value is 120 seconds, which means that a bootstrap message is sent every 120 seconds for each table. +# send-bootstrap-interval-in-sec = 120 + +# send-bootstrap-in-msg-count controls the message interval for sending bootstrap, in message count. +# The default value is 10000, which means that a bootstrap message is sent every 10000 row changed messages for each table. +# send-bootstrap-in-msg-count = 10000 +# Note: If you want to disable the sending of bootstrap messages, set both send-bootstrap-interval-in-sec and send-bootstrap-in-msg-count to 0. + +# send-bootstrap-to-all-partition controls whether to send bootstrap messages to all partitions. +# The default value is true, which means that bootstrap messages are sent to all partitions of the corresponding table topic. +# Setting it to false means bootstrap messages are sent to only the first partition of the corresponding table topic. +# send-bootstrap-to-all-partition = true + +[sink.kafka-config.codec-config] +# encoding-format controls the encoding format of the Simple protocol messages. Currently, the Simple protocol message supports "json" and "avro" encoding formats. +# The default value is "json". +# encoding-format = "json" + # Specifies the replication consistency configurations for a changefeed when using the redo log. For more information, see https://docs.pingcap.com/tidb/stable/ticdc-sink-to-mysql#eventually-consistent-replication-in-disaster-scenarios. # Note: The consistency-related configuration items only take effect when the downstream is a database and the redo log feature is enabled. [consistent] diff --git a/ticdc/ticdc-simple-protocol.md b/ticdc/ticdc-simple-protocol.md new file mode 100644 index 0000000000000..def6e7f3f78d9 --- /dev/null +++ b/ticdc/ticdc-simple-protocol.md @@ -0,0 +1,714 @@ +--- +title: TiCDC Simple Protocol +summary: Learn how to use the TiCDC Simple protocol and the data format implementation. +--- + +# TiCDC Simple Protocol + +TiCDC Simple protocol is a row-level data change notification protocol that provides data sources for monitoring, caching, full-text indexing, analysis engines, and primary-secondary replication between heterogeneous databases. This document describes how to use the TiCDC Simple protocol and the data format implementation. + +## Use the TiCDC Simple protocol + +When you use Kafka as the downstream, specify `protocol` as `"simple"` in the changefeed configuration. Then TiCDC encodes each row change or DDL event as a message, and sends the data change event to the downstream. + +The configuration example for using the Simple protocol is as follows: + +`sink-uri` configuration: + +```shell +--sink-uri = "kafka://127.0.0.1:9092/topic-name?kafka-version=2.4.0" +``` + +Changefeed configuration: + +```toml +[sink] +protocol = "simple" + +# The following configuration parameters control the sending behavior of bootstrap messages. +# send-bootstrap-interval-in-sec controls the time interval for sending bootstrap messages, in seconds. +# The default value is 120 seconds, which means that a bootstrap message is sent every 120 seconds for each table. +send-bootstrap-interval-in-sec = 120 + +# send-bootstrap-in-msg-count controls the message interval for sending bootstrap, in message count. +# The default value is 10000, which means that a bootstrap message is sent every 10000 row changed messages for each table. +send-bootstrap-in-msg-count = 10000 +# Note: If you want to disable the sending of bootstrap messages, set both send-bootstrap-interval-in-sec and send-bootstrap-in-msg-count to 0. + +# send-bootstrap-to-all-partition controls whether to send bootstrap messages to all partitions. +# The default value is true, which means that bootstrap messages are sent to all partitions of the corresponding table topic. +# Setting it to false means bootstrap messages are sent to only the first partition of the corresponding table topic. +send-bootstrap-to-all-partition = true + +[sink.kafka-config.codec-config] +# encoding-format controls the encoding format of the Simple protocol messages. Currently, the Simple protocol message supports "json" and "avro" encoding formats. +# The default value is "json". +encoding-format = "json" +``` + +## Message types + +The TiCDC Simple protocol has the following message types. + +DDL: + +- `CREATE`: the creating table event. +- `RENAME`: the renaming table event. +- `CINDEX`: the creating index event. +- `DINDEX`: the deleting index event. +- `ERASE`: the deleting table event. +- `TRUNCATE`: the truncating table event. +- `ALTER`: the altering table event, including adding columns, dropping columns, modifying column types, and other `ALTER TABLE` statements supported by TiCDC. +- `QUERY`: other DDL events. + +DML: + +- `INSERT`: the inserting event. +- `UPDATE`: the updating event. +- `DELETE`: the deleting event. + +Other: + +- `WATERMARK`: containing a TSO (that is, a 64-bit timestamp) of the upstream TiDB cluster, which marks the table replication progress. All events earlier than the watermark have been sent to the downstream. +- `BOOTSTRAP`: containing the schema information of a table, used to build the table schema for the downstream. + +## Message format + +In the Simple protocol, each message contains only one event. The Simple protocol supports encoding messages in JSON and Avro formats. This document uses JSON format as an example. For Avro format messages, their fields and meanings are the same as those in JSON format messages, but the encoding format is different. For details about the Avro format, see [Simple Protocol Avro Schema](https://github.com/pingcap/tiflow/blob/master/pkg/sink/codec/simple/message.json). + +### DDL + +TiCDC encodes a DDL event in the following JSON format: + +```json +{ + "version":1, + "type":"ALTER", + "sql":"ALTER TABLE `user` ADD COLUMN `createTime` TIMESTAMP", + "commitTs":447987408682614795, + "buildTs":1708936343598, + "tableSchema":{ + "schema":"simple", + "table":"user", + "tableID":148, + "version":447987408682614791, + "columns":[ + { + "name":"id", + "dataType":{ + "mysqlType":"int", + "charset":"binary", + "collate":"binary", + "length":11 + }, + "nullable":false, + "default":null + }, + { + "name":"name", + "dataType":{ + "mysqlType":"varchar", + "charset":"utf8mb4", + "collate":"utf8mb4_bin", + "length":255 + }, + "nullable":true, + "default":null + }, + { + "name":"age", + "dataType":{ + "mysqlType":"int", + "charset":"binary", + "collate":"binary", + "length":11 + }, + "nullable":true, + "default":null + }, + { + "name":"score", + "dataType":{ + "mysqlType":"float", + "charset":"binary", + "collate":"binary", + "length":12 + }, + "nullable":true, + "default":null + }, + { + "name":"createTime", + "dataType":{ + "mysqlType":"timestamp", + "charset":"binary", + "collate":"binary", + "length":19 + }, + "nullable":true, + "default":null + } + ], + "indexes":[ + { + "name":"primary", + "unique":true, + "primary":true, + "nullable":false, + "columns":[ + "id" + ] + } + ] + }, + "preTableSchema":{ + "schema":"simple", + "table":"user", + "tableID":148, + "version":447984074911121426, + "columns":[ + { + "name":"id", + "dataType":{ + "mysqlType":"int", + "charset":"binary", + "collate":"binary", + "length":11 + }, + "nullable":false, + "default":null + }, + { + "name":"name", + "dataType":{ + "mysqlType":"varchar", + "charset":"utf8mb4", + "collate":"utf8mb4_bin", + "length":255 + }, + "nullable":true, + "default":null + }, + { + "name":"age", + "dataType":{ + "mysqlType":"int", + "charset":"binary", + "collate":"binary", + "length":11 + }, + "nullable":true, + "default":null + }, + { + "name":"score", + "dataType":{ + "mysqlType":"float", + "charset":"binary", + "collate":"binary", + "length":12 + }, + "nullable":true, + "default":null + } + ], + "indexes":[ + { + "name":"primary", + "unique":true, + "primary":true, + "nullable":false, + "columns":[ + "id" + ] + } + ] + } +} +``` + +The fields in the preceding JSON data are explained as follows: + +| Field | Type | Description | +| ------------- | ------- | ------------------------------------------------------------- | +| `version` | Number | The version number of the protocol, which is currently `1`. | +| `type` | String | The DDL event type, including `CREATE`, `RENAME`, `CINDEX`, `DINDEX`, `ERASE`, `TRUNCATE`, `ALTER`, and `QUERY`. | +| `sql` | String | The DDL statement. | +| `commitTs` | Number | The commit timestamp when the DDL statement execution is completed in the upstream. | +| `buildTs` | Number | The UNIX timestamp when the message is successfully encoded within TiCDC. | +| `tableSchema` | Object | The current schema information of the table. For more information, see [TableSchema definition](#tableschema-definition). | +| `preTableSchema` | Object | The schema information of the table before the DDL statement is executed. All DDL events, except the `CREATE` type of DDL event, have this field. | + +### DML + +#### INSERT + +TiCEC encodes an `INSERT` event in the following JSON format: + +```json +{ + "version":1, + "database":"simple", + "table":"user", + "tableID":148, + "type":"INSERT", + "commitTs":447984084414103554, + "buildTs":1708923662983, + "schemaVersion":447984074911121426, + "data":{ + "age":"25", + "id":"1", + "name":"John Doe", + "score":"90.5" + } +} +``` + +The fields in the preceding JSON data are explained as follows: + +| Field | Type | Description | +| ------------- | ------- | --------------------------------------------------------- | +| `version` | Number | The version number of the protocol, which is currently `1`. | +| `database` | String | The name of the database. | +| `table` | String | The name of the table. | +| `tableID` | Number | The ID of the table. | +| `type` | String | The DML event type, including `INSERT`, `UPDATE`, and `DELETE`. | +| `commitTs` | Number | The commit timestamp when the DML statement execution is completed in the upstream. | +| `buildTs` | Number | The UNIX timestamp when the message is successfully encoded within TiCDC. | +| `schemaVersion` | Number | The schema version number of the table when the DML message is encoded. | +| `data` | Object | The inserted data, where the field name is the column name and the field value is the column value. | + +The `INSERT` event contains the `data` field, and does not contain the `old` field. + +#### UPDATE + +TiCDC encodes an `UPDATE` event in the following JSON format: + +```json +{ + "version":1, + "database":"simple", + "table":"user", + "tableID":148, + "type":"UPDATE", + "commitTs":447984099186180098, + "buildTs":1708923719184, + "schemaVersion":447984074911121426, + "data":{ + "age":"25", + "id":"1", + "name":"John Doe", + "score":"95" + }, + "old":{ + "age":"25", + "id":"1", + "name":"John Doe", + "score":"90.5" + } +} +``` + +The fields in the preceding JSON data are explained as follows: + +| Field | Type | Description | +| ------------- | ------- | --------------------------------------------------------- | +| `version` | Number | The version number of the protocol, which is currently `1`. | +| `database` | String | The name of the database. | +| `table` | String | The name of the table. | +| `tableID` | Number | The ID of the table. | +| `type` | String | The DML event type, including `INSERT`, `UPDATE`, and `DELETE`. | +| `commitTs` | Number | The commit timestamp when the DML statement execution is completed in the upstream. | +| `buildTs` | Number | The UNIX timestamp when the message is successfully encoded within TiCDC. | +| `schemaVersion` | Number | The schema version number of the table when the DML message is encoded. | +| `data` | Object | The data after updating, where the field name is the column name and the field value is the column value. | +| `old` | Object | The data before updating, where the field name is the column name and the field value is the column value. | + +The `UPDATE` event contains both the `data` and `old` fields, which represent the data after and before updating respectively. + +#### DELETE + +TiCDC encodes a `DELETE` event in the following JSON format: + +```json +{ + "version":1, + "database":"simple", + "table":"user", + "tableID":148, + "type":"DELETE", + "commitTs":447984114259722243, + "buildTs":1708923776484, + "schemaVersion":447984074911121426, + "old":{ + "age":"25", + "id":"1", + "name":"John Doe", + "score":"95" + } +} +``` + +The fields in the preceding JSON data are explained as follows: + +| Field | Type | Description | +| ------------- | ------- | --------------------------------------------------------- | +| `version` | Number | The version number of the protocol, which is currently `1`. | +| `database` | String | The name of the database. | +| `table` | String | The name of the table. | +| `tableID` | Number | The ID of the table. | +| `type` | String | The DML event type, including `INSERT`, `UPDATE`, and `DELETE`. | +| `commitTs` | Number | The commit timestamp when the DML statement execution is completed in the upstream. | +| `buildTs` | Number | The UNIX timestamp when the message is successfully encoded within TiCDC. | +| `schemaVersion` | Number | The schema version number of the table when the DML message is encoded. | +| `old` | Object | The deleted data, where the field name is the column name and the field value is the column value. | + +The `DELETE` event contains the `old` field, and does not contain the `data` field. + +### WATERMARK + +TiCDC encodes a `WATERMARK` event in the following JSON format: + +```json +{ + "version":1, + "type":"WATERMARK", + "commitTs":447984124732375041, + "buildTs":1708923816911 +} +``` + +The fields in the preceding JSON data are explained as follows: + +| Field | Type | Description | +| ------------- | ------- | --------------------------------------------------------- | +| `version` | Number | The version number of the protocol, which is currently `1`. | +| `type` | String | The `WATERMARK` event type. | +| `commitTs` | Number | The commit timestamp of the `WATERMARK`. | +| `buildTs` | Number | The UNIX timestamp when the message is successfully encoded within TiCDC. | + +### BOOTSTRAP + +TiCDC encodes a `BOOTSTRAP` event in the following JSON format: + +```json +{ + "version":1, + "type":"BOOTSTRAP", + "commitTs":0, + "buildTs":1708924603278, + "tableSchema":{ + "schema":"simple", + "table":"new_user", + "tableID":148, + "version":447984074911121426, + "columns":[ + { + "name":"id", + "dataType":{ + "mysqlType":"int", + "charset":"binary", + "collate":"binary", + "length":11 + }, + "nullable":false, + "default":null + }, + { + "name":"name", + "dataType":{ + "mysqlType":"varchar", + "charset":"utf8mb4", + "collate":"utf8mb4_bin", + "length":255 + }, + "nullable":true, + "default":null + }, + { + "name":"age", + "dataType":{ + "mysqlType":"int", + "charset":"binary", + "collate":"binary", + "length":11 + }, + "nullable":true, + "default":null + }, + { + "name":"score", + "dataType":{ + "mysqlType":"float", + "charset":"binary", + "collate":"binary", + "length":12 + }, + "nullable":true, + "default":null + } + ], + "indexes":[ + { + "name":"primary", + "unique":true, + "primary":true, + "nullable":false, + "columns":[ + "id" + ] + } + ] + } +} +``` + +The fields in the preceding JSON data are explained as follows: + +| Field | Type | Description | +| ------------- | ------- | --------------------------------------------------------- | +| `version` | Number | The version number of the protocol, which is currently `1`. | +| `type` | String | The `BOOTSTRAP` event type. | +| `commitTs` | Number | The `commitTs` of the `BOOTSTRAP` is `0`. Because it is generated internally by TiCDC, its `commitTs` is meaningless. | +| `buildTs` | Number | The UNIX timestamp when the message is successfully encoded within TiCDC. | +| `tableSchema` | Object | The schema information of the table. For more information, see [TableSchema definition](#tableschema-definition). | + +## Message generation and sending rules + +### DDL + +- Generation time: TiCDC sends a DDL event after all transactions before this DDL event have been sent. +- Destination: TiCDC sends DDL events to all partitions of the corresponding topic. + +### DML + +- Generation time: TiCDC sends DML events in the order of the `commitTs` of the transaction. +- Destination: TiCDC sends DDL events to the corresponding partition of the corresponding topic according to the user-configured dispatch rules. + +### WATERMARK + +- Generation time: TiCDC sends `WATERMARK` events periodically to mark the replication progress of a changefeed. The current interval is 1 second. +- Destination: TiCDC sends `WATERMARK` events to all partitions of the corresponding topic. + +### BOOTSTRAP + +- Generation time: + - After creating a new changefeed, before the first DML event of a table is sent, TiCDC sends a `BOOTSTRAP` event to the downstream to build the table schema. + - Additionally, TiCDC sends `BOOTSTRAP` events periodically to allow newly joined consumers to build the table schema. The default interval is 120 seconds or every 10000 messages. You can adjust the sending interval by configuring the `send-bootstrap-interval-in-sec` and `send-bootstrap-in-msg-count` parameters in the `sink` configuration. + - If a table does not receive any new DML messages within 30 minutes, the table is considered inactive. TiCDC stops sending `BOOTSTRAP` events for the table until new DML events are received. +- Destination: By default, TiCDC sends `BOOTSTRAP` events to all partitions of the corresponding topic. You can adjust the sending strategy by configuring the `send-bootstrap-to-all-partition` parameter in the sink configuration. + +## Message consumption methods + +Because the TiCDC Simple protocol does not include the schema information of the table when sending a DML message, the downstream needs to receive the DDL or BOOTSTRAP message and cache the schema information of the table before consuming a DML message. When receiving a DML message, the downstream obtains the corresponding table schema information from the cache by searching the `table` name and `schemaVersion` fields of the DML message, and then correctly consumes the DML message. + +The following describes how the downstream consumes DML messages based on DDL or BOOTSTRAP messages. According to preceding descriptions, the following information is known: + +- Each DML message contains a `schemaVersion` field to mark the schema version number of the table corresponding to the DML message. +- Each DDL message contains a `tableSchema` and `preTableSchema` field to mark the schema information of the table before and after the DDL event. +- Each BOOTSTRAP message contains a `tableSchema` field to mark the schema information of the table corresponding to the BOOTSTRAP message. + +The consumption methods are introduced in the following two scenarios. + +### Scenario 1: The consumer starts consuming from the beginning + +In this scenario, the consumer starts consuming from the creation of a table, so the consumer can receive all DDL and BOOTSTRAP messages of the table. In this case, the consumer can obtain the schema information of the table through the `table` name and `schemaVersion` field of the DML message. The detailed process is as follows: + +![TiCDC Simple Protocol consumer scene 1](/media/ticdc/ticdc-simple-consumer-1.png) + +### Scenario 2: The consumer starts consuming from the middle + +When a new consumer joins the consumer group, it might start consuming from the middle, so it might miss earlier DDL and BOOTSTRAP messages of the table. In this case, the consumer might receive some DML messages before obtaining the schema information of the table. Therefore, the consumer needs to wait for a period of time until it receives the DDL or BOOTSTRAP message to obtain the schema information of the table. Because TiCDC sends BOOTSTRAP messages periodically, the consumer can always obtain the schema information of the table within a period of time. The detailed process is as follows: + +![TiCDC Simple Protocol consumer scene 2](/media/ticdc/ticdc-simple-consumer-2.png) + +## Reference + +### TableSchema definition + +TableSchema is a JSON object that contains the schema information of the table, including the table name, table ID, table version number, column information, and index information. The JSON message format is as follows: + +``` json +{ + "schema":"simple", + "table":"user", + "tableID":148, + "version":447984074911121426, + "columns":[ + { + "name":"id", + "dataType":{ + "mysqlType":"int", + "charset":"binary", + "collate":"binary", + "length":11 + }, + "nullable":false, + "default":null + }, + { + "name":"name", + "dataType":{ + "mysqlType":"varchar", + "charset":"utf8mb4", + "collate":"utf8mb4_bin", + "length":255 + }, + "nullable":true, + "default":null + }, + { + "name":"age", + "dataType":{ + "mysqlType":"int", + "charset":"binary", + "collate":"binary", + "length":11 + }, + "nullable":true, + "default":null + }, + { + "name":"score", + "dataType":{ + "mysqlType":"float", + "charset":"binary", + "collate":"binary", + "length":12 + }, + "nullable":true, + "default":null + } + ], + "indexes":[ + { + "name":"primary", + "unique":true, + "primary":true, + "nullable":false, + "columns":[ + "id" + ] + } + ] +} +``` + +The preceding JSON data is explained as follows: + +| Field | Type | Description | +| ---------- | ------ | ------------------------------------------------------------------- | +| `schema` | String | The name of the database. | +| `table` | String | The name of the table. | +| `tableID` | Number | The ID of the table. | +| `version` | Number | The schema version number of the table. | +| `columns` | Array | The column information, including the column name, data type, whether it can be null, and the default value. | +| `indexes` | Array | The index information, including the index name, whether it is unique, whether it is a primary key, and the index columns. | + +You can uniquely identify the schema information of a table by the table name and the schema version number. + +> **Note:** +> +> Due to the implementation limitations of TiDB, the schema version number of a table does not change when the `RENAME TABLE` DDL operation is executed. + +#### Column definition + +Column is a JSON object that contains the schema information of the column, including the column name, data type, whether it can be null, and the default value. + +```json +{ + "name":"id", + "dataType":{ + "mysqlType":"int", + "charset":"binary", + "collate":"binary", + "length":11 + }, + "nullable":false, + "default":null +} +``` + +The preceding JSON data is explained as follows: + +| Field | Type | Description | +| ---------- | ------ | ------------------------------------------------------------------- | +| `name` | String | The name of the column. | +| `dataType` | Object | The data type information, including the MySQL data type, character set, collation, and field length. | +| `nullable` | Boolean | Whether the column can be null. | +| `default` | String | The default value of the column. | + +#### Index definition + +Index is a JSON object that contains the schema information of the index, including the index name, whether it is unique, whether it is a primary key, and the index column. + +```json +{ + "name":"primary", + "unique":true, + "primary":true, + "nullable":false, + "columns":[ + "id" + ] +} +``` + +The preceding JSON data is explained as follows: + +| Field | Type | Description | +| ---------- | ------ | ------------------------------------------------------------------- | +| `name` | String | The name of the index. | +| `unique` | Boolean | Whether the index is unique. | +| `primary` | Boolean | Whether the index is a primary key. | +| `nullable` | Boolean | Whether the index can be null. | +| `columns` | Array | The column names included in the index. | + +### mysqlType reference table + +The following table describes the value range of the `mysqlType` field in the TiCDC Simple protocol and its type in TiDB (Golang) and Avro (Java). When you need to parse DML messages, you can correctly parse the data according to this table and the `mysqlType` field in the DML message, depending on the protocol and language you use. + +**TiDB type (Golang)** represents the type of the corresponding `mysqlType` when it is processed in TiDB and TiCDC (Golang). **Avro type (Java)** represents the type of the corresponding `mysqlType` when it is encoded into Avro format messages. + +| mysqlType | Value range | TiDB type (Golang) | Avro type (Java) | +| --- | --- | --- | --- | +| tinyint | [-128, 127] | int64 | long | +| tinyint unsigned | [0, 255] | uint64 | long | +| smallint | [-32768, 32767] | int64 | long | +| smallint unsigned | [0, 65535] | uint64 | long | +| mediumint | [-8388608, 8388607] | int64 | long | +| mediumint unsigned | [0, 16777215] | uint64 | long | +| int | [-2147483648, 2147483647] | int64 | long | +| int unsigned | [0, 4294967295] | uint64 | long | +| bigint | [-9223372036854775808, 9223372036854775807] | int64 | long | +| bigint unsigned | [0, 9223372036854775807] | uint64 | long | +| bigint unsigned | [9223372036854775808, 18446744073709551615] | uint64 | string | +| float | / | float32 | float | +| double | / | float64 | double | +| decimal | / | string | string | +| varchar | / | []uint8 | string | +| char | / | []uint8 | string | +| varbinary | / | []uint8 | bytes | +| binary | / | []uint8 | bytes | +| tinytext | / | []uint8 | string | +| text | / | []uint8 | string | +| mediumtext | / | []uint8 | string | +| longtext | / | []uint8 | string | +| tinyblob | / | []uint8 | bytes | +| blob | / | []uint8 | bytes | +| mediumblob | / | []uint8 | bytes | +| longblob | / | []uint8 | bytes | +| date | / | string | string | +| datetime | / | string | string | +| timestamp | / | string | string | +| time | / | string | string | +| year | / | int64 | long | +| enum | / | uint64 | long | +| set | / | uint64 | long | +| bit | / | uint64 | long | +| json | / | string | string | +| bool | / | int64 | long | + +### Avro schema definition + +The Simple protocol supports outputting messages in Avro format. For details about the Avro format, see [Simple Protocol Avro Schema](https://github.com/pingcap/tiflow/blob/master/pkg/sink/codec/simple/message.json). From e3623db8b970695dc716daa53a05036061e7ee36 Mon Sep 17 00:00:00 2001 From: Grace Cai Date: Mon, 25 Mar 2024 14:44:16 +0800 Subject: [PATCH 73/82] pd: support pd microservices (#16803) --- TOC.md | 1 + pd-microservices.md | 81 +++++++++++++++++++++++++++++++++++++++++ tiup/tiup-playground.md | 13 +++++++ 3 files changed, 95 insertions(+) create mode 100644 pd-microservices.md diff --git a/TOC.md b/TOC.md index e24a3e3e943ed..4fc8ade65b8bd 100644 --- a/TOC.md +++ b/TOC.md @@ -328,6 +328,7 @@ - [Use Load Base Split](/configure-load-base-split.md) - [Use Store Limit](/configure-store-limit.md) - [DDL Execution Principles and Best Practices](/ddl-introduction.md) + - [Use PD Microservices](/pd-microservices.md) - TiDB Tools - [Overview](/ecosystem-tool-user-guide.md) - [Use Cases](/ecosystem-tool-user-case.md) diff --git a/pd-microservices.md b/pd-microservices.md new file mode 100644 index 0000000000000..4b7800223a14a --- /dev/null +++ b/pd-microservices.md @@ -0,0 +1,81 @@ +--- +title: PD Microservices +summary: Learn how to enable the microservice mode of PD to improve service quality. +--- + +# PD Microservices + +Starting from v8.0.0, PD supports the microservice mode, which splits the timestamp allocation and cluster scheduling functions of PD into the following two independently deployed microservices. In this way, these two functions are decoupled from the routing function of PD, which allows PD to focus on the routing service for metadata. + +- `tso` microservice: provides monotonically increasing timestamp allocation for the entire cluster. +- `scheduling` microservice: provides scheduling functions for the entire cluster, including but not limited to load balancing, hot spot handling, replica repair, and replica placement. + +Each microservice is deployed as an independent process. If you configure more than one replica for a microservice, the microservice automatically implements a primary-secondary fault-tolerant mode to ensure high availability and reliability of the service. + +> **Warning:** +> +> Currently, the PD microservices feature is experimental. It is not recommended that you use it in production environments. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/tikv/pd/issues) on GitHub. + +## Usage scenarios + +PD microservices are typically used to address performance bottlenecks in PD and improve PD service quality. With this feature, you can avoid the following issues: + +- Long-tail latency or jitter in TSO allocations due to excessive pressure in PD clusters +- Service unavailability of the entire cluster due to failures in the scheduling module +- Bottleneck issues solely caused by PD + +In addition, when the scheduling module is changed, you can update the `scheduling` microservice independently without restarting PD, thus avoiding any impact on the overall service of the cluster. + +> **Note:** +> +> If the performance bottleneck of a cluster is not caused by PD, there is no need to enable microservices, because using microservices increases the number of components and raises operational costs. + +## Restrictions + +- Currently, the `tso` microservice does not support dynamic start and stop. After enabling or disabling the `tso` microservice, you need to restart the PD cluster for the changes to take effect. +- Only the TiDB component supports a direct connection to the `tso` microservice through service discovery, while other components need to forward requests to the `tso` microservice through PD to obtain timestamps. +- Microservices are not compatible with the [Data Replication Auto Synchronous (DR Auto-Sync)](/two-data-centers-in-one-city-deployment.md) feature. +- Microservices are not compatible with the TiDB system variable [`tidb_enable_tso_follower_proxy`](/system-variables.md#tidb_enable_tso_follower_proxy-new-in-v530). +- Because [hibernate Regions](/tikv-configuration-file.md#hibernate-regions) might exist in a cluster, during a primary and secondary switchover of the `scheduling` microservice, the scheduling function of the cluster might be unavailable for a certain period (up to [`peer-stale-state-check-interval`](/tikv-configuration-file.md#peer-stale-state-check-interval), which is five minutes by default) to avoid redundant scheduling. + +## Usage + +Currently, PD microservices can be deployed using TiDB Operator or TiUP Playground. + + +