许多操作后来自PHP的SQL连接错误

时间:2015-09-11 14:40:51

标签: php sql pdo mbtiles

我正在循环创建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

我检查了这里写的解决方案: How to prevent SQLITE SQLSTATE[HY000] [14]? 但回显的消息只出现在循环的第一次,所以我假设P​​DO连接没有关闭。

我没有找到与此错误代码相关的其他文档。

这里可能出现什么问题?

我尝试在以下条件下移动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

下载

2 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分:0)

错误消息具有误导性。经过几个小时的调试,我发现它与我的数据库连接完全无关。 我使用fopen()来获取切片数据,并且在注册后没有fclose(),因此达到1024的限制。

1024是因为我使用了6个require或require_once语句,所以1018个tile请求+6个require = 1024个已打开的连接。