php实现mysql连接池效果实现代码


Posted in PHP onJanuary 25, 2018

循环从mysql连接池中获取连接,不需要重复创建新的连接。

参考配置修改:可以参考下面的文章

防止访问量过大,把连接数占满了

<?php

/**
 * @author xuleyan
 * @title mysql类
 */

class DbHelper{
  //连接池
  private $_pools = [];

  //连接池大小
  const POOLSIZE = 5;

  const USERNAME = "root";
  const PASSWORD = "root";
  const HOST = "127.0.0.1";
  const DB = "test";

  public function __construct()  
  {
    $db = self::DB;
    $username = self::USERNAME;
    $password = self::PASSWORD;
    $host = self::HOST;

    //持久化连接
    $presistent = array(PDO::ATTR_PERSISTENT => true);

    for ($i=0; $i < self::POOLSIZE; $i++) { 
      $connection = new PDO("mysql:dbname=$db;host=$host", $username, $password);
      // sleep(3);
      array_push($this->_pools, $connection);
    }
  }

  //从数据库连接池中获取一个数据库链接资源
  public function getConnection()
  {
    echo 'get' . count($this->_pools) . "<br>";
    if (count($this->_pools) > 0) {
      $one = array_pop($this->_pools);
      echo 'getAfter' . count($this->_pools) . "<br>";
      return $one;
    } else {
      throw new ErrorException ( "<mark>数据库连接池中已无链接资源,请稍后重试!</mark>" );
    }
  }

  //将用完的数据库链接资源放回到数据库连接池
  public function release($conn)
  {
    echo 'release' . count($this->_pools) . "<br>";
    if (count($this->_pools) >= self::POOLSIZE) {
      throw new ErrorException ( "<mark>数据库连接池已满!</mark>" );
    } else {
      array_push($this->_pools, $conn);
      // $conn = null;
      echo 'releaseAfter' . count($this->_pools) . "<br>";
    }
  }

  public function query($sql)
  {
    try {
      $conn = $this->getConnection();
      $res = $conn->query($sql);
      $this->release($conn);
      return $res;
    } catch (ErrorException $e) {
      print 'error:' . $e->getMessage();
      die;
    }
  }

  public function queryAll($sql)
  {
    try {
      $conn = $this->getConnection();
      $sth = $conn->prepare($sql);
      $sth->execute();
      $result = $sth->fetchAll();
      return $result;
    } catch (PDOException $e) {
      print 'error:' . $e->getMessage();
      die;
    }
  }
}

在另外的文件这样调用

<?php 

require_once 'db.php';
$sql = 'select * from user';

$dbhelper = new DbHelper;
for ($i=0; $i < 10; $i++) { 
  $res = $dbhelper->query($sql);
  // var_dump($res) . PHP_EOL;
}

ThinkPHP连接MySQL的连接池使用方法

因为一个小bug,导致项目在某个晚上向mysql发送了大量的连接请求,同时mysql服务器的dns出现问题,导致反解超时。最后活活的把mysql服务器拖挂了。

最后bug修复了,并研究了一下增加 mysql连接池的办法。

这两天搜了一下,发现ThinkPHP文档里没有连接池的相关文档。所以自己研究了下代码。

首先: PHP常用的mysql扩展库有三种 : mysql, mysqli, pdo_mysql.

* mysqli 是不支持连接池的。
* pdo_mysql 支持,但是,thinkPHP的pdo扩展不支持mysql,仅支持:'MSSQL','ORACLE','Ibase','OCI' . ( 见 Pdo.class.php 的第59行)

* mysql 支持,通过方法:mysql_pconnect . (具体参数可以看php官方文档)

1 使ThinkPHP启用 长连接的方式是:

class BaseMysql extends Model {
  protected $connection = array(
    'db_type' => 'mysql',
    'db_user' => '***',
    'db_pwd' => '*******',
    'db_host' => '*******',
    'db_port' => '3306',
    'db_name' => 'custom',
    'db_params' => array('persist' => true),
  );
}

如果你认为,配置这个就万事大吉了,那就大错特错了。

2 mysql -> my.cnf修改配置:
[mysqld]

interactive_timeout =60 // 交互连接(mysql-client)的过期时间。
wait_timeout =30 // 长连接的过期时间时间。 这个一定要改啊!默认是8个小时。 如果请求量大点,很快连接数就占满了。
max_connections = 100 //最大连接数,可以认为是连接池的大小

3 php.ini 修改:
[MySql]
mysql.allow_persistent = On
mysql.max_persistent = 99 // 要小于mysql配置的最大连接数
mysql.max_links = 99

4 webserver如果是apache ,需要启用keep-alive。 否则,一旦请求退出,长连接将无法再重用。
webserver 是nginx的情况:
pm = dynamic // 默认启动一些子进程,用于处理http请求。
pm.max_children // 最大的子进程数。 这个配置要小于 mysql 的max_connections。

