关于数据库连接池大小 · brettwooldridge/HikariCP Wiki · GitHub

标签: | 发表时间:2020-01-29 16:48 | 作者:
出处:https://github.com

关于连接池大小

Brett Wooldridge编辑了此页面 on 8 Jan 2017 ·  29个修订

开发人员经常会错误地配置连接池。在配置池时,需要理解一些原则,对于某些原则可能是违反直觉的。

10,000个同时前端用户

想象一下,您有一个网站,尽管它可能不是Facebook规模,但仍然经常有10,000个用户同时发出数据库请求-每秒约有20,000个事务。您的连接池应该有多大?您可能会惊讶,问题不是 多大,而是 多小!

观看Oracle真实世界性能小组的这段简短视频,以进行令人大开眼界的演示(约10分钟):

{Spoiler Alert},如果您没有观看视频。哦,加油!观看,然后回到这里。

您可以从视频中看到,在不进行任何其他更改的情况下,仅减小连接池大小就可以将应用程序的响应时间从约100ms减少到约2ms-改进了50倍以上。

但为什么?

我们似乎最近在计算的其他部分已经了解到,少即是多。为什么只有4个线程的 Nginx Web服务器可以大大 胜过具有100个进程的 Apache Web服务器?如果回想一下计算机科学101,这不是很明显吗?

即使是只有一个CPU内核的计算机也可以“同时”支持数十个或数百个线程。但是我们所有人[应该]都知道,这只是 时间片的神奇之处,而不仅仅是操作系统的一个把戏。实际上,那个单核一次只能执行 一个线程。然后OS切换上下文,该内核执行另一个线程的代码,依此类推。计算的基本定律是,给定单个CPU资源,按时间顺序执行A和B  总是比“同时” 执行A和B更快。一旦线程数超过CPU内核数,添加更多线程就会变慢,而不是更快。

几乎是真的...

有限的资源

它不像上面说的那么简单,但是很接近。还有其他一些因素在起作用。当我们查看数据库的主要瓶颈时,它们可以概括为三个基本类别: CPUDiskNetwork。我们可以在其中添加 内存,但是与 磁盘网络相比,带宽存在几个数量级的差异。

如果我们忽略“  磁盘网络”,那将很简单。在具有8个计算核心的服务器上,将连接数设置为8将提供最佳性能,并且由于上下文切换的开销,超出此限制的任何内容都将开始变慢。但是我们不能忽略 磁盘网络。数据库通常将数据存储在 磁盘上传统上由旋转的金属板组成,金属板带有安装在步进电机驱动臂上的读/写头。读/写头一次只能位于一个位置(一次查询的读/写数据),并且必须“搜寻”到新的位置才能为另一次查询读/写数据。因此,存在寻道时间成本以及旋转成本,由此磁盘必须等待数据在读/写盘上“再次出现”。缓存在这里当然有帮助,但是原理仍然适用。

在这段时间内(“ I / O等待”),连接/查询/线程仅被“阻塞”以等待磁盘。正是在这段时间内,OS可以通过为另一个线程执行更多代码来更好地利用CPU资源。因此,由于线程在I / O上被阻塞,因此通过使连接/线程的数量大于物理计算内核的数量,我们实际上可以完成更多的工作。

还有多少?我们将会看到。还有多少个问题也取决于 磁盘子系统,因为较新的SSD驱动器没有“寻找时间”的成本或需要处理的旋转因素。不要被欺骗,“ SSD  更快,因此我可以拥有 更多线程”。那就是向后180度。更快,没有寻道,没有旋转延迟意味着 更少的阻塞,因此 更少的线程(更接近内核数)将比更多的线程有更好的性能。  只有在阻塞为执行创造机会时,更多的线程才能更好地执行。

网络类似于 磁盘。当发送/接收缓冲区填满并停顿时,通过以太网接口通过有线方式写数据也会引入阻塞。10千兆位接口的停滞速度将小于千兆以太网,而千兆以太网将停滞于100兆位以下。但是就资源阻塞而言,网络排名第三。有些人经常从计算中忽略它。

