You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL转换函数致数据丢失:如何避免Mojibake转Emoji时误删数据?

解决MySQL中Mojibake乱码恢复及避免数据截断问题

问题背景

数据库表内Emoji与外文字符全部变为Mojibake乱码,尝试执行以下语句恢复:

UPDATE table SET user_post = convert(cast(convert(user_post using latin1) as binary) using utf8mb4);

该语句多数场景有效,但导致大量数据被删除,同时抛出错误:

Invalid utf8 character string: 'FC6265'

在含50万条帖子的表中,约5万条数据受影响,最终只能回滚恢复数据库。需求为:转换遇到无效字符时避免数据删除,寻找更优的Mojibake还原函数(支持Emoji及正常字符)。


更新1:双重编码问题尝试

经HEX测试确认字符为双重编码,尝试以下查询:

UPDATE table SET description = IFNULL(CONVERT(CONVERT(CONVERT(description USING latin1) USING binary) USING utf8mb4), description );

执行后抛出错误并导致产品描述被截断:

Warning: #1300 Invalid utf8mb4 character string: 'A02047'

回滚后尝试ALTER方法(列已为utf8mb4,直接执行步骤3-5):

Step 3) ALTER TABLE table MODIFY description LONGTEXT CHARSET latin1;
Step 4) ALTER TABLE table MODIFY description LONGBLOB;
Step 5) ALTER TABLE table MODIFY description LONGTEXT CHARSET utf8mb4;

步骤3出现大量警告:

Warning: #1366 Incorrect string value: '\xE2\x86\x91\xE2\x86\x91...' for column 'description' at row 34882
Warning: #1366 Incorrect string value: '\xE2\x86\x91\xE2\x86\x93...' for column 'description' at row 45270
...

步骤5同样出现警告,且描述仍被截断:

Warning: #1366 Incorrect string value: '\xA0our m...' for column 'description' at row 20450
Warning: #1366 Incorrect string value: '\xA0</div...' for column 'description' at row 20484

更新2:硬空格清理尝试

为清理A0字符,执行以下语句:

UPDATE table SET description = UNHEX(REPLACE(HEX(description), 'A0', ''));

仍出现错误并导致内容截断:

Warning: #1366 Incorrect string value: '\xC2 GO F...' for column 'description' at row 1

数据库存储HTML格式字符串,推测截断由case.后的硬空格(对应HTML )导致:

<p><strong><span style="font-size:22px;"><span style="font-family:Arial, Helvetica, sans-serif;">It is covered by the case.  GO FIGURE ???</span></span></strong></p>

更新3:HEX值对比

更新前HEX:

3C703E3C7374726F6E673E3C7370616E207374796C653D22666F6E742D73697A653A323270783B223E3C7370616E207374796C653D22666F6E742D66616D696C793A417269616C2C2048656C7665746963612C2073616E732D73657269663B223E4E6F746520746865206C657474657265642065646765206973206E6F742076697369626C652E20497420697320636F76657265642062792074686520636173652EC2A020474F20464947555245203F3F3F3C2F7370616E3E3C2F7370616E3E3C2F7374726F6E673E3C2F703E

更新后HEX:

3C703E3C7374726F6E673E3C7370616E207374796C653D22666F6E742D73697A653A323270783B223E3C7370616E207374796C653D22666F6E742D66616D696C793A417269616C2C2048656C7665746963612C2073616E732D73657269663B223E497420697320636F76657265642062792074686520636173652E

解决方案

1. 前置操作:必做备份

所有操作前,务必全量备份目标表或数据库,避免不可逆数据损失。

2. 安全转换(避免截断/删除)

针对MySQL 8.0+版本

使用TRY_CONVERT函数,转换失败时保留原数据:

UPDATE your_table 
SET description = CASE 
    WHEN TRY_CONVERT(CONVERT(CONVERT(description USING latin1) USING binary) USING utf8mb4) IS NOT NULL 
    THEN TRY_CONVERT(CONVERT(CONVERT(description USING latin1) USING binary) USING utf8mb4)
    ELSE description 
END;

针对MySQL 5.7及以下版本

使用UPDATE IGNORE跳过转换错误的行,仅修改可正常转换的数据:

UPDATE IGNORE your_table 
SET description = CONVERT(CONVERT(CONVERT(description USING latin1) USING binary) USING utf8mb4);

或者先验证编码有效性,再执行更新:

UPDATE your_table 
SET description = CONVERT(CONVERT(CONVERT(description USING latin1) USING binary) USING utf8mb4)
WHERE VALIDATE_STRING(CONVERT(CONVERT(description USING latin1) USING binary), 'utf8mb4') = 1;

3. 处理硬空格(C2A0)问题

硬空格是UTF-8编码的非断空格(对应HTML&nbsp;),直接删除A0会破坏编码结构,需整体替换为普通空格:

UPDATE your_table 
SET description = REPLACE(description, UNHEX('C2A0'), ' ');

可结合编码转换,先处理硬空格再恢复乱码:

UPDATE IGNORE your_table 
SET description = CONVERT(CONVERT(REPLACE(CONVERT(description USING latin1), UNHEX('C2A0'), ' ') USING binary) USING utf8mb4);

4. 安全ALTER表方案

跳过转latin1的步骤,直接通过BLOB保留原始字节再转回utf8mb4,避免中间编码错误:

-- 先转BLOB,保留原始二进制数据
ALTER TABLE your_table MODIFY description LONGBLOB;
-- 再转utf8mb4,MySQL自动解析字节为正确编码
ALTER TABLE your_table MODIFY description LONGTEXT CHARSET utf8mb4;

内容的提问来源于stack exchange,提问作者peppy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 14:57:57