连接器

281 阅读5分钟

连接器负责跟客户端建立连接、获取权限、维持和管理连接。如果在 Linux 里要使用 MySQL,那第一步肯定是先连接 MySQL 服务,接待的就是连接器,然后才能执行 SQL 语句,普遍都是使用下面这条命令进行连接

# -h 指定 MySQL 服务的 IP 地址,如果是连接本地的 MySQL服务,可以不用这个参数;
# -u 指定用户名,管理员角色名为 root;
# -p 指定密码,如果命令行中不填写密码(为了密码安全,建议不要在命令行写密码),就需要在交互对话里面输入密码
mysql -h$ip -u$user -p

连接的过程需要先经过 TCP 三次握手,因为 MySQL 是基于 TCP 协议进行传输的,如果 MySQL 服务并没有启动,则会收到如下的报错: image.png

如果 MySQL 服务正常运行,完成 TCP 连接的建立后,连接器就要开始验证用户名和密码,如果用户名或密码不对,就收到一个 "Access denied for user" 的错误,然后客户端程序结束执行 image.png

如果用户密码都没有问题,连接器会到权限表里面查出该用户的权限,然后保存起来,后续该用户在此连接里的任何操作,都会基于连接开始时读到的权限进行权限逻辑的判断

如果一个用户已经建立了连接,即使管理员中途修改了该用户的权限,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置

如何查看 MySQL 服务被多少个客户端连接了?

如果想知道当前 MySQL 服务被多少个客户端连接了,你可以执行 show processlist 命令进行查看

image.png 比如上图的显示结果,共有两个用户名为 root 的用户连接了 MySQL 服务,其中 id 为 6 的用户的 Command 列的状态为 Sleep ,这意味着该用户连接完 MySQL 服务就没有再执行过任何命令,也就是说这是一个空闲的连接,并且空闲的时长是 736 秒( Time 列)。

空闲连接会一直占用着吗?

当然不是了,MySQL 定义了空闲连接的最大空闲时长,由 wait_timeout 参数控制的,默认值是 8 小时(28880秒),如果空闲连接超过了这个时间,连接器就会自动将它断开。

mysql> show variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
1 row in set (0.00 sec)

也可以手动断开空闲的连接,使用的是 kill connection + id 的命令

mysql> kill connection +6;
Query OK, 0 rows affected (0.00 sec)

一个处于空闲状态的连接被服务端主动断开后/手动断开连接之后,这个客户端并不会马上知道,等到客户端在发起下一个请求的时候,才会收到这样的报错 “ERROR 2013 (HY000): Lost connection to MySQL server during query”。这时候如果要继续,就需要重连,然后再执行请求了。

MySQL 的连接数有限制吗?

MySQL 服务支持的最大连接数由 max_connections 参数控制,比如我的 MySQL 服务默认是 151 个,超过这个值,系统就会拒绝接下来的连接请求,并报错提示“Too many connections”。

mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 151   |
+-----------------+-------+
1 row in set (0.00 sec)

MySQL 的连接也跟 HTTP 一样,有短连接和长连接的概念,它们的区别如下:

// 短连接
连接 mysql 服务(TCP 三次握手)
执行sql
断开 mysql 服务(TCP 四次挥手)

// 长连接
连接 mysql 服务(TCP 三次握手)
执行sql
执行sql
执行sql
....
断开 mysql 服务(TCP 四次挥手)

数据库里面,长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。

建立连接的过程通常是比较复杂的,使用长连接的好处就是可以减少建立连接和断开连接的过程,所以一般是推荐使用长连接

但是,使用长连接后可能 MySQL 会占用内存增多,因为 MySQL 在执行查询过程中临时使用内存管理连接对象,这些连接对象资源只有在连接断开时才会释放。如果长连接累计很多,将导致 MySQL 服务占用内存太大,有可能会被系统强制杀掉,这样会发生 MySQL 服务异常重启 的现象

怎么解决长连接占用内存的问题?

有两种解决方式。

第一种,定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。

第二种,客户端主动重置连接。MySQL 5.7 或更新版本实现了 mysql_reset_connection() 函数的接口,注意这是接口函数不是命令,那么当客户端执行了一个很大的操作后,在代码里调用 mysql_reset_connection 函数来重新初始化连接资源(重置连接),达到释放内存的效果。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态

至此,连接器的工作做完了,简单总结一下:

  • 与客户端进行 TCP 三次握手建立连接
  • 校验客户端的用户名和密码,如果用户名或密码不对,则会报错
  • 如果用户名和密码都对了,会读取该用户的权限,然后后面的权限逻辑判断都基于此时读取到的权限