这是另一个打破文本墙的图表。

您可以在上述PostgreSQL基准测试中看到,TPS速率在大约50个连接处开始趋于平稳。在上面的Oracle视频中,他们显示连接从2048个下降到96个。我们可以说,即使96个也可能太高了,除非您使用的是16或32核处理器。

公式

PostgreSQL项目提供了以下公式作为起点,但是我们认为该公式将在很大程度上适用于数据库。您应该测试您的应用程序,即模拟预期的负载,并 此起点 附近尝试不同的池设置:

连接数=((core_count * 2)+ Effective_spindle_count)
      A formula which has held up pretty well across a lot of benchmarks for years is
that for optimal throughput the number of active connections should be somewhere
near ((core_count * 2) + effective_spindle_count). Core count should not include
HT threads, even if hyperthreading is enabled. Effective spindle count is zero if
the active data set is fully cached, and approaches the actual number of spindles
as the cache hit rate falls. ... There hasn't been any analysis so far regarding
how well the formula works with SSDs.

猜猜那是什么意思?您的带有一个硬盘的4核i7小型服务器应该正在运行以下连接池:  9 = ((4 * 2) + 1)。将其 10称为一个不错的整数。看起来低吗?试试看,我们打赌您可以轻松地处理3000个前端用户,在这种设置下以6000 TPS的速度运行简单查询。如果运行负载测试,则可能会发现,随着您将连接池推到更远的位置 10(在给定的硬件上),TPS速率开始下降,前端响应时间开始攀升。

公理:您需要一个小的池,池中充满等待连接的线程。

如果您有10,000个前端用户,那么拥有10,000个连接池将使您精神错乱。1000仍然很恐怖。甚至有100个连接,过度杀伤力。您需要一个最多只有几十个连接的小型池,并且希望池中等待连接的其余应用程序线程被阻塞。如果对池进行了适当的调整,则将其设置为数据库能够同时处理的查询数量的极限,这几乎不超过如上所述的(CPU内核* 2)。

我们永远不会停止对我们遇到的内部Web应用程序的惊奇,几十个前端用户执行定期活动,并且连接池包含100个连接。不要过度配置数据库。


“锁池”

对于获得许多联系的单个演员,“池锁定”的前景有所提高。这在很大程度上是应用程序级的问题。是的,增加池的大小可以减轻这些情况下的锁定,但是我们敦促您在扩大池之前先检查一下在应用程序级别可以执行的操作。

为了避免死锁,计算池大小是一个相当简单的资源分配公式:

    池大小= T n x(C m -1)+ 1

其中 T n是最大线程数,而 C m是单个线程 同时保持的最大 连接数。

例如,设想三个线程( T n = 3),每个线程都需要四个连接来执行某些任务( C m = 4)。确保永远不会发生死锁所需的池大小为:

    池大小= 3 x(4-1)+ 1 = 10

另一个示例,您最多有八个线程( T n = 8),每个线程需要三个连接才能执行某些任务( C m = 3)。确保永远不会发生死锁所需的池大小为:

    池大小= 8 x(3-1)+ 1 = 17

👉这不一定是 最佳的池大小,但 最低要求,以避免死锁。

some在某些环境中,使用JTA(Java事务管理器)可以通过将相同的Connection从返回 getConnection()到当前事务中已经拥有Connection的线程中来,大大减少所需的连接数。


注意事项

池大小调整最终非常特定于部署。

例如,混合了长时间运行的事务和非常短的事务的系统通常是最难于使用任何连接池进行调整的系统。在那种情况下,创建两个池实例可以很好地工作(例如,一个用于长时间运行的作业,另一个用于“实时”查询)。

在主要运行长时间事务的系统中,通常对所需连接数存在“外部”限制-例如作业执行队列仅允许一定数量的作业一次运行。在这些情况下,作业队列大小应为“正确大小”以匹配池(而不是相反)。

相关 [数据库 大小 brettwooldridge] 推荐:

关于数据库连接池大小 · brettwooldridge/HikariCP Wiki · GitHub

