Я работаю в проекте, где требуется загрузить большой файл с удаленного сервера, который содержит данные, разделенные на трубы, около 5 миллионов записей.Нужно обходное решение против PHP 7.0.3 undefined function mysqli :: set_local_infile_handler()
После завершения загрузки необходимо загрузить данные в базу данных. В настоящее время я работаю с базой данных 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
Я попробовал несколько идей (только с 100 тысяч записей):
- Измененный от
new mysqli()
кmysqli_init()
иmysqli::real_connect()
, но единственная причина в том, что все примеры сmysqli::set_local_infile_handler
использовать последнюю форму. - Я раскопал
mysqli.allow_local_infile = On
в файлеphp.ini
, однако до этого я не имел проблем с запуском кода с локальным запросом 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 callback function, когда нашел
mysqli::set_local_infile_handler
ссылку.
Я был с этим весь день, так что я должен был попробовал некоторые другие вещи, но как я не помню их, или они не имеют никакого отношения на данный момент. Спасибо заранее.
Я не вижу ошибок в коде, он работает без локальных методов входной_файл, но здесь это:
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
и таблицы сценария:
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;
Опубликовать код, вызывающий ошибку. Возможно, вы называете это неправильным. – ShiraNai7
Вы можете разветвить дочерний процесс, чтобы выполнить загрузку и импорт файла, затем введите бесконечный цикл (каждый со сном() и некоторым условием для выхода с ошибкой или завершением) ... затем проверьте innodb_rows_inserted (as вы упомянули об изменениях). Викинг: http://php.net/manual/en/function.pcntl-fork.php –
Хорошо, добавлен код. Я изменил некоторые вещи, связанные с частными данными. –