代码之家  ›  专栏  ›  技术社区  ›  user2700551

多次操作后PHP出现SQL连接错误

  •  1
  • user2700551  · 技术社区  · 11 年前

    我目前正在循环创建一个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连接没有关闭。

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

    这里可能会出什么问题?

    我尝试在如下条件下移动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 回复  |  直到 9 年前
        1
  •  0
  •   Navnish Bhardwaj    11 年前

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

    创建属性: 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();
        }
    }
    
        2
  •  0
  •   user2700551    11 年前

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

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

    推荐文章