了解是什么限制了数据库连接的数量

1,081 阅读5分钟

简介

你有没有想过,一个给定的RDBMS所提供的数据库连接的最大数量是多少?

在这篇文章中,我们将看看是什么限制了数据库连接的数量,无论你使用的是Oracle、SQL Server、PostgreSQL还是MySQL。

甲骨文

如果你使用的是Oracle,你可以使用V$RESOURCE_LIMIT 视图来检查各种系统资源的最大限制,以及当前的分配数量。

在我们的案例中,我们对processessessions 资源感兴趣,所以我们可以使用以下查询来收集这些信息。

SELECT 
    RESOURCE_NAME,
    CURRENT_UTILIZATION,
    MAX_UTILIZATION,
    INITIAL_ALLOCATION,
    LIMIT_VALUE
FROM
    V$RESOURCE_LIMIT
WHERE
    RESOURCE_NAME IN (
      'processes',
      'sessions'
    )

而当在我的本地Oracle XE数据库上运行这个SQL查询时,我得到的结果如下。

| RESOURCE_NAME | CURRENT_UTILIZATION | MAX_UTILIZATION | INITIAL_ALLOCATION | LIMIT_VALUE |
|---------------|---------------------|-----------------|--------------------|-------------|
| processes     | 77                  | 88              | 1000               | 1000        |
| sessions      | 104                 | 113             | 1528               | 1528        |

processes 记录显示,我当前的Oracle数据库有1000个操作系统进程可以连接到它的硬性限制,而sessions 行告诉我们,这个特定的Oracle XE数据库支持最大数量的1528 并发连接。

然而,我们很快就会看到,在我目前的笔记本上使用1500 并发连接将是一个糟糕的主意,因为实际上,最大连接数是相对于底层系统资源而言的,如此高的并发值将很容易使我的笔记本的非常有限的资源饱和。

SQL服务器

SQL Server最多允许32,767个用户连接。因为user connections 是一个动态的(自我配置)选项,所以SQL Server会根据需要自动调整用户连接的最大数量,最多可达到允许的最高值。

PostgreSQL

PostgreSQL提供了一个 max_connections设置,其默认值为100

因为PostgreSQL中的数据库连接是在单个操作系统进程中运行的,所以你不希望把max_connections 设置成一个非常高的值,因为这将损害你的数据库系统的吞吐量。

MySQL

MySQL也提供了一个 max_connections设置来控制最大并发连接数,默认值是151

什么限制了最大连接数?

在现实中,即使不对最大连接数设置硬性限制,也总会有一个提供最大吞吐量的最大连接数。

如果你读过令人惊叹的《Java并发实践》,那么你就会熟悉阿姆达尔定律,它给出了最大连接数与执行计划并行化能力之间的关系,但这只是故事的一半。

阿姆达尔定律只告诉我们,一个资源有限的系统可以达到最大吞吐量,但它没有考虑到增加连接数的成本。

这就是为什么一个更好的公式是通用可扩展性定律,它提供了吞吐量和并发连接数之间的关系,它告诉我们,在达到最大吞吐量后,增加更多的连接将降低吞吐量,因为系统将不得不花费资源来协调所有的并发连接。

USL (Universal Scalability Law)

因此,在现实中,一个给定的数据库系统所提供的最大连接数是由底层硬件资源(如CPU、IO、内存)、优化器能力以及由客户发送的SQL语句所产生的负载决定的。

默认情况下,最大连接数被设置得太高了,有可能造成数据库方面的资源匮乏。

因此,只有性能负载测试才能为你提供能在你的特定系统上提供最佳吞吐量的最大连接数。这个值应该被用作所有连接到数据库的应用节点所能共享的最大连接数。

如果最大连接数设置得太高,就像许多默认设置一样,那么你就有可能过度订阅连接请求,导致数据库资源匮乏,正如这个非常好的视频演示中所解释的。

如何增加数据库的最大连接数

虽然从理论上讲,像SQL Server这样的数据库允许你打开32,767个连接,但在实践中,系统资源瓶颈会在一个更低的值上出现。

所以,有两种方法可以增加最大连接数。

  • 纵向扩展
  • 横向扩展

垂直扩展是通过改善硬件资源来实现的,在现实生活中,最好的系统垂直扩展的例子是Stack Overflow,它已经成功地进行了十多年的垂直扩展。如果你查看Stack Overflow的性能统计,你会发现他们仅用两个SQL Server节点就能提供13亿的页面浏览量,这些节点有1.5TB的数据来存储缓冲池中的整个工作集的表和索引页面。

横向扩展是通过数据库复制完成的,通过增加更多的数据库节点,用户可以建立额外的连接,为系统增加额外的资源。

Database Replication

虽然扩展只读事务很容易,因为你可以只增加更多的复制节点,但扩展读写事务就比较困难了,因为在单主复制方案中,只能有一个,而且只有一个主节点。

如何在多个应用节点之间分割连接?

主节点有一个最大的连接数,它可以为其客户提供服务,但连接可以从多个应用程序(如前端节点、批处理任务)建立。

那么,如何将有限的连接数分给多个应用节点呢?

有两种方法来实现这一目标。

  • 你可以设置一个应用层面的连接池,如HikariCP,并使用FlexyPool来确定一个给定的应用节点需要的最大连接数。
  • 你可以在主节点前面使用ProxySQLHAProxy,让应用程序从这个连接池服务中借用连接,而不是直接从数据库系统中获取。

结论

虽然许多数据库系统提供了一个给定的最大连接数限制,但实际上,这种设置并不十分有用,因为实际的限制是由底层系统资源(如CPU、IO、内存)、数据库优化器算法和来自客户端的传入负载所给出。

由于每个系统都是独一无二的,你将不得不通过性能负载测试来确定最大连接数。之后,你可以通过复制增加只读连接的限制,通过扩大主节点的规模增加读写连接的限制。