需要针对 PHP 7.0.3 未定义函数 mysqli::set_local_infile_handler() 的解决方法
Need workaround against PHP 7.0.3 undefined function mysqli::set_local_infile_handler()
我在一个项目中工作,需要从远程服务器下载一个大文件,其中包含大约 500 万条记录的管道分隔数据。
下载完成后需要将数据加载到数据库中。目前我一直在使用 MySQL 数据库,所以我没有考虑其他选择。
我使用面向对象 MySQLi 并调用 LOAD DATA LOCAL INFILE
查询。
完成需要一个半小时到两个小时,我需要一种显示进度的方法,我找到的唯一选项是 set_local_infile_handler
方法。似乎此方法的目的是允许程序员在将数据提供给查询之前更改数据的格式,但作为我发现的唯一选择,我想将它用于我的进度目的。
然而我得到的是:
PHP Fatal error: Uncaught Error: Call to undefined method mysqli::set_local_infile_handler() in C:\Repositories\project\tools\loaddata.php:65
我要求:
- 在我的代码中启用
mysqli::set_local_infile_handler
的修复程序
- MySQLi 的替代方案,用于在加载数据时显示进度
- 使用PHP
的其他替代方案
我尝试了一些想法(只有 10 万条记录):
- 已从
new mysqli()
更改为 mysqli_init()
和 mysqli::real_connect()
,但唯一的原因是因为所有带有 mysqli::set_local_infile_handler
的示例都使用后一种形式。
- 我在
php.ini
文件中取消了 mysqli.allow_local_infile = On
的注释,但是我没有遇到 运行 之前使用本地 infile 查询的代码的问题,但我预计这可能会使麻烦的方法可见.顺便把服务器停了再启动。
我调用了第二个查询
SHOW STATUS WHERE Variable_name in ('bytes_received','bytes_sent','innodb_buffer_pool_pages_data','innodb_buffer_pool_bytes_data','innodb_buffer_pool_pages_flushed','innodb_buffer_pool_read_requests','innodb_buffer_pool_reads','innodb_buffer_pool_write_requests','innodb_data_read','innodb_data_reads','innodb_data_writes','innodb_data_written','innodb_rows_inserted')
.
我保留了所有这些变量,因为我没有仔细研究每个变量的确切含义,我注意到只有那些变量发生了有意义的变化,但似乎最后一个可能就足够了。但是我使用单独的文件执行此操作,我还不知道我是否可以在同一代码中有两个连接 运行 和两个线程在后台具有最慢的 运行。事实上,我在浏览 php mysqli 回调函数 时发现了 mysqli::set_local_infile_handler
参考。
我整天都在用这个,所以我一定尝试过一些其他的东西,但要么我不记得它们,要么它们暂时无关紧要。
提前致谢。
我没有看到代码中的错误,它可以在没有本地 infile 方法的情况下工作,但这里是:
require_once("connectvars.php");
$filepath = $_SERVER["argv"][1];
$bloqIdx=0;
$conn = mysqli_init();
$conn->real_connect($mysvr,$myusr,$mypwd,$mydb);
// $conn = new mysqli($mysvr,$myusr,$mypwd,$mydb);
if ($conn->connect_error) {
trigger_error("SQL".$conn->connect_error,E_USER_ERROR);
die("Connect Error");
}
function countData($stream, &$buffer, $buflen, &$errmsg) {
global $bloqIdx;
$len = strlen($buffer);
if ($bloqIdx%1000==0) echo ".";
return $len;
}
function getRowsInserted() {
global $conn;
$result = $conn->query("show status where Variable_name='innodb_rows_inserted')";
$rowsInserted=0;
if ($result && $conn->affected_rows>0 && $row = $result->fetch_assoc()) $rowsInserted=$row["Value"];
$result->close();
return $rowsInserted;
}
$conn->query("truncate mytable");
$riStart = getRowsInserted();
$start = time();
$query = "LOAD DATA LOCAL INFILE '$filepath' INTO TABLE mytable FIELDS TERMINATED by '|' LINES TERMINATED BY '\n'";
$conn->set_local_infile_handler("countData");
$conn->query($query);
$conn->set_local_infile_default();
$minutes = abs(time() - $start)/60;
$riEnd = getRowsInserted()-$riStart;
echo "Finished Loading $riEnd rows from $filepath for ".round($minutes,2)." minutes\n";
$conn->close();
通过注释行:
$conn->set_local_infile_handler("countData");
和
$conn->set_local_infile_default();
代码有效,但没有进度信息。
在 http://php.net/manual/en/mysqli.set-local-infile-handler.php 有效版本显然是 (PHP 5, PHP 7)
如果您真的需要测试代码,作为参数的文本文件可以是这样的:
1|one|alpha|C|2012-10-21 17:44:18
2|two|beta|C|2013-02-05 12:23:57
3|three|gamma|C|2012-12-10 07:18:09
4|four|delta|X|2012-11-27 11:51:32
5|five|phi|C|2013-01-07 14:03:29
和table脚本:
create table `mytable` (
`id` INT NOT NULL,
`num` CHAR(10) NULL,
`code` CHAR(13) NULL,
`status` CHAR(1) NULL,
`registered` DATETIME NULL,
INDEX `mycode` (`code` ASC, `registered` ASC),
PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_bin;
您可以将它们分成 2 个不同的进程。
第一个进程 运行 每分钟由一个 cron 作业执行,并查找是否存在某种触发器(如 tmp 文件)。当找到触发器时,它会删除触发器(tmp 文件),下载大文件,将文件重命名为包含要插入的总行数的格式,然后开始将行插入数据库。
第二个进程是gui。它为用户提供了一个创建触发器(tmp 文件)的按钮,然后定期检查下载文件是否存在。一旦第一个进程将下载文件重命名为给定格式,它就可以解析文件名以获得总行数,然后定期查询数据库以确定现有行数并将其作为完成百分比呈现给用户。
现在我将这个案例报告为一个错误。今天加了一条评论。此方法已被删除。
我在一个项目中工作,需要从远程服务器下载一个大文件,其中包含大约 500 万条记录的管道分隔数据。
下载完成后需要将数据加载到数据库中。目前我一直在使用 MySQL 数据库,所以我没有考虑其他选择。
我使用面向对象 MySQLi 并调用 LOAD DATA LOCAL INFILE
查询。
完成需要一个半小时到两个小时,我需要一种显示进度的方法,我找到的唯一选项是 set_local_infile_handler
方法。似乎此方法的目的是允许程序员在将数据提供给查询之前更改数据的格式,但作为我发现的唯一选择,我想将它用于我的进度目的。
然而我得到的是:
PHP Fatal error: Uncaught Error: Call to undefined method mysqli::set_local_infile_handler() in C:\Repositories\project\tools\loaddata.php:65
我要求:
- 在我的代码中启用
mysqli::set_local_infile_handler
的修复程序 - MySQLi 的替代方案,用于在加载数据时显示进度
- 使用PHP 的其他替代方案
我尝试了一些想法(只有 10 万条记录):
- 已从
new mysqli()
更改为mysqli_init()
和mysqli::real_connect()
,但唯一的原因是因为所有带有mysqli::set_local_infile_handler
的示例都使用后一种形式。 - 我在
php.ini
文件中取消了mysqli.allow_local_infile = On
的注释,但是我没有遇到 运行 之前使用本地 infile 查询的代码的问题,但我预计这可能会使麻烦的方法可见.顺便把服务器停了再启动。 我调用了第二个查询
SHOW STATUS WHERE Variable_name in ('bytes_received','bytes_sent','innodb_buffer_pool_pages_data','innodb_buffer_pool_bytes_data','innodb_buffer_pool_pages_flushed','innodb_buffer_pool_read_requests','innodb_buffer_pool_reads','innodb_buffer_pool_write_requests','innodb_data_read','innodb_data_reads','innodb_data_writes','innodb_data_written','innodb_rows_inserted')
.我保留了所有这些变量,因为我没有仔细研究每个变量的确切含义,我注意到只有那些变量发生了有意义的变化,但似乎最后一个可能就足够了。但是我使用单独的文件执行此操作,我还不知道我是否可以在同一代码中有两个连接 运行 和两个线程在后台具有最慢的 运行。事实上,我在浏览 php mysqli 回调函数 时发现了
mysqli::set_local_infile_handler
参考。
我整天都在用这个,所以我一定尝试过一些其他的东西,但要么我不记得它们,要么它们暂时无关紧要。 提前致谢。
我没有看到代码中的错误,它可以在没有本地 infile 方法的情况下工作,但这里是:
require_once("connectvars.php");
$filepath = $_SERVER["argv"][1];
$bloqIdx=0;
$conn = mysqli_init();
$conn->real_connect($mysvr,$myusr,$mypwd,$mydb);
// $conn = new mysqli($mysvr,$myusr,$mypwd,$mydb);
if ($conn->connect_error) {
trigger_error("SQL".$conn->connect_error,E_USER_ERROR);
die("Connect Error");
}
function countData($stream, &$buffer, $buflen, &$errmsg) {
global $bloqIdx;
$len = strlen($buffer);
if ($bloqIdx%1000==0) echo ".";
return $len;
}
function getRowsInserted() {
global $conn;
$result = $conn->query("show status where Variable_name='innodb_rows_inserted')";
$rowsInserted=0;
if ($result && $conn->affected_rows>0 && $row = $result->fetch_assoc()) $rowsInserted=$row["Value"];
$result->close();
return $rowsInserted;
}
$conn->query("truncate mytable");
$riStart = getRowsInserted();
$start = time();
$query = "LOAD DATA LOCAL INFILE '$filepath' INTO TABLE mytable FIELDS TERMINATED by '|' LINES TERMINATED BY '\n'";
$conn->set_local_infile_handler("countData");
$conn->query($query);
$conn->set_local_infile_default();
$minutes = abs(time() - $start)/60;
$riEnd = getRowsInserted()-$riStart;
echo "Finished Loading $riEnd rows from $filepath for ".round($minutes,2)." minutes\n";
$conn->close();
通过注释行:
$conn->set_local_infile_handler("countData");
和
$conn->set_local_infile_default();
代码有效,但没有进度信息。
在 http://php.net/manual/en/mysqli.set-local-infile-handler.php 有效版本显然是 (PHP 5, PHP 7)
如果您真的需要测试代码,作为参数的文本文件可以是这样的:
1|one|alpha|C|2012-10-21 17:44:18
2|two|beta|C|2013-02-05 12:23:57
3|three|gamma|C|2012-12-10 07:18:09
4|four|delta|X|2012-11-27 11:51:32
5|five|phi|C|2013-01-07 14:03:29
和table脚本:
create table `mytable` (
`id` INT NOT NULL,
`num` CHAR(10) NULL,
`code` CHAR(13) NULL,
`status` CHAR(1) NULL,
`registered` DATETIME NULL,
INDEX `mycode` (`code` ASC, `registered` ASC),
PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_bin;
您可以将它们分成 2 个不同的进程。
第一个进程 运行 每分钟由一个 cron 作业执行,并查找是否存在某种触发器(如 tmp 文件)。当找到触发器时,它会删除触发器(tmp 文件),下载大文件,将文件重命名为包含要插入的总行数的格式,然后开始将行插入数据库。
第二个进程是gui。它为用户提供了一个创建触发器(tmp 文件)的按钮,然后定期检查下载文件是否存在。一旦第一个进程将下载文件重命名为给定格式,它就可以解析文件名以获得总行数,然后定期查询数据库以确定现有行数并将其作为完成百分比呈现给用户。
现在我将这个案例报告为一个错误。今天加了一条评论。此方法已被删除。