5 如果发现还是不能用,请检查操作系统的keepalive 是否启用。

综述:

需要 keep-alive 和 数据库长连接同时启用,否则长连接回白白的占用mysql的连接数资源,而无法重用。
对于 nginx + php-fpm 的情况,其实是保持了 php-fpm 子进程与mysql的长连接。 前端的http请求被分配给哪个 php-fpm子进程,该子进程就重用自己与mysql 的长连接。

上述是一整天的研究结果,不完备的地方,请大家指出,在此先行谢过!

PHP 相关文章推荐
php5 pdo新改动加载注意事项
Sep 11 PHP
PHP手机号码归属地查询代码(API接口/mysql)
Sep 04 PHP
Thinkphp模板中使用自定义函数的方法
Sep 23 PHP
解析PHP中常见的mongodb查询操作
Jun 20 PHP
关于PHPDocument 代码注释规范的总结
Jun 25 PHP
php中生成随机密码的自定义函数代码
Oct 21 PHP
非常好用的Zend Framework分页类
Jun 25 PHP
php获取URL中带#号等特殊符号参数的解决方法
Sep 02 PHP
PHP+JS三级菜单联动菜单实现方法
Feb 24 PHP
php 替换文章中的图片路径,下载图片到本地服务器的方法
Feb 06 PHP
PHP getDocNamespaces()函数讲解
Feb 03 PHP
Laravel 读取 config 下的数据方法
Oct 13 PHP
php使用imagecopymerge()函数创建半透明水印
Jan 25 #PHP
CI框架(CodeIgniter)操作redis的方法详解
Jan 25 #PHP
PHP开发之用微信远程遥控服务器
Jan 25 #PHP
php实现统计二进制中1的个数算法示例
Jan 23 #PHP
基于php中echo用逗号和用点号的区别详解
Jan 23 #PHP
php数据结构之顺序链表与链式线性表示例
Jan 22 #PHP
通过源码解析Laravel的依赖注入
Jan 22 #PHP
You might like
PHP调用Twitter的RSS的实现代码
2010/03/10 PHP
php生成Android客户端扫描可登录的二维码
2016/05/13 PHP
PHP身份证校验码计算方法
2016/08/10 PHP
PHP基于SPL实现的迭代器模式示例
2018/04/22 PHP
ext 列表页面关于多行查询的办法
2010/03/25 Javascript
jQuery 表格工具集
2010/04/25 Javascript
javascript 循环读取JSON数据的代码
2010/07/17 Javascript
jquery实现文本框鼠标右击无效以及不能输入的代码
2010/11/05 Javascript
基于jquery的代码显示区域自动拉长效果
2011/12/07 Javascript
JavaScript之自定义类型
2012/05/04 Javascript
jQuery javaScript捕获回车事件(示例代码)
2013/11/07 Javascript
Javascript中的异步编程规范Promises/A详细介绍
2014/06/06 Javascript
jQuery判断一个元素是否可见的方法
2015/06/05 Javascript
学习javascript面向对象 实例讲解面向对象选项卡
2016/01/04 Javascript
原生javascript+css3编写的3D魔方动画旋扭特效
2016/03/14 Javascript
解决JS组件bootstrap table分页实现过程中遇到的问题
2016/04/21 Javascript
js实现select选择框效果及美化
2016/08/19 Javascript
Angular下H5上传图片的方法(可多张上传)
2017/01/09 Javascript
Vue2单一事件管理组件通信
2017/05/09 Javascript
第一次记录Bootstrap table学习笔记(1)
2017/05/18 Javascript
vue element-ui table组件动态生成表头和数据并修改单元格格式 父子组件通信
2019/08/15 Javascript
基于JavaScript实现轮播图效果
2021/01/02 Javascript
python抓取某汽车网数据解析html存入excel示例
2013/12/04 Python
Web服务器框架 Tornado简介
2014/07/16 Python
Python中的多重装饰器
2015/04/11 Python
详解python3中socket套接字的编码问题解决
2017/07/01 Python
Django 权限认证(根据不同的用户,设置不同的显示和访问权限)
2019/07/24 Python
美国一家主打母婴用品的团购网站:zulily
2017/09/19 全球购物
7 For All Mankind官网:美国加州洛杉矶的高级牛仔服装品牌
2018/12/20 全球购物
彪马荷兰官网:PUMA荷兰
2019/05/08 全球购物
工艺工程师工作职责
2013/11/23 职场文书
邮政员工辞职信
2014/01/16 职场文书
医学生职业生涯规划书范文
2014/03/13 职场文书
社区义诊通知
2015/04/24 职场文书
初中毕业感言300字
2015/07/31 职场文书
Python可变与不可变数据和深拷贝与浅拷贝
2022/04/06 Python