使用http://位置损坏加载数据本地infile

时间:2015-09-23 11:23:05

标签: php mysql file-io load-data-infile

背景 我将一些网站从共享主机帐户移动到VPS。除了使用来自外部服务器(即http://server1.net/getfile.php?f=101)的数据源的LOAD DATA LOCAL INFILE执行查询的PHP代码行之外,一切都非常流畅。此代码在共享主机帐户上工作(并且长时间工作),但是,此帐户正在达到资源限制,尤其是在数据库大小/速度方面。

问题: 从http://地址下载的带有LOAD DATA INFILE的代码在移动到(新)VPS后不再起作用。

系统和软件: VPS用作Web服务器,运行带有Vesta(0.9.8(amd64))的Ubuntu(Ubuntu 14.04),apache,nginx,mysql(5.5.44),app-armor等。最近都安装了,很少或没有改变。

从phpinfo()输出中选择:

System  Linux MyServer 3.13.0-62-generic #102-Ubuntu SMP Tue Aug 11 14:29:36 UTC 2015 x86_64 
Apache Version  Apache/2.4.7 (Ubuntu) mod_fcgid/2.3.9 PHP/5.5.9-1ubuntu4.11 OpenSSL/1.0.1f 
Server Root     /etc/apache2
PATH    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SERVER_SOFTWARE     Apache/2.4.7 (Ubuntu) mod_fcgid/2.3.9 PHP/5.5.9-1ubuntu4.11 OpenSSL/1.0.1f
allow_url_fopen On  On
allow_url_include   Off
doc_root    no value    
docref_ext  no value
docref_root no value
file_uploads    On
open_basedir    no value
sys_temp_dir    /tmp
upload_tmp_dir  /tmp
user_dir    no value
cURL support    enabled 
mysql
Directive                   Local Value  Master Value
mysql.allow_local_infile    On           On
mysqli
Directive                   Local Value  Master Value
mysqli.allow_local_infile   On           On

来自/etc/mysql/my.cnf

的几行
[client]
loose-local-infile=1
local-infile=1

[mysqld]
basedir=/usr
datadir=/var/lib/mysql
tmpdir=/tmp
local-infile=1

下面的代码与phpinfo()

的文件在同一目录中运行

测试代码:

$url = "http://myserver.net/x.csv";
$file = "/var/lib/mysql/test2.csv";

$handle = curl_init($url);
curl_setopt($handle,  CURLOPT_RETURNTRANSFER, TRUE);
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
echo("<br>Http code: ". $httpCode);
curl_close($handle);

echo "<br>Temp_name: ". $_FILES["file"]["tmp_name"];
echo "<br>Host info: " . $conn->host_info . "\n";
echo "<br>Client info: ".mysqli_get_client_info($conn) ."\n";

$conn = mysqli_init();
if (!$conn) {
    die('mysqli_init failed');
}

if (!$conn->options(MYSQLI_OPT_LOCAL_INFILE, true)) {
    die('Setting MYSQLI_OPT_LOCAL_INFILE failed');
}

if (!$conn->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5)) {
    die('Setting MYSQLI_OPT_CONNECT_TIMEOUT failed');
}

if (!$conn->real_connect('localhost','root','pass','database')) {
    die('Connect Error (' . mysqli_connect_errno() . ') '
            . mysqli_connect_error());
}

$conn->query("LOAD DATA INFILE '". $file ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error file: " . mysqli_error($conn));

$conn->query("LOAD DATA INFILE '". $url ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error url: " . mysqli_error($conn));

$conn->query("LOAD DATA LOCAL INFILE '". $file ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error file (LOCAL): " . mysqli_error($conn));

$conn->query("LOAD DATA LOCAL INFILE '". $url ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error url (LOCAL): " . mysqli_error($conn));

$conn->query("SELECT * INTO OUTFILE 'andreas.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n' FROM x_import;");
echo("<br>Error OutFile: " . mysqli_error($conn));

代码结果:

Http code: 200
Temp_name:
Host info:
Client info: 5.5.44
Error file:
Error url: Can't get stat of '/var/lib/mysql/http:/myserver.net/x.csv' (Errcode: 2)
Error file (LOCAL): File '/var/lib/mysql/test2.csv' not found (Errcode: 13)
Error url (LOCAL): File 'http:/myserver.net/x.csv' not found (Errcode: 2)
Error OutFile: File 'andreas.txt' already exists

使用带有mysql的root帐户的php代码,所以那里有完全访问/权限。

带有sql代码的第一行(没有使用本地文件的LOCAL的LOAD DATA INFILE)正确地添加了数据库中文件的数据。

使用INTO OUTFILE代码的最后一行在/ var / lib / mysql / database /中正确创建了一个文件(第二次给出了已经存在的错误)

到目前为止,我从所有研究中了解到:

  • 错误代码13是权限问题。
  • 错误代码02是无法找到文件的时间。
  • “LOAD DATA”用于数据库服务器上的文件。
  • “LOAD DATA LOCAL”用于客户端上的文件(apache / php-code)。

我不明白为什么在使用LOCAL时URL中存在/缺失(参见代码输出)。当LOCAL被添加到URL时,我也不明白为什么会出现错误代码13(php在代码的第一部分接收代码200)。在我看来,由于几个原因,php和mysql都无法查看正确的位置。

下面我将解释一些我尝试过的尝试(主要来自本网站上的大量其他答案):

我已将/ var /和/ var / lib /的文件权限更改为755(并且一次更改为777),但这并未更改我的测试代码输出。 / tmp /已经设置为777。

在app-armor中我已经将mysql更改为抱怨模式,并且在app-armor(usr.sbin.mysqld)的mysql配置文件中尝试了一些更改,但两者都没有更改测试代码输出。

有用的文档(但我可能没有完全理解): http://dev.mysql.com/doc/refman/5.5/en/load-data-local.html

我更喜欢使用LOAD DATA LOCAL,但如果它以任何其他方式工作,我也很高兴。

请帮忙。欢迎任何问题和建议。

1 个答案:

答案 0 :(得分:0)

当我尝试使用mysql load infile(localhost和远程数据库上的数据文件和项目)时遇到同样的问题。我使用来自mysql的直接php命令(通过system函数)。以下是我的代码示例:

system('mysql --local-infile -h '.$host. ' -D '.$dbname.' -u'.$dbuser.' -p'.$password." -e \"LOAD DATA LOCAL INFILE '". $pathToFile . "' INTO TABLE table FIELDS TERMINATED BY ';' (field1, field2, field3)\"");

我希望这对你有用。