升级与升级后常见问题
本文介绍 TiDB 升级与升级后的常见问题与解决办法。
升级常见问题
本小节列出了 TiDB 升级相关的常见问题与解决办法。
滚动升级有那些影响?
滚动升级 TiDB 期间,业务运行会受到一定影响。因此,不建议在业务高峰期进行滚动升级。需要配置最小集群拓扑 (TiDB * 2、PD * 3、TiKV * 3),如果集群环境中有 Pump 和 Drainer 服务,建议先停止 Drainer,然后滚动升级(升级 TiDB 时会升级 Pump)。
集群在执行 DDL 请求期间可以进行升级操作吗?
如果升级前 TiDB 的版本低于 v7.1.0:
集群中有 DDL 语句正在被执行时(通常为
ADD INDEX
和列类型变更等耗时较久的 DDL 语句),请勿进行升级操作。在升级前,建议使用ADMIN SHOW DDL
命令查看集群中是否有正在进行的 DDL Job。如需升级,请等待 DDL 执行完成或使用ADMIN CANCEL DDL
命令取消该 DDL Job 后再进行升级。在升级 TiDB 集群的过程中,请勿执行 DDL 语句,否则可能会出现行为未定义的问题。
如果升级前 TiDB 的版本为 v7.1.0 或更高的版本:
- 不用遵循限制低版本升级时的限制,即在升级时可以接收用户 DDL 任务。建议参考平滑升级 TiDB。
Binary 如何升级?
不推荐使用 Binary 来升级集群。建议使用 TiUP 升级 TiDB 进行升级,确保分布式系统版本一致性和兼容性。
升级后常见问题
本小节列出了一些升级后可能会遇到的问题与解决办法。
执行 DDL 操作时遇到的字符集 (charset) 问题
TiDB 在 v2.1.0 以及之前版本(包括 v2.0 所有版本)中,默认字符集是 UTF8。从 v2.1.1 开始,默认字符集变更为 UTF8MB4。如果在 v2.1.0 及之前版本中,建表时显式指定了 table 的 charset 为 UTF8,那么升级到 v2.1.1 之后,执行 DDL 操作可能会失败。
要避免该问题,需注意以下两个要点:
- 在 v2.1.3 之前,TiDB 不支持修改 column 的 charset。所以,执行 DDL 操作时,新 column 的 charset 需要和旧 column 的 charset 保持一致。
- 在 v2.1.3 之前,即使 column 的 charset 和 table 的 charset 不一样,
show create table
也不会显示 column 的 charset,但可以通过 HTTP API 获取 table 的元信息来查看 column 的 charset,下文提供了示例。
unsupported modify column charset utf8mb4 not match origin utf8
升级前:v2.1.0 及之前版本
create table t(a varchar(10)) charset=utf8;Query OK, 0 rows affected Time: 0.106sshow create table t+-------+-------------------------------------------------------+ | Table | Create Table | +-------+-------------------------------------------------------+ | t | CREATE TABLE `t` ( | | | `a` varchar(10) DEFAULT NULL | | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | +-------+-------------------------------------------------------+ 1 row in set Time: 0.006s升级后:v2.1.1、v2.1.2 会出现下面的问题,v2.1.3 以及之后版本不会出现下面的问题。
alter table t change column a a varchar(20);ERROR 1105 (HY000): unsupported modify column charset utf8mb4 not match origin utf8
解决方案:显式指定 column charset,保持和原来的 charset 一致即可。
alter table t change column a a varchar(22) character set utf8;
根据要点 1,此处如果不指定 column 的 charset,会用默认的 UTF8MB4,所以需要指定 column charset 保持和原来一致。
根据要点 2,用 HTTP API 获取 table 元信息,然后根据 column 名字和 Charset 关键字搜索即可找到 column 的 charset。
curl "http://$IP:10080/schema/test/t" | python -m json.tool这里用了 python 的格式化 json 的工具,也可以不加,此处只是为了方便注释。
{ "ShardRowIDBits": 0, "auto_inc_id": 0, "charset": "utf8", # table 的 charset "collate": "", "cols": [ # 从这里开始列举 column 的相关信息 { ... "id": 1, "name": { "L": "a", "O": "a" # column 的名字 }, "offset": 0, "origin_default": null, "state": 5, "type": { "Charset": "utf8", # column a 的 charset "Collate": "utf8_bin", "Decimal": 0, "Elems": null, "Flag": 0, "Flen": 10, "Tp": 15 } } ], ... }
unsupported modify charset from utf8mb4 to utf8
升级前:v2.1.1,v2.1.2
create table t(a varchar(10)) charset=utf8;Query OK, 0 rows affected Time: 0.109sshow create table t;+-------+-------------------------------------------------------+ | Table | Create Table | +-------+-------------------------------------------------------+ | t | CREATE TABLE `t` ( | | | `a` varchar(10) DEFAULT NULL | | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | +-------+-------------------------------------------------------+上面
show create table
只显示出了 table 的 charset,但其实 column 的 charset 是 UTF8MB4,这可以通过 HTTP API 获取 schema 来确认。这是一个 bug,即此处建表时 column 的 charset 应该要和 table 保持一致为 UTF8,该问题在 v2.1.3 中已经修复。升级后:v2.1.3 及之后版本
show create table t;+-------+--------------------------------------------------------------------+ | Table | Create Table | +-------+--------------------------------------------------------------------+ | t | CREATE TABLE `t` ( | | | `a` varchar(10) CHARSET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL | | | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | +-------+--------------------------------------------------------------------+ 1 row in set Time: 0.007salter table t change column a a varchar(20);ERROR 1105 (HY000): unsupported modify charset from utf8mb4 to utf8
解决方案:
因为在 v2.1.3 之后,TiDB 支持修改 column 和 table 的 charset,所以这里推荐修改 table 的 charset 为 UTF8MB4。
alter table t convert to character set utf8mb4;也可以像问题 1 一样指定 column 的 charset,保持和 column 原来的 charset (UTF8MB4) 一致即可。
alter table t change column a a varchar(20) character set utf8mb4;
ERROR 1366 (HY000): incorrect utf8 value f09f8c80(🌀) for column a
TiDB 在 v2.1.1 及之前版本中,如果 charset 是 UTF8,没有对 4-byte 的插入数据进行 UTF8 Unicode encoding 检查。在 v2.1.2
及之后版本中,添加了该检查。
升级前:v2.1.1 及之前版本
create table t(a varchar(100) charset utf8);Query OK, 0 rows affectedinsert t values (unhex('f09f8c80'));Query OK, 1 row affected升级后:v2.1.2 及之后版本
insert t values (unhex('f09f8c80'));ERROR 1366 (HY000): incorrect utf8 value f09f8c80(🌀) for column a
解决方案:
v2.1.2 版本:该版本不支持修改 column charset,所以只能跳过 UTF8 的检查。
set @@session.tidb_skip_utf8_check=1;Query OK, 0 rows affectedinsert t values (unhex('f09f8c80'));Query OK, 1 row affectedv2.1.3 及之后版本:建议修改 column 的 charset 为 UTF8MB4。或者也可以设置
tidb_skip_utf8_check
变量跳过 UTF8 的检查。如果跳过 UTF8 的检查,在需要将数据从 TiDB 同步回 MySQL 的时候,可能会失败,因为 MySQL 会执行该检查。alter table t change column a a varchar(100) character set utf8mb4;Query OK, 0 rows affectedinsert t values (unhex('f09f8c80'));Query OK, 1 row affected关于
tidb_skip_utf8_check
变量,具体来说是指跳过 UTF8 和 UTF8MB4 类型对数据的合法性检查。如果跳过这个检查,在需要将数据从 TiDB 同步回 MySQL 的时候,可能会失败,因为 MySQL 执行该检查。如果只想跳过 UTF8 类型的检查,可以设置tidb_check_mb4_value_in_utf8
变量。tidb_check_mb4_value_in_utf8
在 v2.1.3 版本加入config.toml
文件,可以修改配置文件里面的check-mb4-value-in-utf8
后重启集群生效。tidb_check_mb4_value_in_utf8
在 v2.1.5 版本开始可以用 HTTP API 来设置,也可以用 session 变量来设置。HTTP API(HTTP API 只在单台服务器上生效)
执行下列命令启用 HTTP API:
curl -X POST -d "check_mb4_value_in_utf8=1" http://{TiDBIP}:10080/settings执行下列命令禁用 HTTP API:
curl -X POST -d "check_mb4_value_in_utf8=0" http://{TiDBIP}:10080/settings
Session 变量
执行下列命令启用 Session 变量:
set @@session.tidb_check_mb4_value_in_utf8 = 1;执行下列命令禁用 Session 变量:
set @@session.tidb_check_mb4_value_in_utf8 = 0;
v2.1.7 及之后版本,如果对表和 column 的字符集没有严格要求为 UTF8,也不想修改客户端代码去跳过 UTF8 检查或者手动修改 column 的 charset,可以在配置文件中把
treat-old-version-utf8-as-utf8mb4
打开。该配置的作用是自动把 v2.1.7 版本之前创建的旧版本的表和 column 的 UTF8 字符集转成 UTF8MB4。这个转换是在 TiDB load schema 时在内存中将 UTF8 转成 UTF8MB4,不会对实际存储的数据做任何修改。在配置文件中关闭treat-old-version-utf8-as-utf8mb4
并重启 TiDB 后,以前字符集为 UTF8 的表和 column 的字符集仍然还是 UTF8。