SQL 多次操作后来自 PHP 的连接错误
SQL connection error from PHP after many operations
我目前正在循环创建 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
下载
如果连接打开,我建议您重新使用它。
创建一个属性: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();
}
}
错误消息具有误导性。经过几个小时的调试,我发现它与我的数据库连接完全无关。
正好我用fopen()获取tiles数据,注册后没有fclose(),就达到了1024的限制
1024 是因为我使用了 6 个 require 或 require_once 语句,所以 1018 tile requests + 6 require = 1024 opened connections.
我目前正在循环创建 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
下载如果连接打开,我建议您重新使用它。
创建一个属性: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();
}
}
错误消息具有误导性。经过几个小时的调试,我发现它与我的数据库连接完全无关。 正好我用fopen()获取tiles数据,注册后没有fclose(),就达到了1024的限制
1024 是因为我使用了 6 个 require 或 require_once 语句,所以 1018 tile requests + 6 require = 1024 opened connections.