转换“????”在 mysql 到可读的东西?

converting "????" in mysql to something readable?

我们遇到这样一种情况,即通过 ODK 聚合收集到 MySQL 数据库的数月数据不可读。

数据是格鲁吉亚字符,但被发送到带有 latin1 字符的数据库 set/collation。

数据管理员直到几天前才发现这个问题,而且我从来没有意识到他们正在使用这些字符的调查......所以现在的问题显然是 1)我们可以恢复现有数据吗?和 2) 如何保证以后的数据是可读的?

我可以做一个 SELECT 十六进制(列)来自 table

并获得十六进制输出,但它看起来像这样:

3F3F3F3F203F3F3F3F3F3F3F3F203F3F3F3F3F3F3F3F3F
3F3F3F3F3F3F3F
E18397E18391E18398E1839AE18398E183A1E18398

如您所见,最后一行看起来是正确的,但其他的则不是。当我使用 latin1 创建测试 table 并尝试插入格鲁吉亚字符时,我得到了 警告:#1366 不正确的字符串值:第 1

行 'georgian_text' 列的 '\xE1\x83\x93\xE1\x83\x93...'

我在 Tomcat 日志中没有看到任何内容,但我假设每次提交记录时聚合都会遇到相同的错误。

我的问题是:第一行的十六进制可以转换成有用的东西吗?

3F 是字符 '?'

这对我来说似乎是有损数据;您将无法将此数据转换回可读的内容。

为避免这种情况,您需要在应用程序的所有层中使用相同的字符集。 UTF-8 是一个流行的选择。

问号大概出处:

  • 客户有一个有效的字符(好),并且
  • SET NAMES同意客户端的编码(好),但是
  • 目标列的 CHARACTER SET 不包含预期字符(错误)。

转换为“?”的字符无法从 table.

恢复

更改 table 定义中的 CHARACTER SET。 (并重新加载您的文本)

我无法恢复丢失的内容,但为了文档起见,答案是从一开始就在 /etc/my.cnf 中始终包含以下内容,这样这些问题就不会在第一时间发生地方。

character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'