如何解决:mysqli_query(): load data local infile 被禁止问题
这种情况我之前在部署项目时碰到过好几次,核心问题是LOAD DATA LOCAL INFILE的权限限制在命令行、PHP、phpMyAdmin这几个环境里的配置逻辑完全不一样,结合你用的MySQL 5.0.12版本,给你一步步排查解决的方案:
你本地环境能跑、命令行能执行,说明MySQL服务器端本身是允许LOAD DATA LOCAL INFILE操作的,但PHP的mysqli客户端、phpMyAdmin客户端默认都禁用了本地文件读取的权限,再加上Linux系统和Windows系统的路径格式差异,才导致部署到Ubuntu服务器后失效。
1. 先修正路径格式(最容易踩的坑)
你的SQL语句里用了Windows风格的反斜杠path\to\file.csv,但Ubuntu是Linux系统,路径分隔符是正斜杠,而且反斜杠在PHP字符串里是转义符,实际传递给MySQL的路径会出错。赶紧把路径改成:
$sql = "LOAD DATA LOCAL INFILE 'path/to/file.csv' REPLACE INTO TABLE tablename FIELDS TERMINATED BY ';' ENCLOSED BY '\"' LINES TERMINATED BY '\\r\\n'";
强烈建议用绝对路径,比如/var/www/html/uploads/file.csv,避免相对路径带来的歧义(比如PHP的工作目录和你预期的不一样)。
2. 给PHP的mysqli连接开启LOCAL_INFILE选项
MySQL客户端(这里就是PHP的mysqli扩展)默认是禁用LOCAL_INFILE的,必须手动开启这个选项才能执行本地文件导入。修改你的代码,在建立数据库连接之后、执行SQL之前添加这一行:
// 假设$con是你的数据库连接对象 mysqli_options($con, MYSQLI_OPT_LOCAL_INFILE, true);
如果是用mysqli_init()的方式初始化连接,代码应该写成这样:
$con = mysqli_init(); // 先开启本地文件导入权限 mysqli_options($con, MYSQLI_OPT_LOCAL_INFILE, true); // 再建立连接 mysqli_real_connect($con, $host, $user, $password, $database);
这一步是PHP脚本能成功执行的关键——本地环境可能因为php.ini的默认配置开启了这个选项,但服务器端通常会默认关闭。
3. 再次确认MySQL服务器端的配置
虽然你说已经设置了local-infile为true,但再仔细检查一遍确保配置生效:
- 找到MySQL的配置文件(Ubuntu上一般是
/etc/mysql/mysql.conf.d/mysqld.cnf或者/etc/mysql/my.cnf) - 在
[mysqld]段落里添加或修改:local-infile=1 - 重启MySQL服务让配置生效:
sudo service mysql restart
MySQL 5.0版本的这个配置逻辑和后续版本一致,设置后服务器才会接收客户端的本地文件导入请求。
4. 修复phpMyAdmin的配置
phpMyAdmin默认是禁用本地文件导入的,要让它能执行LOAD DATA LOCAL INFILE,需要修改其配置文件:
- 找到phpMyAdmin的
config.inc.php(Ubuntu上一般在/etc/phpmyadmin/config.inc.php) - 在文件里添加一行:
$cfg['AllowLocalInfile'] = true; - 重启web服务器(比如Apache):
sudo service apache2 restart
这样再去phpMyAdmin里执行SQL语句就不会返回空结果了。
5. 确认MySQL用户的FILE权限
最后再确认你的数据库用户拥有FILE权限,执行以下SQL语句:
GRANT FILE ON *.* TO '你的用户名'@'localhost'; FLUSH PRIVILEGES;
替换你的用户名为你实际使用的数据库用户名,这个权限是用户读取本地文件并导入到数据库的必要条件。
- 先检查文件路径是否正确,用
ls -l /绝对路径/file.csv确认文件存在,且www-data用户(PHP的运行用户)有读取权限 - 添加
mysqli_options代码后,重新运行PHP脚本,查看是否还有错误警告 - 去phpMyAdmin里执行修正后的SQL语句,验证是否能正常导入数据
内容的提问来源于stack exchange,提问作者Jazal

