当mysql的wait_timeout被超出时,我的PHP CLI脚本失去连接。我无法更改wait_timeout,那么在使用PDOStatement执行查询时,如何构建重新连接的try/catch语句?PDO与PDOStatement在“mysql servers gone”错误时重新连接
回答
最好的方法是将PDO实例创建包装成一个存储实例和创建时间的单例(即MyPDOFactory),这样,您可以在达到TTL后重用它或重新创建它(2或3秒对于大多数应用来说已经足够了)。您只需调用MyPDOFactory :: get()即可获得一个可用于准备PDOStatement的有效PDO,只需确保尽快执行即可。
我认为这可以帮助你。
/* Your Database Name */
$dbname = 'mydatabase';
/* Your Database User Name and Passowrd */
$username = 'root';
$password = 'password';
try {
/* Establish the database connection */
$conn = new PDO("mysql:host=localhost;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
/* your code goes here*/
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
//mysql_close($conn);
$conn=null;
您的答案在超时后无法重新连接。在try块你应该把查询代码,如果连接不见了,重新连接catch块。然后以某种方式再次启动查询... – 2013-12-13 10:55:55
发生错误后重新连接到数据库实际上是一个比看起来更复杂的问题。
我的第一个想法是写PDO一个简单的包装类,代理方式在内部PDO对象,并且可以处理连接错误本身:
class BetterPDO extends PDO
{
private $realPDO = NULL;
private $dsn = "";
private $username = "";
private $password = "";
private $options = [];
public function __construct ($dsn, $username = "", $password = "", $options = [])
{
$this -> dsn = $dsn;
$this -> username = $username;
$this -> password = $password;
$this -> options = $options;
}
private function getRealPDO()
{
if (is_null ($this -> realPDO))
{
$this -> realPDO = new PDO ($this -> dsn, $this -> username, $this -> password, $this -> options);
}
return $this -> realPDO;
}
// We're only implementing exec for brevity but you have to do this for all public methods of PDO
public function exec ($sql)
{
$retries = 0;
while (true)
{
try
{
return $this -> getRealPDO() -> exec ($sql);
}
catch (PDOException $ex)
{
$this -> realPDO = NULL;
if (++$retries > 5)
{
// We've passed our retry limit
throw $ex;
}
}
}
}
}
由于这一类扩展PDO,它可以在任何地方使用的可以使用通用的PDO类。你可以看到,这种方法会在exec()方法放弃之前给你一些重试,允许在瞬时错误之后重新连接(这仅仅是为了演示,并且缺乏一些真正实现需要的功能,比如重试之间的退避,足够的错误记录等)。这种方法还需要您检查抛出的PDO异常的具体情况,理由是您不希望MySQL语法错误等事件导致连接重置并尝试重试。你只希望它发生在诸如“服务器已经消失”之类的事情上。
正如你所看到的,实现所有代理的PDO方法将会是一件苦差事,尽管你只需要投入努力就可以做到这一点。
虽然有一个更大的问题,这对任何与数据库进行通信的代码来说都是一个普遍问题,而不仅仅是PDO。如果在交易过程中连接丢失会发生什么?在这种情况下,您不希望脚本重新连接并选择停止的位置,因为您完成上一次提交所做的所有工作都将丢失,并且有可能会导致恢复失败重新连接后,你必须重新开始。因此,您可能只希望整个脚本重新开始,尝试重新连接就没有任何意义。这可能是为什么mySQLI支持重新连接,但PDO不支持。
如果您的脚本只读取或非事务性写入,那么上述方法仍然有价值,但只要您将事务处理引入混音中,您实际上会更好,而不会尝试重新连接。
- 1. PDO ::查询与PDOStatement ::执行(PHP和MySQL)
- 2. 通过php连接到mysql与pdo
- 3. 如何在连接类中使用PDO时显示mysql错误?
- 4. PDO连接抛出超时错误
- 5. 与MySQL连接错误
- 6. 错误的PDO SSL连接
- 7. Pdo Dblib Mssql连接错误
- 8. 与MySQL连接时出错
- 9. PDO重复更新错误
- 10. PHP PDO PDOStatement-> execute()
- 11. PDO :: PARAM_INT在PDOStatement ::执行
- 12. mySQL PDO错误
- 13. 执行后重新使用PDO连接?
- 14. 连接错误MySQL
- 15. MySQL连接错误
- 16. MySQL连接错误
- 17. Mysql连接错误
- 18. 错误MySQL连接
- 19. 连接mysql错误
- 20. MYSQL更新连接错误 - >
- 21. MySQL连接功能PDO
- 22. C++连接到mysql与库的错误
- 23. Unity3D与MySQL的连接错误
- 24. 与mysql错误的java连接
- 25. Java + MySQL与JDBC连接错误
- 26. PDO连接上的CakePHP和XAMPP错误
- 27. 连接错误,同时连接到MySQL数据库在asp.net
- 28. PDO返回MySQL错误与bindParam
- 29. MySQL问题重新连接(mysqld.exe)不断给出错误
- 30. 使用Asp.net与MySql连接时出错
我明白你的想法,但你真的应该添加代码到你的答案。 – 2013-12-03 21:40:52
如果您正在运行一组查询,那么会发生什么情况:a)事务性,以及b)比TTL需要更长的时间? – GordonM 2016-04-05 10:25:43