如何解决MySQL超过最大连接数问题

如何解决MySQL超过最大连接数问题,第1张

遇到mysql超出最大连接数,相信不少人第一反应就是查看mysql进程,看有没有慢查询,当然这个做法是完全正确的!

但是很多时候真正的问题不在这里。

今天有遇到同样的问题,一味查看mysql进程和慢查询日志,无果。

后来老大提点了一下,查看一下nginx日志,发现有一两个访问执行时候比较长,然后使用top命令查看了一下服务器负载,惊了,居然超高!

最后发现原来有一台web分流主机挂了,导致另外几台web主机负载增高,从而导致了php-fpm的执行效率降低。

那么这跟mysql有什么关系呢?原因很简单,因为php执行时间过长,mysql连接迟迟未释放,就会导致连接数过多出现。

最后总结:其实很多时候,一个问题的根本原因并不是那么直接的呈现出来,需要自己去跟踪。

老大有一句很实用的话:遇到问题先查日志(mysql、php、nginx等)

===============================================================

排查连接数过多的方法

当用户收到链接数告警时,意味着连接数即将达到该实例的上限。如果实例的连接数超过了实例规定的连接数,将无法创建新的连接,这个时候会影响用户的业务;

Mysql 的连接通常是一个请求占用一个连接,如果该请求(update,insert,delete,select)长时间没有执行完毕,则会造成连接的堆积,迅速的消耗完数据库的连接数,这个时候技术支持人员就要登录数据库进行排序,看看到底是那些sql 占用了连接;

问题排查步骤:

1 、查看实例配置:

可登录RDS控制台“详情与配置”查看实例额定链接数,我们假设最高支持1500个链接

2、 查看当前的连接数:

1)可登录RDS控制台“性能监控”查看实例当前链接数。

2)或者登录数据库查询当前连接,可以使用同步账号或者用户的业务账号登录数据库,执行show processlist;

[root@r41d05036xy2aliyuncom ~]# mysql -uroot -h127001 -P3020 -e “show processlist”|wc -l

1262

可以看到该实例已经有1262 个连接

3、排查是什么动作占用了这些连接:

[root@r41d05036xy2aliyuncom ~]# myql -uroot -h127001 -P3018 -e “show full processlist”>/tmp/1log

root@r14d11038dgaliyuncom # more /tmp/1log

615083 my_db 223449212:54115 my_db Query 100 Sending data

INSERT INTO tmp_orders_modify (oid, tid, seller_id, status, gmt_create, gmt_modified)

SELECT oid, tid, seller_id, status, gmt_create, gmt_modified

FROM sys_infoorders WHERE

gmt_modified < NAME_CONST(‘v_last’,_binary’2012-12-24 10:33:00’ COLLATE ‘binary’) AN

D gmt_modified >= NAME_CONST(‘v_curr’,_binary’2012-12-24 10:32:00’ COLLATE ‘binary’)

621564 my_db 223449212:46596 my_db Query 3890 sorting result

insert into tmp_trades(sid, d, h, tc, tm, tp, ic, new_tp, old_tp)

select aseller_id as sid,

…………

from orders_1 as a where seller_id =1 and is_detail = ‘1’

and created < date_format(‘2012-12-24 10:35:00’, ‘%Y-%m-%d %H:00:00’)

and gmt_create < date_format(‘2012-12-24 10:40:00’, ‘%Y-%m-%d %H:%i:00’)

and gmt_create >= date_format(‘2012-12-24 10:35:00’, ‘%Y-%m-%d%H:%i:00’)

group by d, h

order by d

………………此处省略其他sql

4、分析连接占用的原因:

可以看到数据库中有长时间没有执行完成的sql,一直占用着连接没有释放,而应用的请求一直持续不断的涌入数据库,这个时候数据库的连接很快就被使用完;所以这个时候需要排查为什么这些sql 为什么长时间没有执行完毕,是索引没有创建好,还是sql执行耗时严重。

第一条sql:

INSERT INTO tmp_orders_modify (oid, tid, seller_id, status, gmt_create, gmt_modified)

SELECT oid, tid, seller_id, status, gmt_create, gmt_modified

FROM sys_infoorders WHERE

gmt_modified < NAME_CONST(‘v_last’,_binary’2012-12-24 10:33:00’ COLLATE ‘binary’) AN

D gmt_modified >= NAME_CONST(‘v_curr’,_binary’2012-12-24 10:32:00’ COLLATE ‘binary’)

是用户从sys_info 数据库中拉取订单到自己的业务库中那个,但是在orders 表上没有gmt_modified 的索引,导致了全表扫描;(更加详尽的排查方法可以参考:为什么我的RDS慢了);

第二条sql:

