前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL8.0之Sending data和Sending to client的区别

MySQL8.0之Sending data和Sending to client的区别

作者头像
AsiaYe
发布2021-07-14 13:15:43
3.6K0
发布2021-07-14 13:15:43
举报
文章被收录于专栏:DBA随笔DBA随笔

//

MySQL8.0之Sending data和Sending to client的区别

//

日常的MySQL运维工作中,我们经常会使用到show processlist这样的语法,来查看当前数据库上面的连接情况。show processlist语法的返回过程中,经常会看到sending data和sending to client的状态。今天来看看这两个状态的区别。

首先查阅官方文档中的描述:(给出官网地址)

https://dev.mysql.com/doc/refman/8.0/en/general-thread-states.html

在MySQL中,将show processlist的结果状态分为8个大的类,分别是:

  • Thread Command Values
  • General Thread States
  • Replication Source Thread States
  • Replication I/O Thread States
  • Replication SQL Thread States
  • Replication Connection Thread States
  • NDB Cluster Thread States
  • Event Scheduler Thread States

首先我们需要知道,我们所讨论的这两种状态,是数据通用线程状态里面的。现在我们看看这两个状态的解释:

sending data(或者叫executing)状态

在 MySQL 8.0.17 之前:表示线程正在读取和处理 SELECT 语句的行,并将数据发送到客户端。由于在此状态期间发生的操作往往会执行大量磁盘访问(读取),因此它通常是给定查询生命周期中运行时间最长的状态。MySQL 8.0.17 及更高版本:此状态不再单独指示,而是

包含在 Executing 状态中。

从描述中不难看出来,Sending data这个状态,在后续的8.0.17版本之后,会自动并入Executing之中,它表示当前SQL查询已经进入了执行阶段,接下来要发送结果给客户端、然后继续执行语句。简单理解,就是Sending data状态,代表这个SQL处于执行阶段的任意时刻。即使在有锁等待的情况下,依旧会显示为Sending data。

8.0.19版本中的实验如下:

在会话1中执行:

代码语言:javascript
复制
[yeyz] 23:40:04> begin;
Query OK, 0 rows affected (0.00 sec)

[yeyz] 23:40:07> select * from a for update;
+------+------+
| f1   | f2   |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
|    4 |    4 |
|    5 |    5 |
|    6 |    6 |
+------+------+
6 rows in set (0.00 sec)

会话2中执行下面操作,并使用show processlist:

代码语言:javascript
复制
[yeyz] 23:23:38> begin;
Query OK, 0 rows affected (0.01 sec)

[yeyz] 23:35:18> select * from a lock in share mode;
+------+------+
| f1   | f2   |
+------+------+
|    1 |    1 |
|    2 |    2 |
|    3 |    3 |
|    4 |    4 |
|    5 |    5 |
|    6 |    6 |
+------+------+
6 rows in set (0.03 sec)

[yeyz] 23:35:31> show processlist;
+----------+----------------+--------------------+------+------------------+----------+---------------------------------------------------------------+----------------------------+
| Id       | User           | Host               | db   | Command          | Time     | State                                                         | Info                       |
+----------+----------------+--------------------+------+------------------+----------+---------------------------------------------------------------+----------------------------+
| 18050523 | mysqlha_common | xxx:51542          | yeyz | Query            |        0 | starting                                                      | show processlist           |
| 18050534 | mysqlha_common | xxx:56822          | yeyz | Query            |        6 | executing                                                     | select * from a for update |
+----------+----------------+--------------------+------+------------------+----------+---------------------------------------------------------------+----------------------------+
2 rows in set (0.01 sec)

可以看到,这个命令处于executing状态(如果是低版本的MySQL,会显示Sending data),但是很明显,会话2处于锁等待状态。但是给人的感觉像是在给客户端发送数据一样。

总结:Sending data状态或者Executing状态,代表这个语句正在执行,一旦执行完毕,进入数据发送阶段,就不再保持这个状态。

sending to client状态

服务器正在向客户端写入数据包。

这个状态要说清楚,必须引入MySQL的查询流程,MySQL的数据发送给客户端,是要经过3个过程的:

1、MySQL把数据写入net_buffer,写满net_buffer之后调用接口发送到本地网络棧;

net buffer的相关变量如下:

代码语言:javascript
复制
[yeyz] 23:47:31> show variables like '%net_bu%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| net_buffer_length | 16384 |
+-------------------+-------+
1 row in set (0.01 sec)

2、本地网络棧也叫socket send buffer,它的默认值保存在Linux操作系统下面的路径中:

代码语言:javascript
复制
[root@ ~]# cat /proc/sys/net/core/wmem_default
212992

客户端会请求本地网络棧的内容,将数据发送到客户端的socket receive buffer中

3、客户端去读取socket receive buffer中的内容,如果客户端接收得慢,会导致MySQL服务端由于结果发不出去,这个事务的执行时间变长

总结:

如果show processlist看到的State的值一直处于“Sending to client”,说明SQL这个语句已经执行完毕,而此时由于请求的数据太多,MySQL不停写入net buffer,而net buffer又不停的将数据写入服务端的网络棧,服务器端的网络栈(socket send buffer)被写满了,又没有被客户端读取并消化,这时读数据的流程就被MySQL暂停了。直到客户端完全读取了服务端网络棧的数据,这个状态才会消失。

一个比较好缓解上面问题的方案是增大net_buffer_length的值,让MySQL将查询到的所有数据都缓存在net buffer里面,由于SQL执行完毕,没有新的数据写入net buffer,net buffer慢慢的发送给socket send buffer,即使客户端读取的速度慢,但是由于没有新数据,这个Sending to Client的状态自然就消失了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-06-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA随笔 微信公众号,前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

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