暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

OceanBase 字段扩容避坑:字符集变更导致 DDL 失败

27

作者:吕虎桥,爱可生 DBA 团队成员,主要负责 DMP 平台和 MySQL 数据库的日常运维及故障处理。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 1100 字,预计阅读需要 3 分钟。


1. 背景

程序报错提示长度超过列长,需要扩容字段长度。在执行修改的时候报错 ERROR 1235 (0A000): Alter charset or collation type not supported
,提示不支持字符集或排序规则变更。

数据库版本:OceanBase 3.2.3.0

2. 复现步骤

2.1 新建表

create table user_info (
idbigintnotnull auto_increment primary keyCOMMENT'自增主键',
user_name varchar(30CHARACTERSET utf8mb4 COLLATE utf8mb4_bin DEFAULTNULLCOMMENT'用户名',
address varchar(200COMMENT'地址',
create_time datetime defaultcurrent_timestampCOMMENT'创建时间',
update_time datetime defaultcurrent_timestamponupdatecurrent_timestampCOMMENT'更新时间'
)defaultcharset utf8mb4;

复制

2.2 修改表结构

MySQL [mydb]> alter table user_info modify user_name varchar(50);
ERROR 1235 (0A000): Alter charset or collation type not supported

复制

3. 问题分析

3.1 查看 MySQL 租户默认的字符集和排序规则

MySQL [mydb]> show variableslike'%character%';
+--------------------------+---------+
| Variable_name            | Value   |
+--------------------------+---------+
| character_set_client     | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database   | utf8mb4 |
| character_set_filesystem | binary  |
| character_set_results    | utf8mb4 |
| character_set_server     | utf8mb4 |
| character_set_system     | utf8mb4 |
+--------------------------+---------+
7 rows in set (0.003 sec)

MySQL [mydb]> showvariableslike'%collation%';
+----------------------+--------------------+
| Variable_name        | Value              |
+----------------------+--------------------+
| collation_connection | utf8mb4_general_ci |
| collation_database   | utf8mb4_general_ci |
| collation_server     | utf8mb4_general_ci |
+----------------------+--------------------+

复制

3.2 查看表和字段默认字符集、排序规则

--查看表的默认字符集、排序规则
SELECT TABLE_NAME, CCSA.character_set_name AScharset, CCSA.collation_name AScollation
FROM INFORMATION_SCHEMA.TABLES T
    JOIN INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY CCSA
    ON T.table_collation = CCSA.collation_name
WHERE T.table_name = 'user_info';

+------------+---------+--------------------+
| TABLE_NAME | charset | collation          |
+------------+---------+--------------------+
| user_info  | utf8mb4 | utf8mb4_general_ci |
+------------+---------+--------------------+

--查看列默认字符集、排序规则
SELECT COLUMN_NAME, CHARACTER_SET_NAME AScharset, COLLATION_NAME AScollation
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'user_info'AND TABLE_SCHEMA = 'mydb';

+-------------+---------+--------------------+
| COLUMN_NAME | charset | collation          |
+-------------+---------+--------------------+
| id          | binary  | binary             |
| user_name   | utf8mb4 | utf8mb4_bin        |
| address     | utf8mb4 | utf8mb4_general_ci |
| create_time | binary  | binary             |
| update_time | binary  | binary             |
+-------------+---------+--------------------+

复制

3.3 问题原因

在字段扩容的时候,没有声明列的排序规则,会自动继承表的排序规则 --> utf8mb4_general_ci
,需要把列排序规则从 utf8mb4_bin
 转换为 utf8mb4_general_ci
,但是 OceanBase 3.2.3 不支持在线修改表的字符集、排序规则,更多参考[1]

3.4 解决方法

修改列的时候声明列的字符集、排序规则。

MySQL [mydb]> alter table user_info modify user_name varchar(50CHARACTERSET utf8mb4 COLLATE utf8mb4_bin DEFAULTNULLCOMMENT'用户名' ;
Query OK, 0 rows affected (0.050 sec)

MySQL [mydb]> showcreatetable user_info\G
*************************** 1.row ***************************
       Table: user_info
CreateTableCREATETABLE`user_info` (
`id`bigint(20NOTNULL AUTO_INCREMENT COMMENT'自增主键',
`user_name`varchar(50CHARACTERSET utf8mb4 COLLATE utf8mb4_bin DEFAULTNULLCOMMENT'用户名',
`address`varchar(200DEFAULTNULLCOMMENT'地址',
`create_time` datetime DEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',
`update_time` datetime DEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'更新时间',
  PRIMARY KEY (`id`)
) AUTO_INCREMENT = 1DEFAULTCHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0
1rowinset (0.009 sec)

复制

4. 在 OceanBase 4.2.1 版本验证

--查看数据库版本
MySQL [mydb]> select @@version;
+---------------------------+
| @@version                 |
+---------------------------+
| 5.7.25-OceanBase-v4.2.1.4 |
+---------------------------+

--修改列长度
MySQL [mydb]> alter table user_info modify user_name varchar(50) ;
Query OK, 0 rows affected (1.706 sec)

复制

在 OceanBase 4.2.1 版本,字段长度扩容成功,列排序规则发生了变更,从 utf8mb4_bin
 变更为 utf8mb4_general_ci

SELECT COLUMN_NAME, CHARACTER_SET_NAME AScharset, COLLATION_NAME AScollation
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'user_info'AND TABLE_SCHEMA = 'mydb';

+-------------+---------+--------------------+
| COLUMN_NAME | charset | collation          |
+-------------+---------+--------------------+
| id          | NULL    | NULL               |
| user_name   | utf8mb4 | utf8mb4_general_ci |
| address     | utf8mb4 | utf8mb4_general_ci |
| create_time | NULL    | NULL               |
| update_time | NULL    | NULL               |
+-------------+---------+--------------------+

复制

查看 OceanBase 官网,在 OceanBase 4.2.1 版本中列字段扩容属于 Online DDL[2],可以直接变更。但是这样就产生了一个潜在的风险,列排序规则变更为 utf8mb4_general_ci
 会忽略大小写,可能会影响数据的一致性。

MySQL [mydb]> insert into user_info (user_name,address) values ('Alice','上海');
Query OK, 1 row affected (0.051 sec)

MySQL [mydb]> insert into user_info (user_name,address) values ('alice','上海');
Query OK, 1 row affected (0.027 sec)

MySQL [mydb]> select * from user_info where user_name='alice';
+----+-----------+---------+---------------------+---------------------+
| id | user_name | address | create_time         | update_time         |
+----+-----------+---------+---------------------+---------------------+
|  1 | Alice     | 上海    | 2025-03-18 14:17:25 | 2025-03-18 14:17:25 |
|  2 | alice     | 上海    | 2025-03-18 14:17:29 | 2025-03-18 14:17:29 |
+----+-----------+---------+---------------------+---------------------+

复制

5. 总结

在字段扩容时,如果原列已声明字符集和排序规则,应确保扩容后的列与原列保持一致。这不仅适用于不同版本的 OceanBase 数据库,还能避免字符集或因排序规则变更带来的潜在问题。

参考资料
[1] 

ERROR 1235: https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000207750

[2] 

Online DDL: https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000000252799


本文关键字:#OceanBase# #字段扩容# #字符集#





带宽被 OBServer 备份 “榨干”,集群陷入 “无主” 危机
OBLogProxy 在 Binlog 模式下的故障案例解析
计算 OceanBase 可用 CPU 的核心逻辑


✨ Github:https://github.com/actiontech/sqle

📚 文档:https://actiontech.github.io/sqle-docs/

💻 官网:https://opensource.actionsky.com/sqle/

👥 微信群:请添加小助手加入 ActionOpenSource

🔗 商业支持:https://www.actionsky.com/sqle


文章转载自爱可生开源社区,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论