这是两年来的夜间工作。PHP 文件将 txt 文件导入 MYSQL 数据库。今天突然在导入 TXT 文件时出现格式错误的数据包。我注意到服务器只启动了 23 小时,所以我认为 GoDaddy 可以更新一些东西。
MYSQL Ver = 5.6.43-cll-lve
local_infile = 开
如果没有"本地",我会收到错误,"拒绝用户访问",我尝试授予 FILE,但在通过 SSH 获取 mysql CLI 访问权限时遇到问题(以前从未需要过),并且 PHP MY 管理员没有访问权限。
我花了一整天的时间,不知道该怎么办。我也尝试将文件设置为 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);
要使用LOAD DATA INFILE LOCAL
需要在连接之前启用MYSQLI_OPT_LOCAL_INFILE。
您应该SHOW GLOBAL VARIABLES LIKE 'local_infile'
查看是否在服务器上启用了此功能,这也是必需的。
确保授予当前用户访问文件的权限:
首先登录到mysql
:
mysql -u root -p
然后
GRANT FILE ON *.* TO 'username'@'localhost';
我遇到了同样的问题,一个运行良好的脚本 3 年,突然开始因"格式错误的数据包"而失败。我正在运行具有私有数据库的 OVH 托管服务器。
可悲的是,没有一个解决方案有效(GRANT
或MYSQLI_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: 'xF0x9Fx93x8B' for column ...
xF0x9Fx93x8B
值实际上是一个完美的 UTF8 编码字符:剪贴板表情符号 📋
但是,它是在 4 个字节上定义的(就像大多数表情符号一样)。
如前所述,我的表和列使用排序规则utf8_unicode_ci
。所以应该很好吧?除了。。。不!mySQL 的utf8
实现存在严重缺陷,因为它只允许表示最多 3 个字节的 UTF8!有关更多背景信息,请参阅这些链接。
在mySQL中UTF8的新的和正确的现代实现称为utf8mb4
。
因此,最终的解决方案只是将所有表和列迁移到utf8mb4_unicode_ci
排序规则中,瞧!问题解决了。
最后,最大的问题是理解这个非常误导性的"格式错误的数据包"错误消息到底是什么意思。
就我而言,解决方案非常简单。
我完全同意@danblack答案。
我在 PHP 脚本中添加了这一行:
@mysqli_options($con, MYSQLI_OPT_LOCAL_INFILE, true);
就在插入脚本之前。