根本原因是客户端与服务器在二进制数据编码、解析、缓冲三环节不一致:max_allowed_packet未协同配置(服务端设256M但Navicat未同步设置)、XML导出启用格式化导致Base64被换行截断、字符集协商失败使BLOB被误作文本转换,最终静默丢弃字节。

Navicat 跨平台传输 BLOB 字段发生数据截断,根本原因不是“传丢了”,而是客户端和服务器在二进制数据编码、解析、缓冲三个环节出现不一致,导致部分字节被静默丢弃或错误终止。
max_allowed_packet 不匹配是首要触发点
MySQL 服务端的 max_allowed_packet 和 Navicat 客户端实际使用的通信包上限必须协同调整。只改服务端配置(比如设成 256M)而忽略 Navicat 连接参数,导入时仍会按默认值(通常 4MB)切包——一旦某行 BLOB 数据解码后超过该阈值,MySQL 就直接截断并返回成功响应,你甚至看不到报错。
- 查当前生效值:执行
SHOW VARIABLES LIKE 'max_allowed_packet';,确认是全局值而非会话值 - Navicat 连接属性里要手动勾选「高级」→「使用自定义 max_allowed_packet」,填入与服务端一致的数值(单位是字节,
256M要写成268435456) - 注意:Linux 下 my.cnf 和 Windows 下 my.ini 的 [client] 段也要同步加
max_allowed_packet=256M,否则 Navicat 启动时读不到
XML 导出格式看似安全,实则暗藏编码陷阱
Navicat 默认用 XML 导出 BLOB,把二进制内容 Base64 编码进 标签。但问题在于:某些平台(尤其是旧版 Windows 或 Java 环境下的 Navicat)对 XML 解析器有行宽限制,默认每 1024 字符自动换行。Base64 编码后的长串被硬拆后,再导入时解析器可能把换行符当非法字符跳过,造成末尾字节丢失。
- 导出时在 Navicat「高级选项」中关闭「格式化 XML 输出」,避免插入多余空白和换行
- 不要依赖「自动检测编码」,导出 XML 前手动指定编码为
UTF-8 without BOM - 验证方式:用
base64 -d(Linux/macOS)或在线工具解码 XML 中任意一个内容,比对原始文件 SHA256
跨平台字符集协商失败导致 BLOB 被误当作文本处理
当源库和目标库字符集不一致(如源为 utf8mb4,目标为 latin1),且 Navicat 未显式指定连接字符集时,它可能把 BLOB 字段的二进制流当成文本流送入字符集转换管道。非可打印字节(如 0x89、0xFF)在转换中被替换为 ? 或直接丢弃,结果就是图片变花、PDF 打不开。
- 在 Navicat 连接属性 → 「高级」→ 「初始化命令」里添加:
SET NAMES utf8mb4 COLLATE utf8mb4_0900_ai_ci; - 确保目标表字段定义明确不含字符集,例如声明为
MEDIUMBLOB而非MEDIUMTEXT - 如果必须用 SQL 导出,禁用 Navicat 的「导出 BLOB 为十六进制」选项,改用
SELECT HEX(blob_col) FROM ...手动导出,再用UNHEX()导入
真正危险的不是报错,而是没报错却数据损坏。每次跨平台传输 BLOB 后,务必抽样校验原始文件与数据库中取出的二进制内容的哈希值——这是唯一能确认是否截断的手段。











