昨天有个微信群在讨论计算数据库连接数的公式,截图不是很清楚。让我描述一下。据说PG提供了连接数的计算公式:连接数=核心数*2+有效磁盘数。核心数不应包括超线程数,而应包括物理核心数。这是一个非常典型的用于估计连接数的极限测试公式。主要目的是避免CPU出现瓶颈。这种设置思路在普通的生产系统中往往不会采用,因为不管是OLTP系统还是OLAP系统,作为数据库服务器,会话中的很多工作都会产生在IO上,包括网络IO和磁盘IO.CPU使用百分比实际上并没有那么高。对于OLTP系统,大量的CPU使用量小于一个时间片(大多数UNIX系统为一厘秒),一个时间片很少用完,因为在数据库应用中,大部分会话都在等待一定的时间。对于一些等待事件,比如IO、LWLOCK、LOCK、IPC等,一个session的ONCPU状态的比例是很低的,所以以CPU数作为设置oncpu状态的依据其实是没有科学依据的会话数。从另一个角度来看,CPU之间也存在差异。即使是相同核数的CPU,其处理能力也是不同的。三五年前相同核数的CPU,处理能力未必和今天一样。1/3,同样的CPU时间所能完成的任务也会相差很大。简单地以CPU作为设置连接数的依据显然是不合理的。在当今绝大部分的OLTP系统中,数据库服务器的CPU资源都非常充足,大多数系统的主要问题并不是出现在CPU资源不足上。这就是过去二十年摩尔定律给我们带来的红利。事实上,数据库中存在排队效应的地方有很多,任何一个地方出现瓶颈都会影响到极限测试的性能和生产环境中的并发访问效率。两年前写过一篇文章《从疏通下水道联想到的优化问题》,在这篇文章里做了详细的分析。有兴趣的朋友可以到我的公众号里找找。事实上,决定数据库连接数的最重要因素是应用程序。对于大多数数据库系统,max_connections参数必须保证所有使用该数据库的模块都不会因为连接池不足而导致应用程序错误。目前的应用系统大多非常复杂,大量模块使用微服务,并发性非常不稳定。我见过一个数据库系统对接了100多个应用程序连接池。即使一个连接池设置了几十个连接,max_connections也必须设置成几千个才能保证大多数情况下应用不会因为数据库连接数的限制而失败。.数据库最大连接数设置太大有什么坏处?最容易出问题的往往不是CPU。当然,如果在云环境下,我们数据库的CPU资源很少,那么大连接可能会导致CPU资源不足。关于云环境下数据库服务器的CPU资源问题,那是一个更大的话题——容量管理,今天不讨论。一般来说,数据库应用程序对CPU的使用不存在资源不足的问题。当然,如果一个并发量大的SQL执行计划有误,很容易把CPU炸掉。这不是我们今天要讨论的。在这个范围内,因为这种情况,即使连接数设置的很低,也会出现问题。另外,内存是最容易出问题的。如果数据库会话过多,ATTACH共享内存占用的TLB会很大,尤其是数据库不使用大页的情况下。前段时间,我们在分析一个数据库宕机的案例时,发现在一个128GB的数据库服务器上,TLB高达30GB。另外,session会使用WORK_MEM进行排序、JOIN等操作。session越多,自然会占用更多的内存。两年前和一个国外的PGER交流的时候,他提出了一种PG内存估算的方法。悲观算法以MAX_CONNECTIONS*WORK_MEM为会话工作内存,乐观算法以MAX_ACTIVE_SESSIONS*WORK_MEM为会话工作内存。据此,结合物理内存大小,计算出SHARED_BUFFERS可以使用的内存最大值。其实悲观和乐观算法计算出的数值相差很大,基本没有参考价值。当时我就跟他说,与其这么细心小心,不如把SWAP设置高一点,就算物理内存偶尔用多了,系统也会有小抖动,很快就结束了.他想了想,同意我的看法。其实我们今天讨论的很多内容都属于容量管理的范畴。这个问题也困扰了我将近20年。在这20年里,我参与了很多容量管理相关的项目,帮助用户建立了一些模型。然而,那份感觉依然悬在门外。有时间我也会写几篇这方面的文章,和大家分享一下我们这些年的一些成果。
