【问题标题】:Exact Same MySQL Table Structure/Data, Different Result To Same Query完全相同的 MySQL 表结构/数据,不同的结果到相同的查询
【发布时间】:2020-03-12 17:09:22
【问题描述】:

这是我的情况。

我正在从一台服务器迁移到另一台服务器。作为其中的一部分,我正在跨数据库数据移动。

迁移方法涉及在新服务器上运行相同的 CREATE TABLE 查询,然后使用一系列 INSERT 命令逐行插入数据。这可能会导致不同的数据,但是,CHECKSUM 命令用于验证内容。 CHECKSUM 是在传输后对整个表、在隔离了该行的新表上以及在应用 LEFT 运算符截断字符串后进行的。每次,新旧服务器的结果都是相同的,这表明原始数据在字节级别上应该完全相同。

CHECKSUM TABLE `test`

我检查了结构,它也完全一样。

SHOW CREATE TABLE `test`

结构如下:

CREATE TABLE test ( item varchar(32) COLLATE utf8_unicode_ci NOT NULL, amount mediumint(5) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

字段的类型:

`item` varchar(32) COLLATE utf8_unicode_ci NOT NULL

这是我在 PHP 中的连接代码:

$sql = new mysqli($db_host, $db_user, $db_pass, $db_name);
if ($sql->connect_error) {
  die('Connect Error ('.$sql->connect_errno.') '.$sql->connect_error);
}

当我用简单的查询在 PHP 中检索数据时:

SELECT * FROM `test`

数据显示如下:

§10

在旧服务器/主机上,我得到以下原始字节序列:

Decimal: -194-167-108-79-
HEX: -C2-A7-6C-4F-

在新服务器上,我在开头得到了几个额外的字节:

Decimal: -195-130-194-167-108-79-
HEX: -C3-82-C2-A7-6C-4F-

为什么完全相同的原始数据、表结构和查询会在两台服务器之间返回不同的结果?我应该怎么做才能确保将来的结果尽可能一致?

【问题讨论】:

  • 检查数据库上的字符集,只需在两者上运行`SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = "database_name"`
  • 感谢您的帮助。在这两种情况下,我收到的结果都是“DEFAULT_CHARACTER_SET_NAME”是“utf8”。
  • 能否请您发布该表的创建表?
  • 在这两种情况下 "CREATE TABLE test (item varchar(32) COLLATE utf8_unicode_ci NOT NULL, amount mediumint(5) NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci "
  • latin1 可能涉及到某处,例如 connection 参数。

标签: php mysql sql character-encoding database-migration


【解决方案1】:

§lO 是 §lO 的“Mojibake”。我认为后者(3 个字符)是“正确的”?

原始数据看起来像这样(在两种情况下,当我显示它时)

是伪造的,因为用于显示它的技术可能与编码混淆。

由于3个字符变成了4个又变成了6个,你可能有“双重编码”。

这里讨论了“双重编码”是如何发生的:Trouble with UTF-8 characters; what I see is not what I stored

如果您提供更多信息(CREATE TABLE、十六进制、迁移数据的方法等),我们或许能够进一步解开您的混乱。

更多

使用mysqli时,请$sql->set_charset('utf8');

(HEX 证实了我的分析。)

迁移方法涉及在新服务器上运行相同的 CREATE TABLE 查询

前面是否有一些字符集设置,如mysqldump?

然后使用一系列 INSERT 命令逐行插入数据。

你能得到文件中某些重音字符的十六进制吗?

...校验和...

好的,相同的情况排除了一件事。

CHECKSUM 是在一个新表上完成的,该行被隔离

你是怎么做到的? SELECTing 该行可能修改了文本,从而使测试无效。

表明原始数据在字节级别应该完全相同。

为了检查表中的数据,SELECT HEX(col)... 是绕过所有可能发生的字符集转换的唯一方法。请为具有非 ascii 字符的某些列提供 HEX(例如给出的示例)。并针对 HEX 输出执行 CHECKSUM。

并提供SHOW VARIABLES LIKE 'char%';

【讨论】:

  • 非常感谢您的帮助。我已将您要求的所有详细信息添加到问题中。我目前正在阅读您提供的另一个问题。我感谢您的帮助。请让我知道是否有任何其他细节有用。
  • @azoundria - 我添加了更多。
  • 非常感谢您的帮助。发生的事情是我只是在迁移中超时并且旧的虚拟主机帐户现在处于脱机状态,所以我无法知道差异。除了谢谢,我没什么可说的了。
猜你喜欢
  • 1970-01-01
  • 2014-07-06
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 2021-03-23
  • 2010-10-10
相关资源
最近更新 更多