前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL 案例:"最大连接数"的隐形限制

MySQL 案例:"最大连接数"的隐形限制

原创
作者头像
王文安@DBA
发布2020-11-25 16:53:36
6.1K0
发布2020-11-25 16:53:36
举报

问题描述

最近遇到一个比较奇怪的问题,用户反馈云服务器的自建 MySQL 连接数没达到的 max_connections 限制,但是程序侧已经开始报错,无法创建新的连接了。程序端报错信息如下:

代码语言:txt
复制
perationalError(1135, "Can't create a new thread (errno 11); if you are not out of available memory, 
you can consult the manual for a possible OS-dependent bug")

MySQL 侧的错误日志显示:

代码语言:txt
复制
Can't create thread to handle new connection(errno= 11)

原因分析

如果是触发了最大连接数的限制,错误信息应该是Too many connections,因此这次遇到的问题应该不是参数方面的问题。

值得注意的是,报错信息中显示了 errorno,这个一般是系统层面抛出的异常 Code,因此看一下这个 11 代表的意义:

OS error code 11: Resource temporarily unavailable

那么问题就比较明显了,这个问题是部分资源不可用引起的,说明是收到了外部(即 Linux)的影响才报错的。那么按照用户的环境,搭建了一个沙盒环境,写了一个简单的 python 脚本(参考附录),发现创建的连接数达到一定的数量之后确认会报错,且抛出的异常信息和用户反馈的信息一致:

代码语言:txt
复制
root@VM-64-5-debian:~# python3 py_conn.py
hello world
OperationalError(1135, "Can't create a new thread (errno 11); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug")
Current MAX_CONNECTION =  32455
5.7.32-log
5.7.32-log
......

在多次尝试过程中,发现一个现象:如果是从 thread_cache 中直接复用的线程是不会触发这个问题的,只有新建连接的时候才会触发。那么追踪了一下 MySQL 创建连接的流程,发现在./sql/conn_handler/connection_handler_per_thread.cc中,以 mysql_thread_create 方法的返回值为条件,会输出这个错误信息。之后以这个方法为入口,最终定位到了原因:调用系统库创建线程的时候出错了。

之后继续查找系统库相关的资料,发现创建线程的数量会受到 Linux 的参数:vm.max_map_count的限制。检查了一下这个参数的作用:

“This file contains the maximum number of memory map areas a process may have. Memory map areas are used as a side-effect of calling malloc, directly by mmap and mprotect, and also when loading shared libraries.

While most applications need less than a thousand maps, certain programs, particularly malloc debuggers, may consume lots of them, e.g., up to one or two maps per allocation.

The default value is 65536.”

简单来说,进程创建线程的时候会创建一些虚拟内存区域,而这个参数限制了这个区域的数量,因此 MySQL 的可创建的连接数也会受到这个参数的限制。

实际测试一下效果:

代码语言:txt
复制
Session 1:
root@debian:~# sysctl -w vm.max_map_count=256
vm.max_map_count = 256
root@debian:~# service mysql restart
root@debian:~# mysql57
......
Server version: 5.7.32-log MySQL Community Server (GPL)
......
mysql> select count(*) from performance_schema.threads;
+----------+
| count(*) |
+----------+
|       59 |
+----------+
1 row in set (0.00 sec)

mysql> show variables like '%max_conn%';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| max_connect_errors | 100   |
| max_connections    | 151   |
+--------------------+-------+
2 rows in set (0.01 sec)

Session 2:
root@debian:~# python3 py_conn.py
hello world
OperationalError(1135, "Can't create a new thread (errno 11); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug")
Current MAX_CONNECTION =  26
5.7.32-log
5.7.32-log
5.7.32-log
5.7.32-log

可以发现调低了这个系统参数之后,尝试创建连接的时候就会报错,而且可用的最大连接数非常低。

总结一下

这个案例属于比较典型的“受牵连”,即 MySQL 因为外部的限制导致问题的发生,DBA 们在排查问题的时候不仅需要考虑到 MySQL 的问题,也要留意是否是外部原因影响了 MySQL 的行为。

附录

Python3.7,py_conn.py。

代码语言:txt
复制
import MySQLdb
import time

def dbconn():
    try:
        conn = MySQLdb.connect(host="127.0.0.1",user="root",passwd="root",charset="utf8mb4")
        return conn
    except Exception as e:
        print(repr(e))
        return None

def main():
    print("hello world")
    conn_list = []
    num = 65535
    couter = 0
    for counter in range(0,num):
        conn = dbconn()
        if conn is None : break
        conn_list.append(conn) 
    i = 0
    print("Current MAX_CONNECTION = ",counter+1)
    while(True):
        tmp_conn = conn_list[i]
        cursor = tmp_conn.cursor()
        n = cursor.execute("select version()")
        for row in cursor.fetchall():
            for r in row:
                print(r)
        if (i == counter - 1): i = 0
        i = i + 1
        time.sleep (1)

if __name__ == "__main__":
    main()

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题描述
  • 原因分析
  • 总结一下
  • 附录
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档