支持自动重连接的PHP PDO类完善

支持自动重连接的PHP PDO类完善
 PHP的PDO是取代原来的php-mysql、php-mysqli模块的统一数据库访问模块,

比直接使用各自数据库提供的原始扩展函数相比,PDO的好处是移植性更好些。

最近在使用PDO开发框架过程,对其有了更多些的认识。

*)对长连接的支持

*)异常的使用

*)连接的自动关闭控制

*)连接中断的重连接(MySQL has gone away)

*)

最近遇到特别麻烦的问题,使用长连接是,全出来 MySQL Server has gone away的问题。

这种情况下PDO没有办法检测并重连接,也没有提供重新连接的相关方法。

这样对长连接的使用有点悲催了,开始运行的很正常的系统,运行一段时间后,却因为数据库连接的问题系统瘫痪了。

经过很多的代码测试与查找资料,实现了一个能重连接的PDO封装。在此分享思路与主要代码,补充PDO在实际应用中遇到的问题。

该封装的主要思路:
使用PDO的异常模式设置,
通过PHP魔法方法__call($name, $args)代理PDO的所有方法,
在代理方法中截获PDO的异常,判断异常的类型,确定是否需要重新连接。
在这一层封装还屏蔽了PDO的异常功能,所有的PDO操作成功与否需要通过调用返回值和errorInfo等方法取得。

这种方法为了实现自动重连功能,实际上降低了代码的效率。
在实际应用中,根据需要确定对效率的需求如何,是否可以接受这种效率损失。

最后,希望能在PDO的核心改进这个问题,或者提供显著重连接的方法,

或者提供显式的关闭当前已经中断连接的方法,

更或者提供一个参数,让PDO确定在遇到这种问题时能够自动重连接,如PDO::AUTO_RECONNECT。

抽时间出看看PDO的代码,看自己能否简单的HACKING下PDO扩展模块,实现我们需要的功能。

附:自动重连接PDO封装类:

    1. public function __call($name, array $arguments)
    2. {
    3. $result = false;
    4. $cnter = self::REQUERY_TIMES;
    5. do {
    6. try {
    7. $result = call_user_func_array(array($this->connection(), $name), $arguments);
    8. if ($result instanceof PDOStatement) {
    9. $result = new ReconnectingPDOStatement($result);
    10. }
    11. break;
    12. } catch(PDOException $e) {
    13. if($e->getCode() != 'HY000' || !stristr($e->getMessage(), 'server has gone away')) {
    14. throw $e;
    15. }
    16.  
    17. $this->reconnect();
    18. }
    19. } while($cnter-- > 0);
    20.  
    21. return $result;
    22. }
    23.  
    24. protected function connection()
    25. {
    26. return $this->pdo instanceof PDO ? $this->pdo : $this->connect();
    27. }
    28. public function connect()
    29. {
    30. $dsn = $this->dsn.';'.time()%10;
    31. if($this->pdo)
    32. {
    33. //让php先回收已断开长连接资源
    34. $this->pdo->setAttribute(PDO::ATTR_PERSISTENT, false);
    35. $this->pdo = null;
    36. $this->pdo = new PDO($dsn, $this->username, $this->password, (array) $this->driver_options);
    37. $this->pdo->setAttribute(PDO::ATTR_TIMEOUT, 3600);
    38. $this->pdo->setAttribute(PDO::ATTR_PERSISTENT, true);
    39. }
    40. else
    41. {
    42. $this->pdo = new PDO($dsn, $this->username, $this->password, (array) $this->driver_options);
    43. $this->pdo->setAttribute(PDO::ATTR_TIMEOUT, 3600);
    44. }
    45.  
    46. return $this->pdo;
    47. }
    48.  
    49. public function reconnect()
    50. {
    51. return $this->connect();
    52. }
    53. }
    54.  
    55. class ReconnectingPDOStatement
    56. {
    57. private $_stmt = null;
    58.  
    59. public function __construct($stmt) {
    60. $this->_stmt = $stmt;
    61. }
    62.  
    63. public function __call($name, array $arguments) {
    64. $result = false;
    65. try {
    66. $result = call_user_func_array(array($this->_stmt, $name), $arguments);
    67. } catch (PDOException $e) {
    68. // var_dump($e);
    69. }
    70. return $result;
    71. }
    72. }

你可能感兴趣的:(支持自动重连接的PHP PDO类完善)