easyswoole mysql-pool连接池empty null的问题

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 计算机是由许多零件组装而成,比如CPU、内存、硬盘等等。 当我们进行网络连接、请求的时候,就需要在不同组件中传递和返回各种信号、数据 比如在CPU、内存、网卡中,数据的传递,请求,获取。 如果在短时间内进行一万次mysql的连接,就需要在这个往返过程循环,在路上浪费了很多时间、性能消耗。 如果我们先把连接连接好,并且放在连接池中,程序中需要使用就从池中获取,执行操作。

问题由来


在easyswoole的群里,每天都需要回答各种各样的问题,其中不乏一些问题反复被小白们问起,比如今天的这个主题:连接池取出empty 为null导致的问题 本文会简单引申出什么是连接池连接池数量如何设置连接池的优点等问题。


什么是连接池


连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用。


简单来说,就是创建一个容器,并且把资源提前准备好放在里面,比如我们常用的redis连接、mysql连接。


连接池的优点


计算机是由许多零件组装而成,比如CPU、内存、硬盘等等。 当我们进行网络连接、请求的时候,就需要在不同组件中传递和返回各种信号、数据 比如在CPU、内存、网卡中,数据的传递,请求,获取。 如果在短时间内进行一万次mysql的连接,就需要在这个往返过程循环,在路上浪费了很多时间、性能消耗。 如果我们先把连接连接好,并且放在连接池中,程序中需要使用就从池中获取,执行操作。 就省去了反复创建连接、断开连接的操作。 可以减少I/O操作,提高资源利用率。


连接池数量如何设置


那么一个池需要设置多少数量比较合适呢?是不是越多越好? 在此之前,我们需要先了解计算机的进程原理,一个CPU伪造出多进程并行的假象。(我们电脑能一边听歌一边聊天等等) 我们把一个池中的连接看成一个进程(在实际中也可能是线程级别),如果设置过多,就会在系统中创建太多进程,切换进程上下文就会比较慢了。 一般我们把连接池数量设置为CPU的1~2倍即可(非固定)


easyswoole中为什么会pool empty


这个问题有好几个可能性。


  • 连接信息错误,导致一个资源都没有
  • 程序有问题,把资源拿出去,没有归还到池内,后续就拿到空了
  • 并发高,池的数量少,需要检查资源占用率,如果占用率没问题,则提高池内的数量


连接信息错误


如果我们的mysql配置信息错误,在easyswoole框架启动之后,就会去初始化连接池。 此时一直连接失败,也就没有产生资源,也没有将资源放在池内 当你在后续程序获取池内资源的时候。自然就报了空池的错误提示。


程序问题


先来一个连接池的伪代码


<?php
class Pool{
    public static function getIn(){
        // 单例模式
    }
    /**
     * 初始化
     */
    public function init()
    {
        // pool准备好就填充指定的资源 比如10个连接
        $this->pool = $array;
    }
    public function get(){
        return array_pop($this->pool);
    }   
    public function push($obj)
    {
        $this->pool[] = $obj;
    }
}


如果我们的程序有这样子的使用场景


<?php
    $db = Pool::getIn()->get();
    $res = $db->query('sql语句');


然后没有进行push 归还操作,那么池内资源一旦拿完,就没有资源可用了。 在easyswoole框架中,有提供以下方法获取资源(以mysql-pool为例)


$db = MysqlPool::defer();
$db->rawQuery('select version()');
$data = MysqlPool::invoker(function (MysqlConnection $db){
    return $db->rawQuery('select version()');
});
$db = PoolManager::getInstance()->getPool(MysqlPool::class)->getObj();
$data = $db->get('test');
//使用完毕需要回收
PoolManager::getInstance()->getPool(MysqlPool::class)->recycleObj($db);


defer方法将会在本次请求协程退出的时候自动回收 invoker是闭包函数方式 一次运行完马上自动回收 get方式 就是我们伪代码的方式 需要自己回收 使用这种方式就需要特别注意啦~!!!


两种自动回收方式怎么选择 请接着往下看!


并发高 资源占用率


