繁体   English   中英

LOAD DATA INFILE + MySQL错误28000

[英]LOAD DATA INFILE + MySQL error 28000

我遇到了以下要执行的SQL查询的问题:

LOAD DATA INFILE 'thelocationofmyfile.csv'
INTO TABLE test_import 
FIELDS TERMINATED BY ';'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES ( ArtID, ArtNamePharmLang, ArtNameFr, ArtNameNl, PubPrice, PercentageRebate, RebateAmount, SellingPrice, Localisation, CnkNr, EanNr, SoldQty, MinThd, MaxThd, QtyInStock, DateLastSale, VatRate, SupplierManufName, BuyPrice, InvCatCode, ArtType, ApbCatCode, ApbLegCode, PharmApbNr );

我想将excel文件的数据加载到我的数据库中的表中。 当我在本地运行时一切正常。 但是当我在服务器上执行此操作时,我收到以下错误:

Uncaught exception 'PDOException' with message 'SQLSTATE[28000]: Invalid authorization specification: 1045 Access denied for user 'myuser'@'localhost' (using password: YES)'

我正在尝试用PHP(在Zend Framework中)这样做。 当我联系托管时,他们说我需要FILE权限才能执行此操作。 但这是不好的做法,并没有提出建议。

我也尝试在这样的shell脚本中执行此操作:

#!/bin/bash
/usr/bin/mysql --host=localhost --user=theuser --password=password --database=db_database<<EOFMYSQL
LOAD DATA INFILE 'locationofmyfile.csv'
INTO TABLE test_import 
FIELDS TERMINATED BY ';'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES ( ArtID, ArtNamePharmLang, ArtNameFr, ArtNameNl, PubPrice, PercentageRebate, RebateAmount, SellingPrice, Localisation, CnkNr, EanNr, SoldQty, MinThd, MaxThd, QtyInStock, DateLastSale, VatRate, SupplierManufName, BuyPrice, InvCatCode, ArtType, ApbCatCode, ApbLegCode, PharmApbNr );
EOFMYSQL

但我得到了同样的错误:

ERROR 1045 (28000) at line 1: Access denied for user 'user'@'localhost' (using password: YES)

更新:

我试过像这样添加LOCAL:

LOAD DATA LOCAL INFILE 'thelocationofmyfile.csv'

但后来我得到了这个错误:

ERROR 1148 (42000) at line 1: The used command is not allowed with this MySQL version

还试图像这样添加--local-infile = 1但是得到了同样的错误

/usr/local/bin/mysql --host=127.0.0.1 --user=theuser --local-infile=1 --password=password --database=db_database

第二次更新:

我的配置文件my.cnf看起来像这样:

[mysqld]
local-infile=0

max_connections         = 50
connect_timeout         = 5
wait_timeout            = 300
max_allowed_packet      = 16M
thread_cache_size       = 128
sort_buffer_size        = 4M
bulk_insert_buffer_size = 16M
tmp_table_size          = 16M
max_heap_table_size     = 16M
key_buffer_size         = 32M
open-files-limit        = 2000
table_cache             = 400
myisam_sort_buffer_size = 8M
concurrent_insert       = 2
read_buffer_size        = 2M
read_rnd_buffer_size    = 1M
query_cache_limit       = 1M
query_cache_size        = 32M
innodb_log_file_size    = 48M
max_allowed_packet  = 32M

建立连接的位置并不重要,因为我正在使用shell脚本对其进行测试,然后进行连接。

我跑的时候没有收到错误

/usr/bin/mysql --host=localhost --user=theuser --password=password --database=db_database<<EOFMYSQL
show tables;
EOFMYSQL

(只是我数据库中所有表的列表)

当我运行SHOW GRANTS; 我明白了:

+------------------------------------------------------------------------------------------------------------------------+
| Grants for theuser@localhost                                                                                           |
+------------------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'theuser'@'localhost' IDENTIFIED BY PASSWORD '*password' |
| GRANT ALL PRIVILEGES ON `mydomain\_live`.* TO 'theuser'@'localhost'                                                    |
| GRANT ALL PRIVILEGES ON `mydomain\_staging`.* TO 'theuser'@'localhost' WITH GRANT OPTION                               |
+------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.01 sec)

您可以尝试LOAD DATA LOCAL INFILE并使用存储在客户端磁盘中的文件。 这样您就不需要拥有FILE权限。 由于必须将文件上传到服务器,因此速度会变慢。

希望这有帮助

首先,请向我们展示您的配置文件(my.cnf)和数据库的verison。 此外,连接是estableshed的代码输出将是有帮助的。 它应该是这样的:

/*** mysql hostname ***/
$hostname = 'localhost';
/*** mysql username ***/
$username = 'user';
/*** mysql password ***/
$password = 'pass';

