MySQL执行CREATE TABLE SELECT建表报Incorrect string value错误
问题现象
- 执行以下SQL,基于
performance_schema.events_statements_history_long表创建新表时触发错误:
create table history select * from performance_schema.events_statements_history_long
- 具体报错信息如下:
Incorrect string value: '\xF0\x9F\x9F\xA8\xE8\xAD...' for column 'SQL_TEXT' at row 1108
- 排查时执行以下语句查询数据库字符集配置:
SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
查询结果初始显示character_set_client、character_set_connection、character_set_database、character_set_results、character_set_server、character_set_system均为utf8,对应collation_connection、collation_database、collation_server均为utf8_general_ci。多次调整配置后问题未解决,即使将字符集切换为utf8mb4,报错仍然存在。
问题根因
- 初始报错的直接原因:MySQL中名称为
utf8的字符集实际是utf8mb3,仅支持最大3字节长度的UTF-8字符,而报错信息中的\xF0\x9F\x9F\xA8是占4字节长度的UTF-8字符(常见为emoji、Unicode补充平面生僻字符),utf8mb3无对应编码映射,无法存储这类字符,因此触发写入错误。 - 切换
utf8mb4后仍报错的核心原因:- 部分场景下调整字符集仅修改了全局参数,未同步更新当前会话的字符集配置,或修改后未重新执行创表操作,会话仍沿用旧的
utf8mb3字符集规则。 CREATE TABLE ... SELECT的隐式建表逻辑存在局限:通过该语法自动生成目标表结构时,字符串列的字符集不会自动适配调整后的库/服务端默认字符集,也不会完整继承performance_schema系统表的列属性,很容易出现目标表SQL_TEXT列的字符集仍停留在utf8mb3的情况,即使库、服务端层面配置为utf8mb4,列级字符集不匹配依然会触发写入报错。
- 部分场景下调整字符集仅修改了全局参数,未同步更新当前会话的字符集配置,或修改后未重新执行创表操作,会话仍沿用旧的
修复方案
- 放弃
CREATE TABLE ... SELECT的简写创表方式,改为先显式建表、指定正确字符集后再导入数据,参考执行语句:
-- 基于源表结构生成初始目标表 CREATE TABLE history LIKE performance_schema.events_statements_history_long; -- 将目标表所有字符串列统一转换为utf8mb4字符集,排序规则可根据实际MySQL版本选择 ALTER TABLE history CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 统一当前会话字符集配置 SET NAMES utf8mb4; -- 插入源表数据 INSERT INTO history SELECT * FROM performance_schema.events_statements_history_long;
内容的提问来源于stack exchange,提问作者zheng bo
相关产品推荐
相关产品推荐