上面说到两种自动回收资源的方式,defer和invoker 首先我们来看一个点,defer是在协程退出时自动回收,正常来说,在一个请求到达的时候,swoole会自动创建一个协程给他,比如我们一个http api的请求,就需要整个api跑完,这个协程才会退出 (相当于我们传统fpm php中 一个脚本全部执行完) 这个时候问题来了,如果我们的业务是这样子的


<?php
    $db = MysqlPool::defer();
    $db->rawQuery('select version()');
    // 执行好mysql了  做其他任务
    // 耗时1.5s 完成其他


实际上使用到mysql资源的可能只有0.1s不到,但是其他运算占用了脚本大量执行时间,要等全部执行完,协程退出了,资源才会回收,这个时候就比较浪费资源的利用率了。占用率比较低。 如果整个程序都是这样子的场景。那么一个池内有十几二十个连接是完全不够用的。这也是大部分新人为什么在pool里设置100个连接的理由。。。。。我真的佩服哦!!! 如果可以的话 ,我们推荐使用invoker 执行一条 马上回收资源 此时要注意一个点,如果程序有比较多执行语句,要么在一个invoker里执行,要么合理使用invoker 不然就会把性能消耗转移到不断get recycle上了 如果以上排查都没问题,并且确认你的用户量比较多,并发高,就可以适当提高pool的number

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3月前
|
机器学习/深度学习 SQL 关系型数据库
【MySQL进阶之路丨第十一篇】一文带你精通MySQL NULL值处理、正则表达式
【MySQL进阶之路丨第十一篇】一文带你精通MySQL NULL值处理、正则表达式
36 0
|
3月前
|
SQL 关系型数据库 MySQL
总结 vue3 的一些知识点:MySQL NULL 值处理
总结 vue3 的一些知识点:MySQL NULL 值处理
|
6天前
|
SQL 关系型数据库 MySQL
Spring_jdbc数据连接池(mysql实现增、删、改、查)
Spring_jdbc数据连接池(mysql实现增、删、改、查)
15 0
|
2月前
|
SQL 关系型数据库 MySQL
python在mysql中插入或者更新null空值
这段代码是Python操作MySQL数据库的示例。它执行SQL查询从表`a_kuakao_school`中选取`id`,`university_id`和`grade`,当`university_id`大于0时按升序排列。然后遍历结果,根据`row[4]`的值决定`grade`是否为`NULL`。若不为空,`grade`被格式化为字符串;否则,设为`NULL`。接着构造UPDATE语句更新`university`表中对应`id`的`grade`值,并提交事务。重要的是,字符串`NULL`不应加引号,否则更新会失败。
22 2
|
1月前
|
关系型数据库 MySQL
mysql中判断NULL和空字符串
mysql中判断NULL和空字符串
9 0
|
2月前
|
移动开发 关系型数据库 MySQL
mysql删除为NULL或者空字符串‘‘或者‘null’的或者删除空格的
mysql删除为NULL或者空字符串‘‘或者‘null’的或者删除空格的
12 1
|
2月前
|
数据可视化 关系型数据库 MySQL
PolarDB常见问题之无法创建mysql的连接池如何解决
PolarDB是阿里云推出的下一代关系型数据库,具有高性能、高可用性和弹性伸缩能力,适用于大规模数据处理场景。本汇总囊括了PolarDB使用中用户可能遭遇的一系列常见问题及解答,旨在为数据库管理员和开发者提供全面的问题指导,确保数据库平稳运行和优化使用体验。
|
2月前
|
SQL 关系型数据库 MySQL
总结 vue3 的一些知识点:MySQL NULL 值处理
总结 vue3 的一些知识点:MySQL NULL 值处理
|
3月前
|
SQL 关系型数据库 MySQL
面试官:MySQL中<>能过滤到null值吗?
引言 了不起最近在定位一个bug的时候,发现本应该过滤出15355条数据的,但其实只过滤出了12891条数据。 然后我就把sql找出来,根据debug调试的参数取到,一执行,果然结果只有12891。 代码大概就像这样的: List<OrderAllotPackage> orderAllotPackageList = orderAllotPackageService.lambdaQuery() .ne(OrderAllotPackage::getTrackingNumber, "") .ne(OrderAllo
38 0
|
3月前
|
存储 关系型数据库 MySQL
如何修改MySQL列允许Null?
如何修改MySQL列允许Null?
49 1
如何修改MySQL列允许Null?