二进制列为什么需要它
BINARY、VARBINARY、BLOB、BIT 这类列存的是原始字节,mysqldump 默认会把字节直接写进文本文件。遇到空字节、换行或与当前字符集冲突的序列时,可能被字符集转换环节改写,恢复后数据校验不过。--hex-blob 让这些列以十六进制字面量输出,导入时由服务端还原字节,与字符集设置无关。
基本信息
| 适用平台 | MySQL 5.7 / 8.0 的 mysqldump,mariadb-dump 同名选项 |
|---|---|
| 影响列类型 | BINARY、VARBINARY、BLOB 系列、BIT |
| 输出形式 | 0x 开头的十六进制字面量 |
| 体积代价 | 这些列约为原来的两倍,压缩后差距明显缩小 |
| 配合项 | --default-character-set 明确字符集,--single-transaction 保证一致性 |
| 恢复行为 | 由服务端解析十六进制,不依赖客户端字符集 |
典型使用场景
- 表里存图片、加密字段、二进制主键,恢复后要做逐行校验
- 跨字符集迁移:源库 latin1、目标库 utf8mb4,避免字节被转换
- 备份文件还要经过压缩、拆分或对象存储中转,要求字节确定
- BIT 标记列在恢复后出现取值异常,需要换成十六进制输出
- 长期归档脚本希望在不同客户端版本下行为一致
二进制安全备份
二进制安全备份
# 常规备份:显式字符集 + 一致性快照
mysqldump -uroot -p --hex-blob --single-transaction --default-character-set=utf8mb4 \
--databases appdb > appdb.sql
# 按表拆分导出,便于定位出问题的表
for t in $(mysql -N -B -e "SELECT table_name FROM information_schema.tables \
WHERE table_schema='appdb' AND table_type='BASE TABLE'"); do
mysqldump -uroot -p --hex-blob --single-transaction appdb "$t" > "appdb.$t.sql"
done
# 边导边压缩,归档体积更友好
mysqldump -uroot -p --hex-blob --single-transaction appdb | zstd -o appdb.sql.zst
# 恢复后逐表比对校验和
mysql -uroot -p -D appdb < appdb.sql
mysql -uroot -p -e "CHECKSUM TABLE appdb.t_blob;"列类型导出表现
| 列类型 | 默认导出 | --hex-blob 之后 |
|---|---|---|
| BINARY(16) | 原始字节,可能被字符集环节改写 | 0x 十六进制字面量 |
| BLOB | 原样写入,含控制字符 | 0x 十六进制字面量 |
| VARBINARY | 字节流直接落盘 | 0x 十六进制字面量 |
| BIT | 输出形式不统一,恢复易出偏差 | 统一为十六进制字面量 |
| TEXT / VARCHAR | 按字符集转义,不受影响 | 不受影响 |
体积翻倍听起来吓人,但十六进制文本的压缩率很高,边导边压缩之后与原始备份的体积差距有限;对含二进制列的库,这个选项带来的确定性远比省下的那点空间重要。
十六进制只是输出编码,不是脱敏或加密:dump 文件里的二进制内容仍可被原样还原。落地到对象存储或传给第三方之前,仍需加密与访问控制。