暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

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

运维路书 2024-09-20
189


最近,有读者交流时,说面试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 = 256K
              sort_buffer_size = 2M
              read_buffer_size = 1M
              read_rnd_buffer_size = 512K
              join_buffer_size = 1M
              tmp_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连接。这还是一个基于简单应用的理论值,实际项目过程中比这个值要少,还是要通过压力测试再进一步的接近实际值。


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


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



                    点击蓝字 关注我们



                    文章转载自运维路书,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论