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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值