如何调试 Etherpad Lite 数据库中 MySQL utf8mb4 列中的无效数据

How to debug invalid data in MySQL utf8mb4 column in Etherpad Lite database

我们是 运行 Etherpad Lite,我们正在尝试将数据库从 MySQL 迁移到 PostgreSQL。

MySQL 数据库 'value' 列的类型为 utf8mb4。但是,所有行中大约 10% 包含的值实际上是用 Windows-1252 或 ISO-8859-15 而不是 UTF-8 编码的。这怎么可能?在将 UTF-8 输入列之前,MySQL 不会验证它吗?

PostgreSQL 无法在迁移期间接受无效值,因为它会验证数据并命中,例如原始字节 0xE4 (ISO-8859-15: ä) 应在 UTF-8 中编码为字节序列 0xC3 0xA4.

这是 MySQL 的已知 "feature" 吗?有没有办法始终从 utf8mb4 列中获取真正的 UTF-8?

如果

  • 你说 客户端 使用 latin1 (等等),
  • 你说是utf8(或utf8mb4),
  • 你提供十六进制E4

那么就万事大吉了。 E4 将在 INSERT 期间转换为 C3A4,这就是存储的内容。做SELECT HEX(...) ...验证。

如果

  • 你说 客户端 使用的是 utf8(或 utf8mb4),
  • 你说是utf8(或utf8mb4),
  • 你提供十六进制C3A4

再次,一切都很好。 C3A4 直接进入 table.

这是一个混乱的案例:

如果

  • 你说客户端正在使用latin1
  • 你说是utf8(或utf8mb4),
  • 但是你提供十六进制C3A4

然后,MySQL有义务将两个字符(C3和A4)转换为utf8,产生C383C2A4。我称之为 "double encoding".

遵循 中的最佳实践并使用其建议的方法来测试数据。然后回来提供更多详细信息。

可能 10% 的数据被错误解释的唯一方法是对 10% 的数据进行不同的编码。因此,请为 10% 的示例和 90% 的示例提供十六进制。并在插入前和插入后的 table 中提供客户端中的十六进制。

没有已知的解决方案。这可能是 MySQL 中的一个错误,它应该不允许存储 non-UTF-8 数据以防 客户端连接和列类型都是utf8mb4.

我不再使用 MySQL 做任何事情,所以我不再费心去尝试找出这个错误。现在,我正在使用 PostgreSQL 代替一切。