[英]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_INFILE
为true
。 请参阅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_live
和mydomain_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.