经过两年的工作,突然在LOAD DATA LOCAL INFILE上出现MYSQL“格式错误的数据包”

时间:2019-04-04 23:15:24

标签: php mysql file mysqli import

这是一项每晚工作了两年的工作。 PHP文件将txt文件导入MYSQL数据库。今天突然导入TXT文件时收到格式错误的数据包。我注意到服务器仅运行了23个小时,因此我认为GoDaddy可能已更新了一些内容。

MYSQL Ver = 5.6.43-cll-lve

local_infile = ON

没有“本地”,我会收到错误消息,“用户的访问被拒绝”,我尝试授予FILE权限,但是在通过SSH获取mysql CLI访问方面遇到了问题(以前从未需要过),而PHP MY Admin没有访问权限。

我花了整整一整天的时间,不知道该怎么办。我也尝试将文件设置为777。

我尝试删除截断部分​​并仅执行导入操作,使用以前有效的旧导入文件将导入文件缩减为3行-无法前后。

require('config_dev.php');
$path = '/home/pro/public_html/upload/IDUpload_dev.txt';
$mysqli = new mysqli($hostname,$username, $password, $dbname);

if ($mysqli->connect_error) {
  die('Error : ('. $mysqli->connect_errno .') '. $mysqli->connect_error);
}

$sql1 = "TRUNCATE TABLE Accounts;";

if (!$mysqli->query($sql1)) {
    echo "\nQuery execute failed: ERRNO: (" . $mysqli->errno . ") " . $mysqli->error;
} else {
    echo ("Truncated<br>");
}

$sql2 = "LOAD DATA LOCAL INFILE '".$path."' INTO TABLE Accounts
        FIELDS TERMINATED BY ','
        LINES TERMINATED BY '\n'
        IGNORE 1 LINES
        (acct,type,zip)";

if (!$mysqli->query($sql2)) {
    echo "\nQuery execute failed: ERRNO: (" . $mysqli->errno . ") " . $mysqli->error;
} else {
    echo ("Imported.");
}

mysqli_close($mysqli);

3 个答案:

答案 0 :(得分:3)

要使用LOAD DATA INFILE LOCAL,必须在连接前启用MYSQLI_OPT_LOCAL_INFILE

您应该SHOW GLOBAL VARIABLES LIKE 'local_infile'来查看服务器上是否启用了此功能,这也是必需的。

答案 1 :(得分:0)

确保授予当前用户访问文件的权限:

先登录mysql

mysql -u root -p

然后

GRANT FILE ON *.* TO 'username'@'localhost';

答案 2 :(得分:0)

我遇到了同样的问题,一个运行良好 3 年的脚本突然开始失败并显示“格式错误的数据包”。我在带有 private database 的 OVH 托管服务器上运行。

遗憾的是,没有一个解决方案有效(GRANTMYSQLI_OPT_LOCAL_INFILE)。

在摆弄之后,我注意到该脚本在同一台服务器上的测试数据库上运行!

我比较了两个数据库的配置,我发现的唯一区别在于数据库整理

  • 在测试数据库上,我有 SELECT @@collation_database == latin1_swedish_ci
  • 在不再工作的生产数据库上,我有 SELECT @@collation_database == utf8_unicode_ci

我更改了生产数据库的排序规则...

ALTER DATABASE DB_PROD_NAME CHARACTER SET latin1 COLLATE latin1_swedish_ci;

它奏效了!(即使所有表都使用 utf8_unicode_ci

好吧,它可以工作,但所有字符都被破坏了。

但这迫使我研究编码问题,这使我找到了正确的解决方案。

使用 LOAD DATA LOCAL INFILE ... CHARACTER SET 'utf8mb4' ... 我能够得到真正的错误:

ERROR : Incorrect string value: '\xF0\x9F\x93\x8B' for column ...

\xF0\x9F\x93\x8B value is actually a perfectly fine UTF8-encoded character:剪贴板表情符号?

但是,它是在 4 个字节上定义的(就像大多数表情符号一样)。

如前所述,我的表和列使用排序规则 utf8_unicode_ci。所以应该不错吧?除了……不是! mySQL 的 utf8 实现存在严重缺陷,因为它只允许表示最多 3 个字节的 UTF8! See these links 了解更多背景信息。

在 mySQL 中新的、正确的现代 UTF8 实现称为 utf8mb4

所以最终的解决方案只是将所有表和列迁移到 utf8mb4_unicode_ci 排序规则,瞧!问题解决了。

最后,最大的问题是理解这个极具误导性的“Malformed packet”错误消息究竟意味着什么。