【问题标题】:SQL connection error from PHP after many operations多次操作后来自 PHP 的 SQL 连接错误
【发布时间】:2015-09-11 14:40:50
【问题描述】:

我目前正在循环创建一个 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]? 但是回显消息只出现在循环的第一次,所以我假设 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();

以下是生成过程中的文件:

在引发异常之后:

此外,当引发异常时,我对我的 $pdo_mbtiles 执行 var_dump,结果如下(与成功执行时完全相同):

object(PDO)#116 (0) {
}

编辑: 仍然试图解决这个问题,我简化了创建 MBTiles 文件的代码。还没有成功,但如果有人想重现这个问题,这里有一个示例。可以从https://www.dropbox.com/s/33vqamc9tn4c3ux/sample_PHP_MBTiles_generation_bug.zip?dl=0下载

【问题讨论】:

  • 尝试将 2 个 setAttributes() 调用移动到 if 中,因为它们只需要在您连接时运行一次,而不是每次都在循环中运行。或者将它们添加到您已经在连接中使用的属性数组中
  • 刚试了下,问题依旧。
  • 尝试使用closeCursor()
  • closeCursor 也无济于事。
  • 已编辑问题以包含文件权限详细信息。

标签: php sql pdo mbtiles


【解决方案1】:

如果连接是打开的,我建议你重用它。

创建属性: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();
    }
}

【讨论】:

  • 如果这是问题所在,我会在循环开始时收到错误消息。只有当我已经运行了 1018 次时它才会出现。较小的文件不会出现此问题。
  • MBTiles 地图是否使用任何具有限制视图的 API?
  • 我尝试了几个来源,都停在 1018,但在这种情况下,我通常会收到有关连接而不是数据库的其他错误消息。
  • 也通过community.sitepoint.com/t/… 这将提供更好的范围
【解决方案2】:

错误消息具有误导性。经过几个小时的调试,我发现它与我的数据库连接完全无关。 正好我用fopen()获取瓦片数据,注册后没有使用fclose(),所以达到了1024的限制。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 2018-03-31
    相关资源
    最近更新 更多