Слишком много ошибок соединения, когда я соединяюсь в цикле - PullRequest
1 голос
/ 16 октября 2019

Я пытаюсь загрузить CSV-файл через PHP, и мой CSV-файл имеет много записей (300). При загрузке процесса файла CSV, он загружает только 25 строк, после чего появляется ошибка PDO «Слишком много подключений». Есть ли способ ускорить процесс вставки?

while(($emapData = fgetcsv($file, 10000, ",")) !== FALSE){    
   try{    
      $dbcon = new PDO("mysql:host=$servername;dbname=$dbname",$username,$password);    
      $dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);    
      $stmt = $dbcon->prepare("INSERT INTO Growth(id, date, stage, length, width) VALUES(nullif('$emapData[0]','NULL'), nullif('$emapData[1]','NULL'), nullif('$emapData[2]','NULL'), nullif('$emapData[3]','NULL'), nullif('$emapData[4]','NULL')");
      $stmt->execute();
   }
   catch(PDOException $e){
      echo "Error: " . $e->getMessage();
   }
}

Ответы [ 2 ]

1 голос
/ 17 октября 2019

Переполнение стека многими воспринимается как услуга, позволяющая быстро решить возникающую проблему.

К сожалению, это также источник примеров кода многократного использования. И когда вы посмотрите на этот сайт с такой точки зрения, вы найдете большинство ответов ужасающих , так как они создают больше проблем, чем решают.

Взять, к примеру, этот пост. Код в OP неправильный на многих уровнях, по сути, неправильно использует подготовленное утверждение, отбрасывая все его преимущества. Ну, на самом деле все в порядке, так как мы все учимся. Но ответ оставляет все проблемы без изменений, сосредоточив внимание на одной конкретной проблеме. В результате у нас есть одобренный сообществом пример кода , который на самом деле чрезвычайно вреден . Хорошо, у меня есть опыт, чтобы сказать плохой код. Но ничего не подозревающий посетитель из Google не делает. И просто скопируйте и вставьте предложенное решение. Наряду со всеми его уязвимостями и неэффективностью.

Чтобы запустить подготовленный оператор в цикле:

  • конечно, соединение должно быть установлено до цикла
    • , кроме того, весь код подключения должен быть перемещенвне цикла, не только его часть
    • , кроме того, это должен быть правильный код подключения со всеми необходимыми опциями, чтобы в будущем не возникло новых проблем (вызванных неправильным charset например)
  • подготовленное утверждение должно быть фактическим подготовленным утверждением, а не имитацией. Все переменные в запросе должны быть заменены местозаполнителями , чтобы этот подготовленный оператор действительно делал что-нибудь полезное - прежде всего предотвращая SQL-инъекцию .
  • prepare() вызов должен быть также перемещен из цикла . В этом и заключается смысл такого заявления: подготовить один раз, выполнить несколько.
  • код обработки ошибок должен быть безопасным и гибким. Хотя echo "Error: " . $e->getMessage(); является чем-то большим, чем

Таким образом, правильный пример будет:

include 'pdo.php';
$sql = "INSERT INTO Growth(id, date, stage, length, width)
VALUES(nullif(?,'NULL'), nullif(?,'NULL'), nullif(?,'NULL'), nullif(?,'NULL'), nullif(?,'NULL')")
$stmt = $dbcon->prepare($sql);
while(($emapData = fgetcsv($file, 10000, ",")) !== FALSE){    
    $stmt->execute($emapData);
}

В этом коде были сделаны два предположения:

  • файл pdo.php содержит правильный код подключения PDO , поскольку вместо подключения в каждом файле код подключения должен быть перемещен в отдельный файл, а затем просто включен в каждый сценарий, для которого требуется подключение к базе данных
  • количество столбцов в файле csv равно количеству строк в таблице. В противном случае функция array_slice() должна быть вызвана заранее $emapData
1 голос
/ 16 октября 2019

сначала установите соединение с базой данных $dbcon, прежде чем вызывать операторы вставки.

$dbcon = new PDO("mysql:host=$servername;dbname=$dbname",$username,$password);

while(($emapData = fgetcsv($file, 10000, ",")) !== FALSE){    
    try{        
        $dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);    $stmt   = $dbcon->prepare("INSERT INTO Growth(id, date, stage, length, width) VALUES(nullif('$emapData[0]','NULL'), nullif('$emapData[1]','NULL'), nullif('$emapData[2]','NULL'), nullif('$emapData[3]','NULL'), nullif('$emapData[4]','NULL')");

        $stmt->execute();
    }
    catch(PDOException $e){
    echo "Error: " . $e->getMessage();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...