- -
Brett Wooldridge编辑了此页面 on 8 Jan 2017 ·  29个修订. 开发人员经常会错误地配置连接池. 在配置池时,需要理解一些原则,对于某些原则可能是违反直觉的. 10,000个同时前端用户. 想象一下,您有一个网站,尽管它可能不是Facebook规模,但仍然经常有10,000个用户同时发出数据库请求-每秒约有20,000个事务.

数据库sharding

- - 数据库 - ITeye博客
当团队决定自行实现sharding的时候,DAO层可能是嵌入sharding逻辑的首选位置,因为在这个层面上,每一个DAO的方法都明确地知道需要访问的数据表以及查询参数,借助这些信息可以直接定位到目标shard上,而不必像框架那样需要对SQL进行解析然后再依据配置的规则进行路由. 另一个优势是不会受ORM框架的制约.

数据库索引

- - CSDN博客推荐文章
索引是由用户创建的、能够被修改和删除的、实际存储于数据库中的物理存在;创建索引的目的是使用户能够从整体内容直接查找到某个特定部分的内容. 一般来说,索引能够提高查询,但是会增加额外的空间消耗,并且降低删除、插入和修改速度. 1.聚集索引:表数据按照索引的顺序来存储的. 2.非聚集索引:表数据存储顺序与索引顺序无关.

数据库事务

- - 数据库 - ITeye博客
事务传播发生在类似以下情形:. 假设methodB的配置是:. 如果methodA在事务里,那么methodB也在这个事务中运行. 如果methodA不在事务里,那么methodB重新建立一个事务运行. 如果methodA在事务里,那么methodB也在这个事务中运行. 如果methodA不在是事务里,那么methodB在非事务中运行.

数据库优化

- - 数据库 - ITeye博客
程序运行效率,优化应用程序,在SP编写过程中应该注意以下几点: . a) SQL的使用规范: .   i.尽量避免大事务操作,慎用holdlock子句,提高系统并发能力.   ii.尽量避免反复访问同一张或几张表,尤其是数据量较大的表,可以考虑先根据条件提取数据到临时表中,然后再做连接.   iii.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该改写;如果使用了游标,就要尽量避免在游标循环中再进行表连接的操作.

数据库调优

- - 数据库 - ITeye博客
1、1、调整数据结构的设计. 这一部分在开发信息系统之前完成,程序员需要考虑是否使用ORACLE数据库的分区功能,对于经常访问的数据库表是否需要建立索引等. 这一部分也是在开发信息系统之前完成,程序员在这一步需要考虑应用程序使用什么样的体系结构,是使用传统的Client/Server两层体系结构,还是使用Browser/Web/Database的三层体系结构.

MySQL数据库的修复

- Xin - 博客园-首页原创精华区
找到mysql的安装目录的bin/myisamchk工具,在命令行中输入:. 然后myisamchk 工具会帮助你恢复数据表的索引. 好象也不用重新启动mysql,问题就解决了. 当你试图修复一个被破坏的表的问题时,有三种修复类型. 如果你得到一个错误信息指出一个临时文件不能建立,删除信息所指出的文件并再试一次--这通常是上一次修复操作遗留下来的.

Oracle 发布 NoSQL 数据库

- 冷月 - 博客园新闻频道
  Oracle 作为全球最大的关系型数据库提供商,在其产品链条中,也加入了 NoSQL 数据库这一环,而且这个新的数据库名字很霸气,就叫 NoSQL Database,想起了当年新浪微博更换 weibo.com 域名之时的一个笑话:. 原来有三家人做面包,张三家的面包叫三张牌面包,李四家的牌子叫李四牌面包,王五家出品的是王五牌面包,而突然有一天,张三家的面包改名了,叫面包牌面包.

WineHQ 数据库泄漏

- gnawux - LinuxTOY
运行于 *Nix 之上的开源跨平台 Win32 API 兼容层 WineHQ 的 AppDB 和 Bugzilla 数据库被黑客攻击. CodeWeavers CEO Jeremy 在信中提到黑客利用某种方式获取了 WineHQ 的 AppDB 和 Bugzilla 的访问,并且下载了完整数据库文件.