看到这条sql 正在进行sorting 排序,为什么导致sql 长时间sorting,通常情况下为排序的结果集太大导致排序不能在内存中完成,需要到磁盘上排序,进而导致了性能的下降;解决的办法就是降低排序的结果集,常用的手段是利用索引的有序性,消除排序,或者建立适当的索引减小结果集;我们可以看到第二条sql 的排序字段非常的复杂,但是我们可以看到查询的时间范围是很短,只有5 分钟的时间间隔,这个时候就可以在gmt_create上创建一个索引,过滤掉大部分的记录:

Alter tale order_1 add index ind_order_gmt_create(gmt_create);

(该用户对orders 进行了分表,大概有50 多张分表需要添加gmt_create 字段的索引);

5、经过上面两步的优化后,用户实例恢复正常:io 情况和connection 情况,可再次登录RDS控制台查看连接数。

1点击电脑左下角圆形的图标“开始”,然后在打开菜单中选择“运行”

2 点击“运行”后,就打开运行对话框,在运行对话框的的输入框中输入cmd,之后点下面的“确定”按钮,打开cmd命令提示符

3在打开的cmd命令提示符中输入下面的命令就可以查看自己的ip地址了

ipconfig /all

方法二

下面这种方式原理和xp系统类型,但是明显 *** 作比xp系统麻烦

点击电脑右下角的表示“网络连接”的图标,之后会打开连接信息对话框,选择“打开网络和共享中心”

在打开的 “打开网络和共享中心”页面中,选择“本地连接”,

在打开的“本地连接 状态”对话框中点击“详细信息”按钮

之后会打开“网络连接详细信息”对话框,在这里我们可以看到除了ip地址之外的更多信息,

mysql是通过线程缓存来完成线程重用的。客户端发起连接时,首先会去线程缓冲池里找是不是有空闲的线程。如果没有才会去新建线程。当一个连接断开的时候,并不会马上销毁线程释放资源。而是暂时把线程放在缓冲池中挂起。

所以这里就涉及到了三个参数,一个是treads_cached这个是缓冲池中的线程个数。还有一个是treads_connected这个是连接中的线程数。第三个就是你说的这个。它的含义是已经创建的线程数。在并发数低的情况下,一般Threads_created参数是treads_cached和treads_connected参数之和。当并发数高的情况下,Threads_created就会暴增,这个时候就需要考虑thread_cache_size来设置缓冲池的大小了。

纯手打。外加是我自己的理解。错误的地方我们可以讨论一下。

1、通过命令行查看:show variables like "max_connections";

2、查看配置文件mycnf,max_connections就是最大连接数,如果没有,那证明你没有做相关设置,所以是系统默认的值。

在使用MySQL数据库的时候,经常会遇到这么一个问题,就是“Can not connect to MySQL server Too many connections”-mysql 1040错误,这是因为访问MySQL且还未释放的连接数目已经达到MySQL的上限。

通常,mysql的最大连接数默认是100, 最大可以达到16384。

在Windows下常用的有两种方式修改最大连接数。

第一种:命令行修改。

>mysql -uuser -ppassword(命令行登录MySQL)

mysql>show variables like 'max_connections';(查可以看当前的最大连接数)

msyql>set global max_connections=1000;(设置最大连接数为1000,可以再次查看是否设置成功)

mysql>exit(推出)

这种方式有个问题,就是设置的最大连接数只在mysql当前服务进程有效,一旦mysql重启,又会恢复到初始状态。

因为mysql启动后的初始化工作是从其配置文件中读取数据的,而这种方式没有对其配置文件做更改。

第二种:修改配置文件。

这 种方式说来很简单,只要修改MySQL配置文件myini 或 myf的参数max_connections,将其改为max_connections=1000,然后重启MySQL即可。

但是有一点最难的就是myini这个文件在哪找。

通常有两种可能,一个是在安装目录下(这是比较理想的情况),另一种是在数据文件的目录下,安装的时候如果没有人为改变目录的话,一般就在C:/ProgramData/MySQL往下的目录下。

与连接数相关的几个参数:

在修改最大连接数的时候会有这样一个疑问—这个值是不是越大越好,或者设置为多大才合适?这个参数的大小要综合很多因素来考虑,比如使用的平台所支持的线程库数量(windows只能支持到2048)、服务器的配置(特别是内存大小)、每个连接占用资源(内存和负载)的多少、系统需要的响应时间等。

可以在global或session范围内修改这个参数。

连接数的增加会带来很多连锁反应,需要在实际中避免由此引发的负面影响。

首先看一下MySQL的状态:

mysql> status;

--------------

mysql Ver 1414 Distrib 5515, for Win32 (x86)

Connection id: 1

Current database:

Current user: root@localhost

SSL: Not in use

Using delimiter: ;

Server version: 5515 MySQL munity Server (GPL)

Protocol version: 10

Connection: localhost via TCP/IP

Server characterset: utf8

Db characterset: utf8

Client characterset: gbk

Conn characterset: gbk

TCP port: 3306

Uptime: 1 hour 3 min 27 sec

