ERROR 1366 是因备份含 utf8mb4 编码的 emoji 或生僻字,而目标库为 utf8(utf8mb3)导致的字符集不兼容;需检查备份文件中 SET NAMES utf8mb4 或 DEFAULT CHARSET=utf8mb4,并确保目标库字符集匹配。
还原时提示 ERROR 1366: Incorrect string value
这是最常见字符集冲突现象:备份文件里有 utf8mb4 编码的 emoji 或生僻字,但目标库是 utf8(实际是 utf8mb3),mysql 拒绝写入。不是数据损坏,是编码不兼容。
- 先查备份 SQL 文件头或前几行,看有没有
SET NAMES utf8mb4或DEFAULT CHARSET=utf8mb4—— 如果有,目标库必须匹配 - 别用
mysql -u root db_name 硬怼,加 <code>--default-character-set=utf8mb4参数才生效 - 如果目标库只能用
utf8(比如老系统不敢动库级配置),还原前用sed或 Python 脚本批量替换utf8mb4为utf8,同时删掉COLLATE=utf8mb4_*字段(否则建表仍失败)
还原后中文变问号或乱码
根本原因不是备份错,而是客户端连接层没对齐:服务端是 utf8mb4,但你用的 mysql 命令、PHP mysqli 或 Python pymysql 连接时没显式指定字符集。
- 命令行还原务必加
--default-character-set=utf8mb4,漏掉这个参数,即使库和表都是 utf8mb4,数据也会被 MySQL 当作 latin1 解析再转存 - PHP 中用
mysqli_set_charset($conn, 'utf8mb4'),不能只靠SET NAMES;PDO 则要在 DSN 加;charset=utf8mb4 - 检查
SHOW VARIABLES LIKE 'character%',重点关注character_set_client、character_set_connection、character_set_results三个值是否全为utf8mb4
mysqldump 备份时没带字符集参数,还原就踩坑
默认情况下 mysqldump 不声明字符集,还原时完全依赖客户端环境,极不稳定。防勒索不是只靠加密,更是靠可重复还原 —— 而可重复的前提是字符集自包含。
- 备份命令必须加
--default-character-set=utf8mb4(注意不是--set-gtid-purged=OFF那种可选参数,这是刚需) - 如果库中混用多种字符集(比如某些日志表用
latin1),不要全局设一个,改用--skip-set-charset+ 手动在 SQL 头部补SET NAMES ...,否则mysqldump会强行统一成一个,导致部分表数据错乱 - 用
file backup.sql | head -20快速确认输出文件是否含SET NAMES utf8mb4和DEFAULT CHARSET=utf8mb4,没这两句等于没备份好
从被勒索快照还原,information_schema 里字符集显示正常但数据还是乱
勒索软件常清空或篡改 mysql 系统库,但不会动 information_schema(它是视图)。所以你看 SHOW CREATE TABLE 显示 CHARSET=utf8mb4,不代表真实存储格式没被破坏 —— 尤其当攻击者执行过 ALTER TABLE ... CONVERT TO CHARACTER SET latin1 后又删了日志。
- 别信
SHOW CREATE TABLE,直接查SELECT CCSA.character_set_name FROM information_schema.`COLUMNS` C, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA WHERE C.collation_name = CCSA.collation_name AND C.table_name = 'your_table' LIMIT 1 - 抽样导出几条中文数据用
hex()看原始字节:SELECT HEX(content) FROM your_table LIMIT 1,正常 utf8mb4 中文是 4 字节(如E4B8AD是“中”),如果变成3F3F3F(即???的 hex)说明已被转码污染过 - 这种情况下,备份文件本身可能已不可逆损坏,优先尝试从更早的、未被勒索影响的物理备份(如 LVM 快照、ZFS snapshot)还原











