MySQL LOAD_FILE 返回 NULL。

15

我想让SQL的LOAD_FILE函数正常工作,并阅读了每一个有关此问题的问答及文档,但是以下是发生的情况。

当我想从我的主目录中LOAD_FILE时:

mysql> SELECT LOAD_FILE('/home/myuser/somefile.txt');
+----------------------------+
| LOAD_FILE('/home/myuser/somefile.txt') |
+----------------------------+
| NULL                       |
+----------------------------+
1 row in set (0.00 sec)

所以,在得到这个之后,我想也许问题在于MySQL无法访问我的主目录。我尝试运行了以下命令,它运行良好:

SELECT LOAD_FILE('/etc/mysql/my.cnf');

然后SELECT LOAD_FILE('/etc/passwd');也正常工作。

所以我说,这是一个文件/文件夹读取/所有权权限问题。因此,我将我的文件移动到了/etc/mysql/,但它仍然无法正常工作。我尝试了chown mysql:mysql somefile.txt,但还是没有成功:

mysql> SELECT LOAD_FILE('/etc/mysql/somefile.txt');
+----------------------------+
| LOAD_FILE('/etc/mysql/somefile.txt') |
+----------------------------+
| NULL                       |
+----------------------------+
1 row in set (0.00 sec)

P.S. 1. 所有文件均可被所有用户组读取,因此无需进行chmod操作。但如果您愿意的话,我甚至尝试了 chmod 777 2. 我已经检查过,在MySQL中未设置secure-file-priv变量,因此LOAD_FILE没有受到任何路径的限制。

您有什么想法,可能是什么问题呢?


你的文件里有任何数据吗? - Rahul
@Rahul 是的,它可以。我在里面放了一两个句子。总共不到2 KB。 - Emir
5个回答

9

以下是我在Linux Mint 18上成功禁用apparmor的备选步骤 - 这将停止apparmor服务的运行,但不会从服务器中删除apparmor软件包:# /etc/init.d/apparmor stop # /etc/init.d/apparmor teardown # update-rc.d -f apparmor remove # service apache2 restart # service mysql restart - John
如果将其放置在 select @@GLOBAL.secure_file_priv; 的原始文件夹中(在我的情况下是 - /var/lib/mysql-files),而不是更改它,则不需要禁用 AppArmor。 - Payel Senapati

5
根据文档,使用此函数需要满足以下条件:

要使用此函数,文件必须位于服务器主机上。

您必须指定文件的完整路径名。

您必须拥有FILE特权。

文件必须对所有用户可读。

文件大小应小于max_allowed_packet字节。

如果将secure_file_priv系统变量设置为非空目录名称,则要加载的文件必须位于该目录中。

如果文件不存在或由于未满足前面的条件之一而无法读取,则函数返回NULL

因此,请检查上述所有条件是否都满足。 编辑: 不确定您是否理解得正确。。
  1. 确保文件的父目录具有执行权限。因此,如果somefile.txt位于myuser目录下,则必须对myuser目录具有执行权限。

  2. 您必须拥有FILE特权意味着必须显式授予FILE特权,例如:GRANT FILE on . TO user@localhost

  3. 刷新权限

  4. 注销并重新登录,然后检查它是否正常工作。

请参阅此帖子

1
是的,我已经阅读了文档并提前检查了所有上述条件。我非常确定文件无法被读取(与最后一个条件有关),但我不知道为什么。出于某种原因它就是无法读取该文件。 - Emir
太好了。SHOW VARIABLES LIKE 'max_allowed_packet' 的值是多少? - Rahul
mysql> SHOW VARIABLES LIKE 'max_allowed_packet'; +--------------------+------------+ | Variable_name | Value | +--------------------+------------+ | max_allowed_packet | 1073741824 | +--------------------+------------+ 1 行记录已显示 (0.00 秒) - Emir
@Emir,那好的。请检查已编辑的答案并验证那些要点。 - Rahul
回答你的编辑:
  1. 是的,该文件夹具有执行权限。我甚至尝试将此文件放在 /etc/mysql/ 下,MySQL 默认拥有所有访问权限。
  2. 我已作为 root 用户登录到 MySQL,所以我已检查并拥有 FILE 权限(以及所有其他权限)。
- Emir
AppArmor 也应该加入列表中。 - ivo Welch

4

我一直在解决这个问题,终于找到了解决方法:

mysql> select LOAD_FILE('/var/www/upload/test.zip');
+---------------------------------------+
| LOAD_FILE('/var/www/upload/test.zip') |
+---------------------------------------+
| NULL                                  |
+---------------------------------------+
1 row in set (0.00 sec)

问题是secure_file_priv未设置。执行以下查询以查看其指向的位置:
执行查询:
select @@GLOBAL.secure_file_priv;

为了指向您想要拉取文件的区域,我所做的是在mysqld.conf的末尾添加以下内容。
secure_file_priv =  /var/www/upload.

重新启动了 MySQL 并进行了测试

mysql> select LOAD_FILE('/var/www/upload/test.zip');
+--------------------------------------------------------------------------------------

这就是我需要的了。只有位于此位置的文件才能被加载到数据库中。谢谢。 - JerseyDevel
1
你需要在文件/etc/mysql/mysql.conf.d/mysqld.cnf[mysqld]行下方精确添加secure_file_priv = /var/www/upload,而不是在“结尾”处。这个不完整的信息让我浪费了几个小时,希望能帮到别人。同时,必须遵循@Emir提供的答案,关闭“mysql”的“apparmor”。 - Payel Senapati

2

在将图像添加到blob字段时,我在Fedora Linux上遇到了同样的问题。

我解决了这个问题,将文件复制到目录/var/lib/mysql/images并执行以下命令:

chown -R mysql:mysql /var/lib/mysql/images


0

使用Load data infile file_name...是MySQL的正确命令。由于您没有提供文件中数据的示例,我无法向您展示如何确切地使用它。有变量来处理分隔符和行结束特征。祝你好运。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接