Threads: 12 Questions: 18 Slow queries: 10 Opens: 33 Flush tables: 5 Open tab

les: 34 Queries per second avg: 6256

--------------

Open tables:34,即当前数据库打开表的数量是34个,注意这个34并不是实际的34个表,因为MySQL是多线程的系统,几个不同的并发连接可能打开同一个表,这就需要为不同的连接session分配独立的内存空间来存储这些信息以避免冲突。

因此连接数的增加会导致MySQL需要的文件描述符数目的增加。

另外对于MyISAM表,还会建立一个共享的索引文件描述符。

在MySQL数据库层面,有几个系统参数决定了可同时打开的表的数量和要使用的文件描述符,那就是table_open_cache、max_tmp_tables和open_files_limit。

mysql> show variables like 'table_open%';

+------------------+-------+

| Variable_name | Value |

+------------------+-------+

| table_open_cache | 256 |

+------------------+-------+

1 row in set (000 sec)

table_open_cache:256,这就是说所有的MySQL线程一共能同时打开256个表,我们可以搜集系统的打开表的数量的历史记录和这个参数来对比,决定是否要增加这个参数的大小。

查看当前的打开表的数目(Open tables)可用上边提到过的status命令,另外可以直接查询这个系统变量的值:

mysql> show status like 'open_tables';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_tables | 3 |

+---------------+-------+

1 row in set (000 sec)

Open_tables就是当前打开表的数目,通过flush tables命令可以关闭当前打开的表。

这个值如果过大,并且如果没有经常的执行flush tables命令,可以考虑增加table_open_cache参数的大小。

接下来看max_tmp_tables:

mysql> show variables like 'max_tmp%';

+----------------+-------+

| Variable_name | Value |

+----------------+-------+

| max_tmp_tables | 32 |

+----------------+-------+

1 row in set (000 sec)

max_tmp_tables:32即单个客户端连接能打开的临时表数目。

查看当前已打开的临时表的信息:

mysql> show global status like '%tmp%table%';

+-------------------------+-------+

| Variable_name | Value |

+-------------------------+-------+

| Created_tmp_disk_tables | 0 |

| Created_tmp_tables | 11 |

+-------------------------+-------+

2 rows in set (000 sec)

根据这两个值可以判断临时表的创建位置,一般选取BLOB和TEXT列、Group by 和 Distinct语句的数据量超过512 bytes,或者union的时候select某列的数据超过512 bytes的时候,就直接在磁盘上创建临时表了,另外内存中的临时表变大的时候,也可能被MySQL自动转移到磁盘上(由tmp_table_size和max_heap_table_size参数决定)。

增加table_open_cache或max_tmp_tables 参数的大小后,从 *** 作系统的角度看,mysqld进程需要使用的文件描述符的个数就要相应的增加,这个是由open_files_limit参数控制的。

mysql> show variables like 'open_files%';

+------------------+-------+

| Variable_name | Value |

+------------------+-------+

| open_files_limit | 2670 |

+------------------+-------+

1 row in set (000 sec)

但是这个参数是OS限制的,所以我们设定的值并不一定总是生效。

如果OS限制MySQL不能修改这个值,那么置为0。

如果是专用的MySQL服务器上,这个值一般要设置的尽量大,就是设为没有报Too many open files错误的最大值,这样就能一劳永逸了。

当 *** 作系统无法分配足够的文件描述符的时候,mysqld进程会在错误日志里记录警告信息。

相应的,有两个状态变量记录了当前和历史的文件打开信息:

mysql> show global status like '%open%file%';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_files | 0 |

| Opened_files | 76 |

+---------------+-------+

2 rows in set (000 sec)

MySQL为每个连接分配线程来处理,可以通过threads_connected参数查看当前分配的线程数量:

mysql> show status like '%thread%';

+------------------------------------------+-------+

| Variable_name | Value |

+------------------------------------------+-------+

| Delayed_insert_threads | 0 |

| Performance_schema_thread_classes_lost | 0 |

| Performance_schema_thread_instances_lost | 0 |

| Slow_launch_threads | 0 |

| Threads_cached | 0 |

| Threads_connected | 1 |

| Threads_created | 1 |

| Threads_running | 1 |

+------------------------------------------+-------+

8 rows in set (000 sec)

比较threads_connected参数和前面提到的max_connections参数,也可以作为目前的系统负载的参照,决定是否需要修改连接数。

查看每个线程的详细信息:mysql>show processlist;对影响系统运行的线程:kill connection|query threadid的命令杀死。

以上就是关于如何解决MySQL超过最大连接数问题全部的内容,包括:如何解决MySQL超过最大连接数问题、如何查看MySQL各IP连接数、mysql通过show status like 'Thread%'命令查看数据库的连接情况,请问一下问题:等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/sjk/9270303.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-26
下一篇 2023-04-26

发表评论

登录后才能评论

评论列表(0条)

保存