【问题标题】:MYSQL database encoding, mix of latin1 and utf-8MYSQL 数据库编码,latin1 和 utf-8 的混合
【发布时间】:2018-06-02 02:33:16
【问题描述】:

我有一个几年前创建的旧 MYSQL 5.6.34 数据库(不是我创建的)。当我注意到其他一些表具有latin1 编码时,我已经使用了其中一个数据库并开始在其中构建表以供我的应用程序使用。然后我注意到所有的数据库,除了information_schema 都使用latin1

SCHEMA_NAME         DEFAULT_CHARACTER_SET_NAME  DEFAULT_COLLATION_NAME
information_schema  utf8                        utf8_general_ci
443347_pxa          latin1                      latin1_swedish_ci
443348_srp          latin1                      latin1_swedish_ci
warehouseinventory  latin1                      latin1_swedish_ci

我不确定为什么最初的开发人员使用 latin1 进行编码和整理。真的没有理由。

我真的不想更改任何现有数据库的任何编码,我只想使用 utf8mb4 创建新表。但我想得越多,为了保持一致,我可能想改变它们。我创建的最后一个数据库是warehouseinventory,但我没有注意到编码,我假设它基于之前创建的数据库的编码默认为latin1

我有什么理由将这些留在latin1 并且更改它们会不会很痛苦?其中一个数据库确实存储了西班牙语,但我一直认为那只是 UTF。

【问题讨论】:

  • 您有所有数据的备份,对吧?如有必要,您可以拉下快照以在实时更改之前对其进行试验?如果您实时进行更改,如果出现严重错误,您可以回滚吗?理想情况下,您拥有所有 UTF-8 或 MySQL 术语中的 utf8mb4,除非您有严重的限制。 MySQL 5.6 可以很好地处理 UTF-8,MySQL 5.7 甚至更好,所以如果你也可以升级考虑。
  • 备份,绝对!
  • 好东西!太多人喜欢“嗯,备份?”然后我在里面死了一点。至少这不是那些“我不小心没有备份的数据库”问题之一。一路走UTF-8,生活会好很多。混合编码对于您的应用程序层来说可能是一场噩梦。这就是“它”的发生方式。
  • MySQL 中的 Utf8_general 不是您可能假设的那样。它不是一个完整的 Unicode 实现,它不会影响表中可以存储和不能存储的内容。它是一种排序规则,会影响字符比较和排序规则。
  • 您可能会因为对原始数据库中的编码的疯狂假设而发现您的代码中断,但您可以通过积极的测试来摆脱这些假设。确保在每个表的每个字段中都有一条带有 Latin1 特殊字符(例如“Tést¥”)的记录,以查看转换后是否可以恢复。有时您的应用程序一直在存储 UTF-8 as Latin1,不知道其中的区别,而数据库也不在乎,所以实际上是乱码。

标签: mysql utf-8 character-encoding utf8mb4


【解决方案1】:

如果您在声明为 VARCHAR(255) 的列上有任何索引,则在转换为 utf8mb4 时可能会收到有关“索引大于 767 字节”的错误。有5 workarounds

如果您没有任何 191 到 255 个字符之间的 varchar 被编入索引,那么

ALTER TABLE tbl CONVERT TO utf8mb4;

会将表tbl中的所有列转换为utf8mb4。

如果您碰巧以“双重编码”将 utf8 字节错误地存储到 latin1 中,则需要进行不同的修复。评论Fixes for various Cases

“默认”字符集或排序规则就是这样——一个默认值。也就是说,当创建新列或表时,它采用 默认值。如果您为列显式指定字符集和/或排序规则,则会覆盖表的默认值。

有句老话:“如果没坏,就不要修。”我倾向于制作新的数据库/表/列 utf8mb4,但不理会旧的。注意:有一个混合物是可以的。 connection 指定 client 使用什么编码。 MySQL 在INSERTSELECT 期间将在客户端设置和列设置之间进行转换。

西班牙语的字符集是有限的。该集是 latin1、utf8 和 utf8mb4 的子集,因此这些字符集中的任何一个都适用于西班牙语。但是,编码是不同的。例如,ñ

Hex F1   in latin1
Hex C3B1 in utf8 and utf8mb4

西欧其他地区也是如此。亚洲至少需要utf8。表情符号和部分汉字需要utf8mb4。

如果你最终得到问号、Mojibake 等,请调试它here

术语:MySQL 之外:UTF-8; MySQL 内部:utf8mb4。这些本质上是一样的。 MySQL 的utf8 是其中的一个子集。

Tést¥,十六进制:

54 E9 73 74 A5 -- cp1256, dec8, latin1, latin5  encoding
54 C3A9 73 74 C2A5 -- utf8, utf8mb4  encoding
54 C383 C2A9 73 74 C382 C2A5 -- "double encoded"; may show as Tést¥

【讨论】:

  • 升级到更新的 MySQL 5.7 可以避开索引问题,这就是链接的 TL;DR。
猜你喜欢
  • 2012-11-17
  • 2020-09-15
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
相关资源
最近更新 更多