查看原文
其他

DBA面试,问一台MySQL服务器最大能支持多少连接?问倒一片候选人。。。

运维路书 运维路书
2024-11-05


最近,有读者交流时,说面试DBA时,被问了这样一个问题:

“一台MySQL服务器最大能支持多少连接?” 

回答的乱七八糟,现场气氛一度很尴尬。

所以,今天就来讨论一下这个问题。


个人观点:其实这个问题没有标准答案,不用直接回答100还是200,而是看你的回答思路是否正确?


概要




  • MySQL层连接数

  • Linux服务器的TCP连接数

  • Linux系统的文件打开数

  • 示例


MySQL层连接数


这里不仅仅指配一个max_connections的参数

MySQL的连接数限制受多个因素影响,包括服务器硬件资源、MySQL配置和系统参数。

在评估一台服务器能支撑的MySQL连接数时,最重要的因素之一就是内存的合理分配。


MySQL服务器的内存分配通常分为三类

01

预留给缓冲池

MySQL的InnoDB引擎需要为缓冲池(Buffer Pool)预留大量内存,通常建议将物理内存的60-70%用于InnoDB缓冲池。这个缓冲池用于缓存数据和索引,提升查询性能,因此内存的合理分配至关重要。

02

每个连接的内存开销

每个MySQL连接都会占用线程资源,以下是一些与每个线程相关的内存参数:

thread_stack:每个线程的栈大小

join_buffer_size:用于联接操作的缓冲区大小。

read_buffer_size:顺序读取时的缓冲区大小

read_rnd_buffer_size:随机读取时的缓冲区大小。

sort_buffer_size:用于排序操作的内存空间。

tmp_table_size:使用临时表的大小

这些参数的大小直接决定了每个线程的内存消耗,过大的设置可能导致内存紧张,影响连接数。


03

系统预留内存

除了MySQL的内存消耗外,系统自身的内存需求也必须被考虑。Linux系统需要预留一部分内存用于系统进程、缓存和其他服务。通常建议保留10-20%的系统内存给操作系统,以确保系统的稳定性


通过合理调整MySQL配置参数,可以有效提高连接数。

根据内存容量、配置以及实际负载,MySQL的连接数可以从数百到数千个不等。



Linux服务器的TCP连接数


MySQL的每个连接实际上对应着一个TCP连接。

MySQL的每个客户端连接到服务器时,会通过TCP协议建立一个socket连接。

这就意味着服务器在支持MySQL连接数时,除了要考虑MySQL的参数配置,还要确保系统可以支撑足够多的TCP连接。


TCP连接数:理论上,Linux系统可以支持大量的TCP连接,但受限于系统资源。影响因素包括内存、CPU、网络带宽等。在理想状态下,仅维护空闲TCP连接,一个TCP连接大概需要3K左右的内存。4GB内存的服务器可以支持100万以上的连接数。


TCP四元组:每个TCP连接由源IP、源端口、目标IP和目标端口四元组唯一确定。在MySQL的连接场景中,服务器会消耗一个端口和相关资源来处理每个TCP连接。


以上仅为理论值,实际应用中,不同的业务类型需要收发的数据大小不同,所需的内存也不同。


所有不以业务为导向的理论都是耍流氓!


Linux系统的文件打开数

在Linux中,文件描述符用于标识已打开的文件,而socket连接也被视为文件。因此,MySQL连接数还受系统能打开的最大文件数限制。


系统级别的文件数限制

fs.file-max:系统级别能打开的最大文件数。可以通过调整这个参数来扩大系统的文件打开数上限。


fs.nr_open:控制整个 Linux 系统中 单个进程 可以打开的文件描述符(file descriptors, FD)总数上限。也就是说,它设置了一个进程能打开的文件数量的绝对上限。


进程级别的文件数限制

soft nofile: 表示用户可以在正常情况下打开的最大文件数。

hard nofile:表示可以提升 soft nofile 到的最大值,即用户进程能打开的文件数硬性上限,用户不能自行超越 hard nofile,但可以通过管理员权限调整。


这几个参数相互耦合,调整时需要注意:

  1. soft nofile不能超过hard nofile,否则实际生效值会按照两者中的较小值来确定。

  2. hard nofile必须小于fs.nr_open,否则可能导致用户无法登录。

配置文件调整

假设我们需要让进程支持100万连接,可以通过以下配置文件来调整:

vim /etc/sysctl.conf fs.file-max=1100000 # 系统级别设置成110万,多留点buffer  fs.nr_open=1100000 # 进程级别也设置成110万,因为要保证比 hard nofile大

以上配置生效: /etc/sysctl -p


vim /etc/security/limits.conf    # 用户进程级别都设置成100万 soft nofile 1000000  hard nofile 1000000


示例

通过一个具体的示例再详细说明一下


假设我们有一台128GB内存的Linux服务器,目标是尽可能多地支持MySQL连接。以下是内存分配和MySQL连接数的预估过程。


1

内存分配策略


InnoDB缓冲池

由于MySQL的InnoDB引擎对缓冲池的依赖较大,建议将内存的60-70%分配给InnoDB缓冲池。

对于128G内存的服务器,预留70%内存给缓冲池:

innodb_buffer_pool_size = 128G * 0.7 = 89.6G

系统预留内存

通常需要预留10-20%的内存给操作系统以及其他服务

我们选择预留15%:

128G * 0.15 = 19.2G

MySQL线程

剩余内存分配给MySQL线程

128G - 89.6G - 19.2G = 19.2G
2

MySQL每个连接的内存消耗


假设每个MySQL连接的内存消耗主要来源于以下几个配置项:

(参数设置偏低,实际应用中会有差别)

thread_stack = 256Ksort_buffer_size = 2Mread_buffer_size = 1Mread_rnd_buffer_size = 512Kjoin_buffer_size = 1Mtmp_table_size = 16M

每个连接的总内存消耗为:

thread_stack + sort_buffer_size + read_buffer_size + read_rnd_buffer_size + join_buffer_size + tmp_table_size= 256K + 2M + 1M + 512K + 1M + 16M≈ 20M

每个连接大约消耗20MB的内存。


3

计算可支持的MySQL连接数


在128GB内存的服务器上,MySQL线程可使用的总内存为19.2GB,因此可支撑的连接数为:

可支持的连接数 = 可用内存 / 每个连接的内存消耗               = 19.2G / 20M               ≈ 960 个连接

因此,在没有其他额外负载的情况下,这台128GB内存的服务器大约可以支撑960个并发MySQL连接。(这其实还是一个理论值,因为参数设置相对较低


4

考虑文件描述符和TCP连接限制

文件描述符限制

每个MySQL连接都会占用一个文件描述符,假设系统的文件描述符限制足够高(如上设置为100万),不会成为瓶颈。


TCP连接数限制

Linux系统的TCP连接数通常不会成为瓶颈,但仍需要确保系统配置足够:

net.ipv4.ip_local_port_range = 1024 65535 #端口号net.core.somaxconn = 1024 # 增加全连接队列长度


5

示例总结


这台128GB内存的Linux服务器,通过合理分配内存资源(例如InnoDB缓冲池和系统预留),可以大约支撑960个并发MySQL连接。这还是一个基于简单应用的理论值,实际项目过程中比这个值要少,还是要通过压力测试再进一步的接近实际值。


掌握了解决这个问题的思路即可,不需要过分纠结的具体数字,实际应用中很难预估的很准确。


【以上仅为个人观点,如有不同意见,欢迎留言讨论!】



点击蓝字 关注我们



继续滑动看下一个
运维路书
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存