Ошибка подключения SQL из PHP после многих операций

В настоящее время я зацикливаюсь на создании карты 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 не закрыто.

Я не нашел другой документации, относящейся к этому коду ошибки.

Что тут может пойти не так?

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

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();

Вот файлы во время генерации: files_during_process

А здесь после возбуждения исключения: files_after_process

Кроме того, когда возникает исключение, я делаю var_dump своих $pdo_mbtiles, и вот результат (точно такой же, как если бы я сделал это с успехом):

object(PDO)#116 (0) {
}

Изменить. Пытаясь решить эту проблему, я упростил код для создания файла MBTiles. Пока безуспешно, но вот пример, если кто-то хочет воспроизвести проблему. Вы можете скачать его с https://www.dropbox.com/s/33vqamc9tn4c3ux/sample_PHP_MBTiles_generation_bug.zip?dl=0


person user2700551    schedule 11.09.2015    source источник
comment
Попробуйте переместить 2 вызова setAttributes() внутрь if, поскольку их нужно запускать только один раз при подключении, а не каждый раз по циклу. Или добавьте их в массив атрибутов, который вы уже используете в соединении.   -  person RiggsFolly    schedule 11.09.2015
comment
Только что попробовал, но проблема все еще здесь.   -  person user2700551    schedule 11.09.2015
comment
Попробуйте использовать closeCursor().   -  person JimmyB    schedule 11.09.2015
comment
closeCursor тоже не помогает.   -  person user2700551    schedule 11.09.2015
comment
Вопрос отредактирован, чтобы включить сведения о правах доступа к файлам.   -  person user2700551    schedule 14.09.2015
comment
В конце концов, ошибка не была связана с базой данных. Он просто не мог открыть его, потому что я открывал fopen() для заполнения базы данных каждый раз, не закрывая ее. Ошибка должна была быть вызвана PHP, например, «слишком много соединений открыто», а не PDO, сообщающим, что доступ к базе данных невозможен.   -  person user2700551    schedule 17.09.2015


Ответы (2)


Я предлагаю вам повторно использовать соединение, если оно открыто.

Создайте свойство: 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();
    }
}
person Navnish Bhardwaj    schedule 11.09.2015
comment
Если бы это было проблемой, я бы получил сообщение об ошибке в начале цикла. Он появляется только тогда, когда я уже пробежал его 1018 раз. Проблема не появляется для файлов меньшего размера. - person user2700551; 11.09.2015
comment
Использует ли карта MBTiles какие-либо API с ограничением просмотра? - person Navnish Bhardwaj; 11.09.2015
comment
Я пробовал несколько источников, все остановились на 1018, но обычно я получаю другие сообщения об ошибках соединения, а не базы данных, когда это так. - person user2700551; 11.09.2015
comment
Также доступна справка на этом dev.mysql.com/ doc/refman/5.0/en/error-messages-server.html - person Navnish Bhardwaj; 11.09.2015
comment
Также просмотрите community.sitepoint.com/t/ это обеспечит лучший охват - person Navnish Bhardwaj; 11.09.2015
comment
Вы обновили свой ответ, но опять же, если бы проблема заключалась в разрешениях, он не стал бы ждать 1018 подключений, чтобы сказать, что он не работает. Я почитаю ваши ссылки. - person user2700551; 11.09.2015
comment
В вашей первой ссылке нет ссылки на ошибку HY000 14, поэтому я прочитал вторую ссылку, но она предлагает обратить внимание на кавычки. Я получаю другие сообщения об ошибках при добавлении кавычек, так как я не могу их удалить. - person user2700551; 11.09.2015
comment
Я отредактировал свой вопрос, включив в него сведения о правах доступа к файлам. - person user2700551; 14.09.2015
comment
Обновлен ответ и предложено повторно использовать соединение - person Navnish Bhardwaj; 14.09.2015
comment
Если бы вы читали мой вопрос, вы бы заметили, что я связался с этим предложением, применил его к своему коду и до сих пор не решает его... - person user2700551; 14.09.2015

Сообщение об ошибке вводило в заблуждение. После многих часов отладки я обнаружил, что это совершенно не связано с моим подключением к базе данных. Просто я использовал fopen() для получения данных о тайлах и не использовал fclose() после регистрации, достигнув предела в 1024.

1024 потому, что я использовал шесть операторов require или require_once, поэтому 1018 запросов тайлов + 6 require = 1024 открытых соединения.

person user2700551    schedule 17.09.2015