性能测试 —— 数据库的连接池和主从同步和分表分区
一、数据库的调优(库层面)
1、数据库连接池
1、介绍:数据库连接池(Database Connection Pool)是一种用于管理数据库连接的技术,它通过预先创建并维护一组数据库连接来提高应用程序的性能和可扩展性。
2、创建、管理、关闭 数据库连接池
-
创建:般在系统初始化时,连接池会根据系统配置建立,并在池中创建了几个连接对象,以便使用时能从连接池中获取。连接池中的连接不能随意创建和关闭,这样避免了连接随意建立和关闭造成的系统开销。
-
管理:是连接池机制的核心,连接池内连接的分配和释放对系统的性能有很大的影响。其管理策略如下:
-
客户请求数据库连接时,首先查看连接池中是否有空闲连接
* 如果存在空闲连接,则将连接分配给客户使用;
* 如果没有空闲连接,则查看当前所开的连接数是否已经达到最大连接数,
- 如果没达到就重新创建一个连接给请求的客户;
- 如果达到就按设定的最大等待时间进行等待,如果超出最大等待时间,则抛出异常给客户
-
当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就从连接池中删除该连接,否则保留为其他客户服务。
-
该策略保证了数据库连接的有效复用,避免频繁的建立、释放连接所带来的系统资源开销。
-
-
关闭:当应用程序退出时,关闭连接池中所有的连接,释放连接池相关的资源,该过程正好与创建相反。
2、线程池的特点
1、有无数据库连接池的对比
- 有连接池
一个请求建立了连接完成查询后不会释放掉,而是进入连接池保存;比如连接池就让其存活5条连接,当一个请求过来了,先去连接池里查看一下是否有空闲的连接,有的话就直接复用这个连接然后去进行查询操作;用完后也不释放,直接放回到连接池里作为空闲的状态等待其他的请求来占用。 这样就避免了频繁的建立和释放连接带来的性能损耗。
- 无连接池
一个数据的查询请求需要建立一个数据库的连接,连接建立成功后才会执行查询操作并返回查询结果后释放这个连接; 这个不断地建立连接和释放连接的过程,对数据库的性能损耗就比较大,所以就引入了连接池的概念
总结:这样之后数据库的连接都是通过连接池进行管理的,对数据库的连接数量在入口处就做了一个限制,不是用户来控制其大小的,而是由系统自己来控制的,这样就起到一个对后端数据库服务器的很好的保护作用。所以基本上连接后端数据库服务都是通过连接池控制的。
2、数据库建立连接的过程
2、不使用数据库连接池的步骤 VS 使用连接池的步骤:
- 不使用数据库连接池
1、 TCP建立连接的三次握手
2、MySQL认证的三次握手
3、真正的SQL执行
4、MySQL的关闭
5、TCP的四次握手关闭
可以看到这是开销比较大的
- 使用数据库连接池
- 第一次访问的时候需要建立连接,但是之后的访问,均会复用之前创建的连接,直接执行SQL语句
3、不使用连接池 VS 使用连接池的优缺点
- 不使用数据库连接池的缺点:
- 网络IO较多
- 数据库的负载较高
- 响应时间较长及QPS较低
- 应用频繁的创建连接和关闭连接,导致临时对象较多,GC频繁
- 使用数据库连接池的优点:
- 减少了网络开销
- 系统的性能会有一个实质的提升:包括降低RT,提高QPS和TPS,降低负载等
- 减少了频繁的创建连接和关闭连接的开销,减少了内存的消耗
3、连接池的主要参数
使用连接池时,要配置以下常见的参数 :
- 初试连接数(initialSize):连接池启动时创建的初始化连接数量
- 最大连接数(maxActive):连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中
- 最大空闲连接数(maxIdle):连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负数表示不限制最大空闲时间
- 最小空闲连接数(minIdle):连接池中最小的空闲的连接数,低于这个数量会创建新的连接。该参数越接近maxIdle,性能越好,因为连接的创建和销毁,都是需要消耗资源的;但是不能太大。
- maxWait :最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间,超过该时间限制会抛出异常,如果设置-1表示无限等待
4、MySQL连接池的参数查看
1、Mysql数据库的配置参数获取,可以通过执行sql: “show variables”:
-
连接池相关的参数主要包括max_connections、max_user_connections、wait_timeout和interactive_timeout。
-
max_connections表示MySQL服务器所能支持的最大并发连接数
-
max_user_connections表示每个用户能够同时建立的最大连接数
-
wait_timeout表示连接在空闲状态多长时间后被自动关闭
-
interactive_timeout表示连接在非空闲状态多长时间后被自动关闭
-
2、其中一个参数 max_connections就是MySQL的最大连接数,是我们最需要关注的:
- 可以过'show variables like "%conn%"'通配符查看当前状态的连接数量的大小;
- show global status like 'max_used_connections'; 查看目前使用的连接数量的大小;
- 一般会使用默认的连接数做性能测试,如果出现了问题 再调高验证。
-
如果服务器的并发连接请求量比较大,建议调高此值以增加并行连接数量,当然这建立在机器能支撑的情况下,因为连接数越多就会开销越多的内存,所以要适当调整该值,不能盲目提高设值。
3、数据库连接不够用的错误提示(在压测的返回结果中查看)
- 出现5xx系列的错误
- mysql:Error preloading the connection pool
- Cannot create PoolableConnectionFactory
- ERROR 1040: Too many connections
5、实战演练
1、设置最大连接数为10,使用命令:set global max_connections=10。是临时调整的,如果数据付服务重启那么会恢复默认的数值
2、使用jmeter发起压测
3、针对这个性能场景进行分析
1、阶梯压测的时候,前面不报错,但是TPS没有随着并发用户增加而增加,而且此时CPU很高
2、结合top命令查看资源情况:
-
CPU的表现: cpu占用率 si会很高,软中断很高,说明再被迫等待中断了操作;
-
结合上一步,如果等待时间很长,但不报错,也会导致TPS上不去【没有随着并发用户数增加而增加TPS,甚至会出现下降】,然后不报错。这个也有可能是连接池不够的问题引起的
3、结合vmstat命令查看
- r 很多,等待运行的进程数,高 r 值可能意味着系统正忙于处理其他任务,无法及时响应新的请求。就是在等待连接池释放。
- 并且cs 和 in 也有比较多的数据:说明中断和上下文切换有发生
此时再继续增加用户数,那么就会报错了: too many connection,那么再查看一下数据库的最大连接数,如下,可以看出远大于10了,因此会报错
4、针对这个性能场景的优化提升:
1、数据库配置连接数不够,我们就需要适当的调整数据库连接池的大小: 改大最大连接数
- 修改方法: 通过SQL修改max_connections值 set global max_connections=256;
- 【最好根据项目 咨询开发+ DBA,并且多次压测的验证 取一个恰当的值: 不报错连接池,内存不会消耗太多】
- 注意:这种是临时修改, 数据库重启后就会失效,修改配置文件里的配置并重启服务器可以永久生效:
- docker cp centos7_mysql57:/etc/mysql/mysql.conf.d/mysqld.cnf $PWD #从容器里拉取到本地
- vi修改这个文件: max_connections = 256
- docker cp mysqld.cnf centos7_mysql57:/etc/mysql/mysql.conf.d/mysqld.cnf #从本地推送到容器里替换原来的配
二、数据库的工作原理