数据库连接瓶颈问题的思考

数据库连接瓶颈问题的思考

背景:客户提出如果客户端总的连接数如果超过数据库服务端的最大连接数,连接会不会成为瓶颈?

Client连接池大小设置

参考来自Oracle 性能小组 : https://www.youtube.com/watch?v=xNDnVOCdvQ0&list=PLDacGuMCXBJoXiEBkULq2mn-VwwxEPK_M&index=2&t=0s
视频中对 Oracle 数据库进行了压力测试,模拟 9600 个并发线程来操作数据库,每两次数据库操作之间 sleep 550ms,开始设置的线程池大小为 2048。
当数据库连接池的大小为 2048 性能测试结果:
每个请求要在连接池队列里等待 33ms,获得连接之后,执行SQL需要耗时77ms, CPU 消耗维持在 95% 左右;
当数据库连接池的大小为1024 性能测试结果:
获取连接等待时长基本不变,但是 SQL 的执行耗时降低
当数据库连接池的大小为 96 性能测试结果:
每个请求在连接池队列中的平均等待时间为 1ms, SQL 执行耗时为 2ms.
结论:连接池数量并非越大越好

数据库瓶颈的三个因素:CPU、磁盘IO、网络IO

磁盘IO越慢,意味着单次查询任务需要的时间越长,线程池数量增加;网络IO越慢,同样拉长单次查询时间,线程数量同样增加

Alt text

上图是 PostgreSQL 的基准性能测试数据,从图中我们可以看到,TPS 在连接数达到 50 时开始变缓。回过头来想下,在上面 Oracle 的性能测试视频中,测试人员们将连接数从 2048 降到了 96,实际上 96 还是太高了,除非你的服务器 CPU 核心数有 16 或 32。

参考连接数计算公式,有PostgreSQL提供:连接数 = ((核心数 * 2) + 有效磁盘数)

数据库server连接设置

数据库server一般是需要设定最大连接数,当连接资源耗尽,客户端将不再能跟数据库建立连接。mysql会抛出 has already more than ‘max_user_connections’ active connections 的错误,这时需要调大数据库的max_user_connections或者将请求放入等待队列。
应用程序建立连接:网络连接三次握手、用户登录认证、用户读写鉴权

mysql允许在运行时修改最大连接数,不重启服务;oracle修改最大连接数必须重启服务;sybase允许运行时修改最大连接数,但需要充分考虑磁盘、内存情况。

连接不足时的临时处理方案:

  1. 通过查看当前占着连接的线程,处理掉一些不需要保持连接的空闲连接(多个应用程序连接同一数据库,牺牲某些应用程序以保障核心程序的运行)
  2. 减少连接过程的损耗,如使用-skip-grant-tables参数跳过权限验证阶段

建议:上文所述,对于每个数据库客户端的基本连接池数量与最大连接池数量,在上生产环境服务器的时候可以根据服务器的配置明确计算出来,对于一个数据库server的最大连接数量也是可以确定的。通过提前计算出最大连接数量,尽量不要随意增加数据库客户端

长效解决方案

  1. 引入缓存层,增加缓存命中率
  2. sql优化,降低sql执行时间
  3. 增加硬件配置:提升服务器性能,降低网络开销
  4. 根据业务场景,如果sql操作insert、update、delete的平均时间远大于select的时间,则可以配置读连接池与写连接池,并专门调整每个连接池的大小,系统吞吐量会有较大幅度的提升
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章