MySQL 连接管理
一、客户端连接线程
连接管理器为每个客户端连接分配一个线程,该线程用于处理身份验证和请求。连接结束时,如果高速缓存未满,这个线程不马上回收,而是被缓存。每次有连接请求的时候,会先查看线程缓存中是否有可用的线程,如果没有,才会创建新线程。
这种连接线程管理方式的缺点是,每个连接都要分配一个线程,资源开销大,性能消耗大。
企业版中提供了一个线程池插件,用来减少开销并提高性能。
1. 系统变量
(1)thread_cache_size
- 缓冲区保留的可重用线程数。0 表示禁用缓存
(2)thread_stack
-
线程栈大小。
当线程堆栈太小时,这将限制服务器可以处理的 SQL 语句的复杂性,存储过程的递归深度以及其他消耗内存的操作。
2. 状态变量
(1)Threads_cached
- 缓存中的线程数
(2)Threads_created
- 由于无法从缓存中获取线程而创建的线程数
二、连接数
1. 系统变量
(1)max_connections
-
最大连接数,默认是 151
组复制的内部会话与客户端连接分开处理,因此它们不计入 max_connections 限制,并且如果服务器达到此限制,也不会被拒绝。
(2)open_files_limit
- 操作系统的打开文件数量限制
2. 状态变量
(1)Connection_errors_max_connections
-
如果达到最大连接数,此状态变量将增加
这个状态变量的值还与其他变量有关,后续遇到再补充。
3. 查看连接线程
mysql> show processlist;
+----+-----------------+-----------------+--------------------+---------+--------+----
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------------+--------------------+---------+--------+----
| 5 | event_scheduler | localhost | NULL | Daemon | 173642 | Waiting on empty queue | NULL |
| 60 | root | localhost | NULL | Query | 0 | init | show processlist |
| 61 | root | 172.16.0.1:3189 | performance_schema | Sleep | 3070 | | NULL |
| 62 | root | 172.16.0.1:3190 | performance_schema | Sleep | 3055 | | NULL |
| 63 | root | 172.16.0.1:3486 | performance_schema | Sleep | 3055 | | NULL |
+----+-----------------+-----------------+--------------------+---------+--------+----
Note:MySQL 实际允许的连接数是 max_connections + 1 ,额外的那个连接是为管理员(需要 CONNECTION_ADMIN 权限)准备的。
4. 受影响因素
如果 RAM 充足,且每个连接的负载低,响应时间不高,Linux 至少支持 500 - 1000 个并发连接,最高 10000 个。
- 给定平台上线程库的质量
- 每个连接使用的 RAM 的大小
- 每个连接的负载
- 所需的响应时间
- 可用文件描述符的数量
三、连接管理(8.0 版本)
8.0 版本,服务器可以使用 TCP/IP 协议指定管理连接的接口。
管理连接的数量没有限制,但是需要 SERVICE_CONNECTION_ADMIN 权限。
管理连接接口有自己的配置选项,与主连接接口相对应。默认情况下,已启用加密连接,不需要特别指定。
1. 系统变量
[mysqld]
admin_address=127.0.0.1
admin_port=33064
(1)admin_address
- 指定 IP 地址
(2)admin_port
- 指定端口,默认是 33062
(3)create_admin_listener_thread
- 启动时可以选择管理接口是否具有自己的单独线程。默认为 OFF。
(4)连接加密
-
admin_tls_xxx、admin_ssl_xxx
与 tls_xxx、ssl_xxx 类似
-
admin_tls_version
TLS 规则,指定加密列表。空值,表示不使用加密连接
[mysqld] admin_tls_version=''加密连接可以通过 --admin-ssl 选项指定
2. 配置过程
-
编辑配置文件 /etc/my.cnf
[mysqld] # 连接管理 thread-cache-size = 9 thread-stack = 300K # default 287620 max_connections = 151 admin_address = 127.0.0.1 admin_port = 33062 #create_admin_listener_thread = on # 连接加密 admin_ssl_ca=ca.pem admin_ssl_cert =server-cert.pem admin_ssl_key =server-key.pem admin_tls_version =TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 -
验证连接
mysql -uroot -p -h 127.0.0.1 -P33062Note:虽然通过 33062 端口连接到服务器,但是服务器端的正常服务端口仍然是 3306,33062 只是用于管理连接的端口。
mysql> select @@port; +--------+ | @@port | +--------+ | 3306 | +--------+
四、DNS 查找和主机缓存
MySQL 服务器在内存中维护了一个主机缓存信息,包含客户端信息,如 IP 地址、主机名、错误信息,会被缓存起来。
主机缓存只用于非本地登录的 TCP 连接。
如果缓存已满,则服务器将丢弃最近最少使用的缓存条目,以便为新条目腾出空间。如果内存不足,可能导致连接错误。
1. 查看主机缓存
-
performance_schema.host_cache
mysql> select * from performance_schema.host_cache\G *************************** 1. row *************************** IP: 172.16.0.30 HOST: NULL HOST_VALIDATED: YES SUM_CONNECT_ERRORS: 0 COUNT_HOST_BLOCKED_ERRORS: 0 COUNT_NAMEINFO_TRANSIENT_ERRORS: 0 COUNT_NAMEINFO_PERMANENT_ERRORS: 1 COUNT_FORMAT_ERRORS: 0 COUNT_ADDRINFO_TRANSIENT_ERRORS: 0 COUNT_ADDRINFO_PERMANENT_ERRORS: 0 COUNT_FCRDNS_ERRORS: 0 COUNT_HOST_ACL_ERRORS: 0 COUNT_NO_AUTH_PLUGIN_ERRORS: 0 COUNT_AUTH_PLUGIN_ERRORS: 0 COUNT_HANDSHAKE_ERRORS: 0 COUNT_PROXY_USER_ERRORS: 0 COUNT_PROXY_USER_ACL_ERRORS: 0 COUNT_AUTHENTICATION_ERRORS: 0 COUNT_SSL_ERRORS: 0 COUNT_MAX_USER_CONNECTIONS_ERRORS: 0 COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS: 0 COUNT_DEFAULT_DATABASE_ERRORS: 0 COUNT_INIT_CONNECT_ERRORS: 0 COUNT_LOCAL_ERRORS: 0 COUNT_UNKNOWN_ERRORS: 0 FIRST_SEEN: 2021-03-04 14:22:45 LAST_SEEN: 2021-03-04 14:22:45 FIRST_ERROR_SEEN: 2021-03-04 14:22:45 LAST_ERROR_SEEN: 2021-03-04 14:22:45Note:因为没有为 172.16.0.30 配置本地 DNS 解析,所以最后两列有值。
2. 作用
-
通过缓存 IP 和主机名的映射,避免对每个客户端连接做 DNS 解析
主机缓存中的错误信息可以用来判断是否阻塞,如果某主机连续多次连接失败,服务器端会阻止该主机的连接。
3. 配置主机缓存
(1)系统变量
-
max_connect_errors
连续失败次数。
[mysqld] max_connect_errors=10000如果存在网络问题,增加此变量的值是没有好处的,所以如果发生阻塞,应该首先确认 TCP/IP 连接是否正常
-
host_cache_size
主机缓存大小,默认开启。
[mysqld] host_cache_size=200动态修改这个变量会清除主机缓存
-
skip_name_resolve
禁用 DNS 解析。
如果 DNS 速度很慢且有很多主机,可以通过此变量禁用 DNS 解析,或者增加主机缓存 host_cache_size
-
禁止 TCP/IP 连接,可以启动时指定 skip_networking
4. 刷新主机缓存
(1)什么时候需要刷新
- 当客户端主机 IP 地址变更时
- 因为连续连接失败导致主机连接受阻时
(2)刷新主机缓存的影响
- 会把性能表 host_cache 的内容删除,相当于清空主机缓存,并解除所有受阻主机
5. 解锁主机的方法
- 改变系统变量 host_cache_size
- truncate 性能表 host_cache
- 执行 FLUSH HOSTS 或 mysqladmin flush-hosts
- 还有一个临时方法,就是增加系统变量 max_connect_errors