PHP ZF2 Mysql 已经消失
PHP ZF2 Mysql has gone away
您好,我有一个 php 守护进程可以处理来自 rabbitmq
的请求
一天后,由于错误 MySQL 已消失,无法再执行。
PHP Warning: PDOStatement::execute(): MySQL server has gone away in /var/www/daemon/www/vendor/zendframework/zendframework/library/Zend/Db/Adapter/Driver/Pdo/Statement.php on line 239
PHP Warning: PDOStatement::execute(): Error reading result set\'s header in /var/www/daemon/www/vendor/zendframework/zendframework/library/Zend/Db/Adapter/Driver/Pdo/Statement.php on line 239
我没有使用学说,而是将我的 \Zend\Db\Adapter\Adapter 发送到具有以下功能的数据库包装器 class。
public static function executeScalar($statement, $parameters, \Zend\Db\Adapter\Adapter $dbAdapter)
{
$dbResult = new DbResult();
if (! $statement) {
$dbResult->addError('No statement given');
return $dbResult;
}
$stmt = $dbAdapter->createStatement();
$stmt->prepare($statement);
foreach ($parameters as $key => &$param) {
$stmt->getResource()->bindParam($key + 1, $param[0], $param[1]);
}
try {
$result = $stmt->execute();
$dbResult->setResult($result);
} catch (\Zend\Db\Adapter\ExceptionInterface $e) {
$dbResult->addError('DB Error');
$message = $e->getPrevious() ? $e->getPrevious()->getMessage() : $e->getMessage();
$dbResult->addError($message);
} catch (\Zend\Db\Adapter\Exception $e) {
$dbResult->addError('DB Error');
$dbResult->addError($e->getMessage());
} catch (\PDOException $e) {
$dbResult->addError('DB Error');
$dbResult->addError($e->getMessage());
} catch (\Exception $e) {
$dbResult->addError('DB Error');
$dbResult->addError($e->getMessage());
}
$stmt->getResource()->closeCursor();
return $dbResult;
}
DbResult 是我自己的db result wrapper class 它主要检查return 是否为空,错误是什么,有多少行等
这是我的 database.local.php 配置
return array(
'service_manager' => array(
'factories' => array(
'mysql' => function ($sm)
{
return new Zend\Db\Adapter\Adapter(array(
'driver' => 'PdoMysql',
'hostname' => 'localhost',
'database' => 'daemon',
'username' => 'daemon',
'password' => 'password',
'driver_options' => array(
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_EMULATE_PREPARES => true,
\PDO::MYSQL_ATTR_LOCAL_INFILE => true
)
));
},
)
)
)
所以每次我想执行 sql 时,我都会在控制器或任何其他 class 中执行此操作(仅举个例子)
$service = $this->getServiceLocator();
$dbAdapter = $service->get('mysql');
$get = \Db\Database::executeScalar('SELECT * FROM mytable WHERE id <= ?', array(10), $dbAdapter);
我似乎无法捕捉到警告,有没有办法强制重新连接,或者我可能只是在每次请求后断开连接?
这可以处理错误吗?
对于每个新请求,我都会这样做
$dbAdapter->getDriver()->getConnection()->connect();
在请求结束时我这样做
$dbAdapter->getDriver()->getConnection()->disconnect();
您可以创建与数据库的持久连接,但请注意,创建持久连接不应该是第一个要寻找的解决方案。在尝试之前一定要对该主题进行一些研究。您可以在此处找到一些文档:
http://php.net/manual/en/pdo.connections.php#example-954
另一方面,您应该查找已发送的查询,以便消息消失的原因不是由 mysql 服务器收到的数据包太大(例如:插入大 blob)引起的。因为如果是,连接仍然会意外关闭。
是的,我检查了持久连接选项,但我也不喜欢它。
我发现了问题,它是由 mysql 服务器在 'wait timeout' 之后关闭空闲连接引起的。当 mysql 关闭空闲连接时,PDO 将不会收到任何事件,因此下次您发起查询时它会 return Mysql has gone away 错误。
对于 http 请求,这是可以接受的,因为在服务器响应请求后,它将 stop/exit php 执行关闭与数据库的所有连接。
对于 daemon/service 这是不可接受的,因为它大部分时间都在等待客户端请求(空闲)。我的解决方案是每次完成处理客户端请求时关闭连接。例如:
while (true) {
//listen to rabbitmq queue
//...
//do something base on client request from rabbitmq queue
//...
//close the connection whether it use database or not
//connection will be reconnected when we call $service->get('mysql');
$service = $this->getServiceLocator();
$dbAdapter = $service->get('mysql');
$dbAdapter->getDriver()->getConnection()->disconnect();
}
您好,我有一个 php 守护进程可以处理来自 rabbitmq
的请求一天后,由于错误 MySQL 已消失,无法再执行。
PHP Warning: PDOStatement::execute(): MySQL server has gone away in /var/www/daemon/www/vendor/zendframework/zendframework/library/Zend/Db/Adapter/Driver/Pdo/Statement.php on line 239
PHP Warning: PDOStatement::execute(): Error reading result set\'s header in /var/www/daemon/www/vendor/zendframework/zendframework/library/Zend/Db/Adapter/Driver/Pdo/Statement.php on line 239
我没有使用学说,而是将我的 \Zend\Db\Adapter\Adapter 发送到具有以下功能的数据库包装器 class。
public static function executeScalar($statement, $parameters, \Zend\Db\Adapter\Adapter $dbAdapter)
{
$dbResult = new DbResult();
if (! $statement) {
$dbResult->addError('No statement given');
return $dbResult;
}
$stmt = $dbAdapter->createStatement();
$stmt->prepare($statement);
foreach ($parameters as $key => &$param) {
$stmt->getResource()->bindParam($key + 1, $param[0], $param[1]);
}
try {
$result = $stmt->execute();
$dbResult->setResult($result);
} catch (\Zend\Db\Adapter\ExceptionInterface $e) {
$dbResult->addError('DB Error');
$message = $e->getPrevious() ? $e->getPrevious()->getMessage() : $e->getMessage();
$dbResult->addError($message);
} catch (\Zend\Db\Adapter\Exception $e) {
$dbResult->addError('DB Error');
$dbResult->addError($e->getMessage());
} catch (\PDOException $e) {
$dbResult->addError('DB Error');
$dbResult->addError($e->getMessage());
} catch (\Exception $e) {
$dbResult->addError('DB Error');
$dbResult->addError($e->getMessage());
}
$stmt->getResource()->closeCursor();
return $dbResult;
}
DbResult 是我自己的db result wrapper class 它主要检查return 是否为空,错误是什么,有多少行等
这是我的 database.local.php 配置
return array(
'service_manager' => array(
'factories' => array(
'mysql' => function ($sm)
{
return new Zend\Db\Adapter\Adapter(array(
'driver' => 'PdoMysql',
'hostname' => 'localhost',
'database' => 'daemon',
'username' => 'daemon',
'password' => 'password',
'driver_options' => array(
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_EMULATE_PREPARES => true,
\PDO::MYSQL_ATTR_LOCAL_INFILE => true
)
));
},
)
)
)
所以每次我想执行 sql 时,我都会在控制器或任何其他 class 中执行此操作(仅举个例子)
$service = $this->getServiceLocator();
$dbAdapter = $service->get('mysql');
$get = \Db\Database::executeScalar('SELECT * FROM mytable WHERE id <= ?', array(10), $dbAdapter);
我似乎无法捕捉到警告,有没有办法强制重新连接,或者我可能只是在每次请求后断开连接?
这可以处理错误吗? 对于每个新请求,我都会这样做
$dbAdapter->getDriver()->getConnection()->connect();
在请求结束时我这样做
$dbAdapter->getDriver()->getConnection()->disconnect();
您可以创建与数据库的持久连接,但请注意,创建持久连接不应该是第一个要寻找的解决方案。在尝试之前一定要对该主题进行一些研究。您可以在此处找到一些文档:
http://php.net/manual/en/pdo.connections.php#example-954
另一方面,您应该查找已发送的查询,以便消息消失的原因不是由 mysql 服务器收到的数据包太大(例如:插入大 blob)引起的。因为如果是,连接仍然会意外关闭。
是的,我检查了持久连接选项,但我也不喜欢它。
我发现了问题,它是由 mysql 服务器在 'wait timeout' 之后关闭空闲连接引起的。当 mysql 关闭空闲连接时,PDO 将不会收到任何事件,因此下次您发起查询时它会 return Mysql has gone away 错误。
对于 http 请求,这是可以接受的,因为在服务器响应请求后,它将 stop/exit php 执行关闭与数据库的所有连接。
对于 daemon/service 这是不可接受的,因为它大部分时间都在等待客户端请求(空闲)。我的解决方案是每次完成处理客户端请求时关闭连接。例如:
while (true) {
//listen to rabbitmq queue
//...
//do something base on client request from rabbitmq queue
//...
//close the connection whether it use database or not
//connection will be reconnected when we call $service->get('mysql');
$service = $this->getServiceLocator();
$dbAdapter = $service->get('mysql');
$dbAdapter->getDriver()->getConnection()->disconnect();
}