From 4c8aa5459dfd51355ac650283a6a7a94db0d2288 Mon Sep 17 00:00:00 2001 From: 2995840376 <2995840376@xiaomi.com> Date: Wed, 28 Oct 2026 08:55:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(N):=20V27=20=E9=80=9A=E7=94=A8=E5=9B=9E?= =?UTF-8?q?=E8=BD=AC=E4=BF=AE=E5=A4=8D=E5=8E=86=E5=8F=B2=E9=81=97=E7=95=99?= =?UTF-8?q?=E7=9A=84=E5=8F=8C=E9=87=8D=E7=BC=96=E7=A0=81=E4=B8=AD=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: V26 只按 code 修好了 8 条预设品类, V25 回填的 2210/4120 备注仍是乱码; 全库体检还发现 V22 迁移写入的 platform_type 字典表 8 条名称/备注全部双重编码。 修法: 用 CONVERT(CAST(CONVERT(col USING latin1) AS BINARY) USING utf8mb4) 把 latin1 误解后的字符转回原始字节再按 utf8mb4 重新解释; 仅对 HEX 含 C2xx/C3xx 特征的值生效, 修完不再命中, 因此幂等可重复执行; platform_type 表做存在性判断, 旧结构库也能整段跑完。 验证: 生产 remaining_mojibake=0; 品类接口返回字节为正确 UTF-8(照明=e785a7e6988e); platform_type 涂鸦智能=e6b682e9b8a6e699bae883bd。 --- .../sql/V27__fix_mojibake_history_data.sql | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 backend/sql/V27__fix_mojibake_history_data.sql diff --git a/backend/sql/V27__fix_mojibake_history_data.sql b/backend/sql/V27__fix_mojibake_history_data.sql new file mode 100644 index 0000000..9377cda --- /dev/null +++ b/backend/sql/V27__fix_mojibake_history_data.sql @@ -0,0 +1,46 @@ +-- ===================================================================== +-- V27 · 修复历史遗留的双重编码中文(通用回转) +-- --------------------------------------------------------------------- +-- 现象:后台「品类管理」备注、以及「平台类型」字典的名称/备注显示乱码。 +-- +-- 成因:V22 / V25 迁移执行时,服务器 mysql 客户端 character_set_client 为 latin1 +-- (容器 C locale),UTF-8 字节被按 latin1 解读后再存入 utf8mb4 列 +-- → 中文双重编码("涂鸦智能" 变成 C3A6C2B6E2809A...)。 +-- +-- 治本(已完成,后续迁移不会再犯): +-- - deploy-all.bat 的 mysql 调用已加 --default-character-set=utf8mb4; +-- - V25 / V26 脚本首行已加 SET NAMES utf8mb4。 +-- 本脚本负责把历史数据修回来。 +-- +-- 修法:把 latin1 误解后的字符按 latin1 转回原始字节,再按 utf8mb4 重新解释: +-- CONVERT(CAST(CONVERT(col USING latin1) AS BINARY) USING utf8mb4) +-- 幂等:仅对仍含双重编码特征(HEX 含 C2xx / C3xx)的值生效,修完不再命中。 +-- +-- 无存储过程、无 DELIMITER;幂等可重复执行。 +-- ===================================================================== + +SET NAMES utf8mb4; + +-- ---------- 1) 平台类型字典(V22 写入;表可能不存在,做存在性判断) ---------- +SET @has_pt = (SELECT COUNT(*) FROM information_schema.TABLES + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'platform_type'); +SET @s = IF(@has_pt > 0, + 'UPDATE platform_type + SET name = CONVERT(CAST(CONVERT(name USING latin1) AS BINARY) USING utf8mb4), + remark = CONVERT(CAST(CONVERT(remark USING latin1) AS BINARY) USING utf8mb4), + update_time = NOW() + WHERE deleted = 0 + AND (HEX(IFNULL(name, '''')) REGEXP ''C[23][0-9A-F]{2}'' + OR HEX(IFNULL(remark, '''')) REGEXP ''C[23][0-9A-F]{2}'')', + 'SELECT ''platform_type table not found, skipped'' AS info'); +PREPARE stmt FROM @s; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- ---------- 2) 品类字典备注(V25 回填历史品类时写入) ---------- +UPDATE product_category + SET remark = CONVERT(CAST(CONVERT(remark USING latin1) AS BINARY) USING utf8mb4), + update_time = NOW() + WHERE deleted = 0 + AND HEX(IFNULL(remark, '')) REGEXP 'C[23][0-9A-F]{2}'; +