1

現在、ループして 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();

生成中のファイルは次のとおりです。 files_during_process

そして、ここで例外が発生した後: files_after_process

また、例外が発生したときに、$pdo_mbtiles の var_dump を実行すると、結果は次のようになります (成功した場合とまったく同じです)。

object(PDO)#116 (0) {
}

編集:この問題を解決しようとして、コードを単純化して MBTiles ファイルを作成しました。まだ成功していませんが、誰かが問題を再現したい場合は、ここにサンプルがあります. https://www.dropbox.com/s/33vqamc9tn4c3ux/sample_PHP_MBTiles_generation_bug.zip?dl=0からダウンロードできます。

4

2 に答える 2

0

エラー メッセージは誤解を招くものでした。何時間もデバッグした後、データベース接続とはまったく無関係であることがわかりました。fopen() を使用してタイル データを取得し、登録後に fclose() を使用しなかったため、1024 の制限に達したのは正当なことです。

1024 は、require または require_once ステートメントを 6 回使用したためです。したがって、1018 タイル リクエスト + 6 require = 1024 の接続が開かれました。

于 2015-09-17T14:42:56.580 に答える
0

開いている場合は、接続を再利用することをお勧めします。

プロパティを作成します。private $pdo;

新しいオブジェクトを作成する前に、null かどうかを確認します。

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();
    }
}
于 2015-09-11T14:56:20.387 に答える