mysql的连接组件
1.连接组件包含什么?(以下为我个人的理解)
1.连接器(基于协议实现)
2.连接管理模块
3.连接进程模块(包括线程管理模块和连接线程模块)
4.用户模块(用户校验)
2.连接池组件都在做什么?
首先在mysql的整个连接过程中,和我们直接打交道的通常就是基于开发语言的连接器,以Java为例,是由mysql自己提供的mysql-connector-java的一个jar包(JDBC的实现),我们的应用程序通常就是通过这个连接器来与mysql进行连接。
在mysql内部与之进行连接的就是连接管理模块。当mysql整个系统初始化结束后,连接管理模块接手。连接管理模块启动处理客户端请求的监听程序(包括tcp/ip的网络监听,还有unix的socket)。当连接管理模块监听到客户端的连接请求,双方通过client&server交互协议模块所定义的协议进行连接(通常是tcp/ip),连接管理模块就会将连接请求转发给线程管理模块,去请求一个连接线程。
线程管理模块又回通知连接线程模块:有连接请求过来,需要建立连接。连接线程模块(这里我理解它就是mysql的线程组)接到连接请求后,首先会检查当前的线程池中是否有被缓存的空闲连接线程(mysql的线程组中不只有连接线程还有监听线程,之后写一个专门讲线程组的文章),如果有,就去出一个和客户端连接,如果没有空闲的连接线程,则建立一个新的连接线程与客户端请求连接。当然连接线程模块并不是在收到连接请求后马上去出一个连接线程与客户端连接,而是首先调用用户模块进行授权检查,他才会将客户端请求和负责请求的连接线程连上。
用户名或者密码不对,那么会直接抛出"Access denied for user" 的错误,客户端结束执行。如果验证通过的话,会直接在权限表里查出你拥有的权限。之后,这个连接里面的权限判断逻辑都将依赖于此时读到的权限。注意,这就意味着,一个用户成功建立连接之后,即使管理员用户修改了这个用户的权限,也不会影响到已经存在的连接,只有后面的新链接才会使用新的权限设置。
3.mysql的通信协议?
4.mysql长/短连接
4.1 长/短连接定义
短连接:程序和数据库通信时需要建立连接,执行操作后,连接关闭。短连接简单来说就是每次操作数据库,都需要建立和断开连接。(客户端连接-创建socket认证连接-维护连接-数据传输-关闭连接)
长连接:长连接是指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。mysql的长连接如果长时间限制,mysql默认会在8小时(可以自己配置)后主动断开连接。(客户端连接-创建socket认证连接-维护连接-数据传输-维护连接-数据传输-......-关闭连接)
4.2 长/短连接的选择
短连接:在网络速度不是很稳定的情况下,短连接会消耗大量的系统资源(因为连接的建立和断开过程需要大量的交互)。在高并发的情况下(网络不稳定的前提下),可能一秒钟需要有几千个连接,如果都是短链接,且sql处理慢的话,会导致资源耗尽速度加快(这里的资源也包括端口资源)。
长连接:从客户端角度来看,使用长连接可以减少创建连接的开销(如果客户端对mysql服务器的请求很频繁,长连接会更加的高效)。从mysql角度来看,维持连接也是需要内存的。(mysql在执行过程中临时使用的内存是管理在连接对象里面的,这就意味着只有在连接断开之后这些资源才会释放。所以长连接累积下来,可能会导致内存占用太大,被系统强行杀掉OOM,也就是mysql异常重启)
总结:在频繁的与数据库服务通信,并且又非高并发的情况下,使用长连接更合适;太多持久连接,大部分是sleep状态的,或者系统是高并发的,使用短连接更合适。
4.3 长连接优化
1.定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。 2.如果你用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。
5.连接之后的状态(show processlist)
连接完成之后,如果没有后续操作,那么这个连接就会进入空闲状态,可以通过show processlist 来查看所有的连接。(show processlist 是显示用户正在运行的线程,需要注意的是,只有root用户可以看到正在运行的所有线程,其他用户都只能看到自己正在运行的线程,看不到其他用户正在运行的线程。除非单独给这个用户赋予process权限)
show processlist (select * from information_schema.processlist) 查询全部连接
依次解释一下表中的字段含义:
Id:线程的唯一标识(也是information_schema.processlist的主键),可以通过kill命令加上Id值将这个线程杀掉。
User:启动这个线程的用户。
Host:这里会记录连接的客户端的ip和端口号。(用户定位到是哪个客户端的哪个进程的连接)
DB:当前执行的命令是在哪一个数据库上。如果没有指定数据库,则该值为NULL。
Command:指此时此刻该线程正在执行的命令。(具体值可以参考mysql8.14.2 Thread Command Values)
Time:表示该线程处于当前状态的时间(s)。
State:线程的状态,和Command对应。
一些可能会用到的语句
1.查看连接数最多的客户端
select client_ip,count(client_ip) as client_num from (select substring_index(host,':' ,1) as client_ip from information_schema.processlist ) as connect_info group by client_ip order by client_num desc;
2、查看正在执行的线程,并按 Time 倒排序,看看有没有执行时间特别长的线程
select * from information_schema.processlist where Command != 'Sleep' order by Time desc;
3、找出所有执行时间超过 5 分钟的线程,拼凑出 kill 语句,方便后面查杀 (此处 5分钟 可根据自己的需要调整SQL标红处)
select concat('kill ', id, ';') from information_schema.processlist where Command != 'Sleep' and Time > 300 order by Time desc;
6.mysql连接组件的优化?
暂无
参考文献
-
[2] 浅谈Mysql架构体系
-
[3] MySQL性能调优于架构设计