function testdb_connect ($hostname, $username, $password){
    $dbh = new PDO("mysql:host=$hostname;dbname=database", $username, $password);
    return $dbh;
}

try {
    $dbh = testdb_connect ($hostname, $username, $password);
    echo 'Connected to database';
} catch(PDOException $e) {
    echo $e->getMessage();
}

至于错误:

ERROR 1045 (28000) at line 1: Access denied for user 'user'@'localhost'
and
ERROR 1148 (42000) at line 1: The used command is not allowed with this MySQL version

执行时是否收到错误:

/usr/bin/mysql --host=localhost --user=theuser --password=password --database=db_database<<EOFMYSQL
show tables;
EOFMYSQL

您可能检查的一件事是(这需要您登录MySQL控制台) - 检查以确保您有权通过localhost登录MySQL:

mysql -h 127.0.0.1 -u user -p

mysql> select user,host from mysql.user;
+------+--------------------------------+
| user | host                           |
+------+--------------------------------+
| user | 127.0.0.1                      | 
| user | ::1                            |
| user | localhost                      | <-- Make sure you have a localhost entry for root
+------+--------------------------------+
3 rows in set (0.00 sec)

此外,您可以检查您的用户的GRANTS。 要列出授予用于连接服务器的帐户的权限,可以使用以下任何语句:

SHOW GRANTS;
SHOW GRANTS FOR CURRENT_USER;
SHOW GRANTS FOR CURRENT_USER();

只是为了确保存在特权问题,您可以尝试以下方法:

sudo service mysql stop
sudo mysqld --skip-grant-tables

然后执行LOAD命令。

UPDATE

至于您的配置文件,出于安全原因,您有:

[mysqld]
local-infile=0

如果在服务器或客户端中禁用了LOAD DATA LOCAL,则尝试发出此类语句的客户端会收到以下错误消息:

ERROR 1148: The used command is not allowed with this MySQL version

您可以将除“admin”和“root”(例如)之外的所有用户设置为在mysql级别没有该特权,然后登录MySQL并运行查询:

UPDATE mysql.user SET File_priv='N' WHERE user!='da_admin' AND user!='root';
FLUSH PRIVILEGES;

对于命令行,尝试仅使用“--local-infile”的“--local-infile”,并让我们知道结果。

加载数据信息

该指令用于加载位于服务器上的文件。

要使用LOAD DATA INFILE ,请确保:

  • 连接用户具有FILE权限。 请参见6.2.1 MySQL提供的权限

  • 服务器具有足够的(文件系统)权限来读取文件。

  • 如果设置了secure_file_priv系统变量,则该文件位于该目录中。 服务器不会加载该目录之外的任何文件。

加载数据本地信息

该指令用于加载位于客户端上的文件。

要使用LOAD DATA INFILE ,请确保:

  • MySQL客户端使用-DENABLED_LOCAL_INFILE=1编译。 如果没有它, LOAD DATA LOCAL INFILE就无法工作。

    大多数发行版都使用此标志进行编译,但有些则不是。 这主要是手动编译MySQL的问题。

  • MySQL服务器以选项--local-infile=1

    您还可以在组[mysqld]下设置local-infile=1 ,以便在服务器启动时自动启用它。

    如果没有它, LOAD DATA LOCAL INFILE就无法工作。

  • [client]组下设置了loose-local-infile=1选项。 这并不总是需要,但最好确保这不是问题。

  • 要在PHP中使用LOAD DATA LOCAL INFILE ,您需要在构造新的数据库句柄时将driver-option PDO::MYSQL_ATTR_LOCAL_INFILEtrue 请参阅MySQL函数(PDO_MYSQL)

    必须在构造新的PDO实例时完成此操作。 之后使用PDO::setAttribute()将不起作用。

有关更多详细信息,请参见6.1.6 LOAD DATA LOCAL的安全问题

当我联系托管时,他们说我需要FILE权限才能执行此操作。 但这是不好的做法,并没有提出建议。

好吧,你有它。 您需要FILE权限才能执行您要执行的操作。 无论您使用的是PHP还是使用bash,实际情况都是如此,因为该权限来自MySQL。

虽然我对使用FILE权限的不良做法有所保留,但我确实认为存在严重的安全问题。 但是,您不必授予导入Excel电子表格的FILE权限。

我将为您提供两种解决方案,一种使用DATA INFILE ,另一种不使用。

首先,注意事项:

无论是否启用FILE权限,安全数据的关键是确保所有查询都能正确转义,尤其是那些接受用户输入的查询(例如下面的例子)。

DATA INFILE选项

