【问题标题】:Invalid UTF-8 in SQL dumpSQL 转储中的 UTF-8 无效
【发布时间】:2021-01-27 08:42:48
【问题描述】:

我有一个 MySQL 转储,它不是有效的 UTF-8。两个问题:

  1. 这可能是由某些使用 utf8mb3 aka MySQL 的 'utf8' 的数据库引起的吗?它确实使用了这种编码。
  2. 如果是这样,我该如何解决它,而无需访问 MySQL 来导入、更改表类型和重新导出?我可以使用任何编码转换工具吗?

编辑以添加无效 UTF-8 的特定数据:

uconv -f utf8 a.sql -o /dev/null

Conversion to Unicode from codepage failed at input byte position XXX. Bytes: ed Error: Illegal character found

这是一个十六进制示例。

xxd -s {XXX-16} -l 30 a.sql
YYY: 6e2e 203c 2f70 3e20 cfa1 ecaf a6eb 9ea0  n. </p> ........    
     aabb aabb aabb aabb aaaa bbbb bbaa aaaa
YYZ: edb6 b0e1 aea5 ee9e a027 2c27 3230       .........','20
     ^^^^ ^^

编辑 2:在上面添加了更多上下文。看起来问题序列符合UTF-8格式,它只是映射到不存在的U+1DDB0。

【问题讨论】:

  • 不清楚。让我们看看“无效转储”的一小部分的十六进制。 utf8utf8mb4 的子集,因此 utf8mb3 不会造成任何问题。 SHOW VARIABLES LIKE 'char%'.
  • "which is not valid UTF-8" - 请举例说明你是如何得出这个结论的,以便我们排除潜在的错误结论。
  • 添加了示例。 @RickJames 您可以为您的声明提供引用/链接吗?我知道“utf8”字符是“utf8mb4”字符的子集,但我没有“utf8mb3”规范来验证一种编码是另一种编码的子集。
  • utf8mb3。你能在这些前面添加至少 4 个字节吗? a6 相当符合第二个字节,所以前面的也很有趣。也许CESU-8 适用。
  • 我确实添加了前导字节——“a6”不是违规字节:)

标签: mysql utf-8 character-encoding utf8mb4


【解决方案1】:

我“解决”了这个问题:

uconv --from-code utf8 --from-callback substitute --to-code utf8 a.sql -o a.sql.fixed

这只是用默认字符替换任何无效序列。 man unconv 显示了其他几个选项,例如转义或删除无效序列。

在我的案例中,似乎只有极少数的错误,所以我更感兴趣的是能够处理转储,而不是正确识别这些案例中发生了什么。

编辑:通过使用--from-callback skip,我可以通过比较输入和输出文件的长度来计算无效序列的数量。

【讨论】:

  • 您的问题听起来像是您想恢复,而不是削减。接受这个答案是不公平的,因为它解决了一个不同的问题。
  • 这个答案不是很好,我同意。我感谢您的努力,但它并没有更好地回答问题。这使用工具而不是手动十六进制编辑,所以我认为它更好。另外,这个问题已经 1 个月大了,我觉得在某些时候我应该将某些问题标记为已解决。
  • "how can I fix it" 绑定到上下文,并且没有暗示剪切/删除不正确的序列是一种选择。也许在你的脑海里,但我坐在外面。请其他人阅读您的问题,然后讨论“修复它”的可能定义。
【解决方案2】:

根据 UTF-8,您的第一行 YYY 包含以下字符(所有有效序列):

U+006E  n  6e        LATIN SMALL LETTER N
U+002E  .  2e        FULL STOP
U+0020     20        SPACE
U+003C  <  3c        LESS-THAN SIGN
U+002F  /  2f        SOLIDUS
U+0070  p  70        LATIN SMALL LETTER P
U+003E  >  3e        GREATER-THAN SIGN
U+0020     20        SPACE
U+03E1  ϡ  cf a1     GREEK SMALL LETTER SAMPI
U+CBE6  쯦  ec af a6  (Hangul)
U+B7A0  랠  eb 9e a0  (Hangul)

您的第二行 YYZ 如下:从技术上正确但逻辑上非法的序列开始,因为不允许使用代理项,尤其是在未配对时(没有相应的高代理项)。 “私人使用”序列/字符是允许的,但可疑:

U+DDB0  �  ed b6 b0  (low surrogate = illegal, reserved for UTF-16)
U+1BA5  ᮥ  e1 ae a5  SUNDANESE VOWEL SIGN PANYUKU
U+E7A0    ee 9e a0  (private use = highly unlikely it is used intentionally)
U+0027  '  27        APOSTROPHE
U+002C  ,  2c        COMMA
U+0027  '  27        APOSTROPHE
U+0032  2  32        DIGIT TWO
U+0030  0  30        DIGIT ZERO

从逻辑上讲,这些字符也没有任何意义(一个希腊语,两个韩语......)。它也不适合任何 ANSI 编码:

  • a6 几乎总是翻译成¦,我已经好几年没遇到这个角色了
  • af 几乎总是转换为 ¯,这主要用于光学原因,但即使这样也很少使用一次
  • 9e 很少使用,只有少数编码映射它
  • a0 到处都是不间断的空格,没有人可以直接输入,但可能来自复制文本,例如 MS Word

从 SQL 上下文中,您可以看到所有这些字符仍在字符串文字中(请参阅撇号),其内容似乎是 HTML(请参阅尖括号)。由于这 17 个字节无法存储太多信息,只需使用十六进制编辑器并用 20(空格)覆盖每个字节。

【讨论】:

  • 这是程序的输出吗?那么是哪一个?
猜你喜欢
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
  • 2013-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
相关资源
最近更新 更多