В настоящее время я зацикливаюсь на создании карты MBTiles и каждый раз добавляю информацию в свою базу данных.
Вот как я настроил свое соединение и выполняю действия во время цикла:
if ($pdo_mbtiles == null) {
echo "Opening new database connection".PHP_EOL;
$pdo_mbtiles = new PDO('sqlite:'.$filename,
'',
'',
array(
PDO::ATTR_PERSISTENT => true
)
);
$pdo_mbtiles->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$pdo_mbtiles->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
$q = $pdo_mbtiles->prepare("INSERT INTO tiles (zoom_level, tile_column, tile_row,tile_data) VALUES (:zoom_level, :tile_column, :tile_rowTMS, :tile_data)");
$q->bindParam(':zoom_level', $zoom_level);
$q->bindParam(':tile_column', $tile_column);
$q->bindParam(':tile_rowTMS', $tile_rowTMS);
$q->bindParam(':tile_data', $tile_data, PDO::PARAM_LOB);
$q->execute();
После 1018 циклов (это число не меняется независимо от того, сколько раз я пытаюсь), я получаю это сообщение об ошибке:
SQLSTATE[HY000]: General error: 14 unable to open database file
Я проверил решение, написанное здесь:
Как предотвратить SQLITE SQLSTATE [HY000] [14]?
но эхо-сообщение появляется только в первый раз цикла, поэтому я предполагаю, что соединение PDO не закрыто.
Я не нашел другой документации, относящейся к этому коду ошибки.
Что здесь может пойти не так?
Я попытался переместить команды prepare и bind в следующее состояние. Исключение не возникает, но сохраняется только первая плитка (или каждая плитка сохраняется поверх первой, не уверен):
if ($pdo_mbtiles == null) {
echo "Opening new database connection".PHP_EOL;
$pdo_mbtiles = new PDO('sqlite:'.$filename,
'',
'',
array(
PDO::ATTR_PERSISTENT => true
)
);
$pdo_mbtiles->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$pdo_mbtiles->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
if ($q == null) {
$q = $pdo_mbtiles->prepare("INSERT INTO tiles (zoom_level, tile_column, tile_row,tile_data) VALUES (:zoom_level, :tile_column, :tile_rowTMS, :tile_data)");
$q->bindParam(':zoom_level', $zoom_level);
$q->bindParam(':tile_column', $tile_column);
$q->bindParam(':tile_rowTMS', $tile_rowTMS);
$q->bindParam(':tile_data', $tile_data, PDO::PARAM_LOB);
}
$q->execute();
И тут после исключения возбуждается:
Кроме того, когда возникает исключение, я делаю var_dump из моего $ pdo_mbtiles, и вот результат (точно такой же, как когда я делаю это с успехом):
object(PDO)#116 (0) {
}
Редактировать: Все еще пытаясь решить эту проблему, я упростил код для создания файла MBTiles. Пока безуспешно, но вот пример, если кто-то хочет воспроизвести проблему. Вы можете скачать его с https://www.dropbox.com/s/33vqamc9tn4c3ux/sample_PHP_MBTiles_generation_bug.zip?dl=0
Я предлагаю вам повторно использовать соединение, если оно открыто.
Создать свойство: private $pdo;
И проверьте, является ли он нулевым, прежде чем создавать новый объект:
function opendatabase(){
try{
if($this->pdo==null){
$this->pdo =new PDO("sqlite:database/database.db","","",array(
PDO::ATTR_PERSISTENT => true
));
}
return $this->pdo;
}catch(PDOException $e){
logerror($e->getMessage(), "opendatabase");
print "Error in openhrsedb ".$e->getMessage();
}
}
Сообщение об ошибке вводило в заблуждение. После многих часов отладки я обнаружил, что это совершенно не связано с подключением к моей базе данных.
Это правда, что я использовал fopen () для получения данных тайлов, и не зарегистрировал fclose (), таким образом, достигнув предела 1024.
1024 — потому что я использовал шесть операторов require или require_once, поэтому 1018 запросов плиток + 6 require = 1024 открытых соединения.