如果你要分配FILE权限,最关心的我会是一个黑客将能够产生种种令人不快的数据,或者拉你不希望有人有数据(文章在这里介绍了如何READ LOCAL INFILE可能非常危险)。 如果您的主机允许,您可以创建一个具有FILE权限的单独用户,该权限只能通过localhost访问。 虽然这绝不是一个灵丹妙药,但它确实大大减少了黑客可以访问文件的渠道,以防你有注入漏洞。

CREATE USER 'filewriter'@'localhost' IDENTIFIED_BY 'some_really_long_and_complex_password';
GRANT FILE ON *.* TO 'filewriter'@'localhost';

DATA INFILE选项

考虑这个例子。

因为您使用的是PHP,所以我建议您创建一个PHP bash文件,或者只是将它放在脚本中并取出hashbang( #!/usr/bin/php )。

你应该可以做这样的事情:

#!/usr/bin/php

$mysqli = new mysqli("host_name", "username", "password", "database") or die("Could not connect.");

$file_handle = fopen("myfile.csv", "r");


$query="INSERT into my_table_name(user_name,user_address,user_class) values(?, ?, ?)";
//practice safe escaping and store records faster.
$stmt = $mysqli->prepare($query) or die(mysql_error());
$stmt->bind_param("sss", $col1, $col2, $col3);
while (($line_of_data = fgetcsv($file_handle, 1000, ",")) !== FALSE) {
    $col1 = $line_of_data[0];
    $col2 = $line_of_data[1];
    $col3 = $line_of_data[2];

    $stmt->execute();
}

$stmt->close();

通过使用PHP,我认为您习惯使用的语言,您将能够采取您需要的任何安全限制(我已经包含准备好的语句)并存储您的数据。 它可能没有LOAD DATA INFILE那么快,但它是一种在PHP中加载数据的安全方式。 如果您的电子表格不是很大(GB),这应该没问题。

这条线

Uncaught exception 'PDOException' with message 'SQLSTATE[28000]: Invalid authorization specification: 1045 Access denied for user 'myuser'@'localhost' (using password: YES)'

显然告诉你登录有问题,然后看看:

+------------------------------------------------------------------------------------------------------------------------+
| Grants for theuser@localhost                                                                                           |
+------------------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'theuser'@'localhost' IDENTIFIED BY PASSWORD '*password' |
| GRANT ALL PRIVILEGES ON `mydomain_live`.* TO 'theuser'@'localhost'                                                    |
| GRANT ALL PRIVILEGES ON `mydomain_staging`.* TO 'theuser'@'localhost' WITH GRANT OPTION                               |
+------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.01 sec)

告诉你,你只能访问数据库mydomain_livemydomain_staging ,所以你导入脚本应该是:

#!/bin/bash
/usr/bin/mysql --host=localhost --user=theuser --password=password --database=mydomain_staging<<EOFMYSQL
LOAD DATA INFILE 'locationofmyfile.csv'
INTO TABLE test_import 
FIELDS TERMINATED BY ';'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES ( ArtID, ArtNamePharmLang, ArtNameFr, ArtNameNl, PubPrice, PercentageRebate, RebateAmount, SellingPrice, Localisation, CnkNr, EanNr, SoldQty, MinThd, MaxThd, QtyInStock, DateLastSale, VatRate, SupplierManufName, BuyPrice, InvCatCode, ArtType, ApbCatCode, ApbLegCode, PharmApbNr );
EOFMYSQL

注意--database = mydomain_staging

你试过从命令行使用mysqlimport吗? 它应该等同于加载数据infile:

以下是在客户端使用--local选项的示例:

mysqlimport -uTHEUSER -pPASSWORD -h ServerIPorDomainGoesHere --local --compress db_name /somepath/TableName.csv

一个重要的细节是csv文件名必须是这里的表名,尝试它并告诉我们你是否仍然得到相同的错误。

如果mysqlimport不起作用,还尝试检查匿名用户的数据库:

mysql> select user,host from mysql.user;
+------------------+-----------+
| user             | host      |
+------------------+-----------+
| root             | localhost |
| root             | 127.0.0.1 |
| root             | ::1       |
|                  | localhost |
|                  | %         |
| myuser           | localhost |
+------------------+-----------+ 

尝试删除表中的空白用户名,因为在匹配“myuser”之前,您的登录将匹配此示例中的其中一个。 因此,即使对“myuser”拥有权限,匿名者也许不会。

希望能帮助到你!

出于安全原因,托管公司通常会禁用LOAD DATA INFILE,并建议使用LOAD DATA LOCAL。

这是来自Hostmonster的一个: https//my.hostmonster.com/cgi/help/317或者来自Bluehost的相同答案: https//my.bluehost.com/cgi/help/317

或者,您可以使用常用的fopen(),fgets()/ fgetcsv(),fclose()从PHP中读取文件中的数据,并将其插入MySQL表中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM