解读MySQL的客户端和服务端协议


Posted in MySQL onMay 10, 2021

如果需要从 MySQL 服务端获得很高的性能,最佳的方式就是花时间研究 MySQL 优化和执行查询的机制。一旦理解了这些,大部分的查询优化是有据可循的,从而使得整个查询优化的过程更有逻辑性。下图展示了 MySQL 执行查询的过程:

  1. 客户端将 SQL 语句发送到服务端。
  2. 服务端检查查询缓存。如果缓存中已有数据,则直接返回缓存结果;否则,将 SQL 语句传递给下一环节。
  3. 服务端解析、预处理和优化 SQL 语句后,传递到查询优化器中形成查询计划。
  4. 查询执行引擎通过调用存储引擎接口执行查询计划。
  5. 服务端将查询结果返回给客户端。

上述的几个步骤都有其复杂性,接下来几篇文章将详细讲述各个环节。查询优化过程尤其复杂,并且理解这一环节很重要。

解读MySQL的客户端和服务端协议

MySQL 客户端/服务端协议

虽然并不需要了解 MySQL 客户端/服务端协议的内部细节,但需要从高应用层面理解其是如何工作的。这个协议是半双工的,这意味着 MySQL 服务端不同同时发送和接收消息,以及不可以将消息拆成多条短消息发送。这种机制一方面使得 MySQL 的通信简单快速,另一方面也增加了一些限制。例如,这意味着无法进行流控,一旦一方发送了消息,另一方在响应前必须接收整个消息。这就好像来回打乒乓球一样,同一时间只有一方有球,只有接到了球才能把它打回去。

客户端通过单个数据包将查询语句发送给服务端,因此在存在大的查询语句时配置 max_allowed_packet 很重要。一旦客户端发送查询语句后,它就只能等待返回结果。

相反,服务端的响应通常是由多个数据包组成的。一旦服务端响应后,客户端必须获取整个结果集。客户端没法简单地获取几行然后告诉服务端不要再发送剩余的数据。如果客户端仅仅需要返回数据前面的几行,只能是等待服务端全部数据返回后再从中丢弃不需要的数据,或者是粗暴地断开连接。不管哪种方式都不是好的选择,因此合适的 LIMIT子句就显得十分重要。

大部分的 MySQL连接库支持获取整个结果集并在内存中缓存起来,或者是获取需要的数据行。默认的行为通常是获取整个结果集然后在内存缓存。知道这一点很重要,因为 MySQL 服务端在所有请求的数据行没返回前,不会释放这次查询的锁和资源。大部分客户端库会让你感觉数据是从服务端获取的,实际上这些数据可能仅仅是从缓存中读取的。这在大部分时间是没问题的,但对于耗时很久或占据很多内存的大数据量查询来说就不合适了。如果指定了不缓存查询结果,那么占用的内存会更小,并且可以更快地处理结果。缺点是这种方式会在查询时引起 服务端的锁和资源占用。

以 PHP 为例,以下是PHP常用的查询代码:

<?php
$link = mysql_connect('localhost', 'user', 'password');
$result = mysql_query('SELECT * FROM huge_table', $link);
while ($row = mysql_fetch_array($result)) {
  //处理数据结果
}

?>

这个代码看起来好像是只获取了需要的数据行。然而,这个查询通过 mysql_query 的调用后实际上将全部结果放到了内存中。而 while 循环实际上是对内存中的数据进行循环迭代。相反,如果使用 mysql_unbuffered_query 替代 mysql_query 的话,那就不会缓存结果。

<?php
$link = mysql_connect('localhost', 'user', 'password');
$result = mysql_unbuffered_query('SELECT * FROM huge_table', $link);
while ($row = mysql_fetch_array($result)) {
  //处理数据结果
}

?>

不同的编程语言处理缓存覆盖的方式不同。例如,Perl 的 DBD::mysql 驱动需要通过 mysql_use_result 属性指定 C 语音客户端库(默认是 mysql_buffer_result),示例如下:

#!/usr/bin/perl

use DBI;
my $dbn = DBI->connect('DBI:mysql:;host=localhost', 'user', 'password');
my $sth = $dbn->prepare('SELECT * FROM huge_table', {mysql_use_result => 1});
$sth->execute();
while (my $row = $sth->fetchrow_array()) {
	#处理数据结果
}

注意到 prepare 指定了使用结果而不是缓存结果。也可以通过在连接的时候指定,这会使得每次查询都不缓存。

my $dbn = DBI->connect('DBI:mysql:;mysql_use_result=1;host=localhost', 'user', 'password');

以上就是解读MySQL的客户端和服务端协议的详细内容,更多关于MySQL 客户端和服务端协议的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
仅用一句SQL更新整张表的涨跌幅、涨跌率的解决方案
May 06 MySQL
MySQL 存储过程的优缺点分析
May 20 MySQL
Mysql 用户权限管理实现
May 25 MySQL
Mysql 如何实现多张无关联表查询数据并分页
Jun 05 MySQL
MySQL中的隐藏列的具体查看
Sep 04 MySQL
Mysql忘记密码解决方法
Feb 12 MySQL
你真的会用Mysql的explain吗
Mar 31 MySQL
MySQL中IO问题的深入分析与优化
Apr 02 MySQL
MySQL事务操作的四大特性以及并发事务问题
Apr 12 MySQL
MySQL去除密码登录告警的方法
Apr 20 MySQL
MySQL详细讲解变量variables的用法
Jun 21 MySQL
MySQL 原理与优化之Limit 查询优化
Aug 14 MySQL
MySQL 重写查询语句的三种策略
May 10 #MySQL
详解MySQL 联合查询优化机制
mysql对于模糊查询like的一些汇总
May 09 #MySQL
MySQL Threads_running飙升与慢查询的相关问题解决
MySQL sql_mode的使用详解
May 08 #MySQL
MySQL 数据丢失排查案例
May 08 #MySQL
MySQL update set 和 and的区别
May 08 #MySQL
You might like
php缩小png图片不损失透明色的解决方法
2013/12/25 PHP
thinkPHP模板中for循环与switch语句用法示例
2016/11/30 PHP
Win7环境下Apache连接MySQL提示连接已重置的解决办法
2017/05/09 PHP
添加到收藏夹代码(兼容几乎所有的浏览器)
2007/01/09 Javascript
JQuery切换显示的效果实例代码
2013/02/27 Javascript
JS脚本defer的作用示例介绍
2014/01/02 Javascript
jQuery检测某个元素是否存在代码分享
2015/07/09 Javascript
jQuery实现自动与手动切换的滚动新闻特效代码分享
2015/08/27 Javascript
Bootstrap Modal遮罩弹出层代码分享
2016/11/21 Javascript
javascript实现将数字转成千分位的方法小结【5种方式】
2016/12/11 Javascript
JS中Array数组学习总结
2017/01/18 Javascript
canvas实现图像放大镜
2017/02/06 Javascript
微信小程序 页面跳转如何实现传值
2017/04/05 Javascript
Angular4实现图片上传预览路径不安全的问题解决
2017/12/25 Javascript
vue短信验证性能优化如何写入localstorage中
2018/04/25 Javascript
在Mac下彻底卸载node和npm的方法
2018/05/16 Javascript
ssh批量登录并执行命令的python实现代码
2012/05/25 Python
Pycharm学习教程(6) Pycharm作为Vim编辑器使用
2017/05/03 Python
numpy实现合并多维矩阵、list的扩展方法
2018/05/08 Python
set在python里的含义和用法
2019/06/24 Python
Django框架静态文件使用/中间件/禁用ip功能实例详解
2019/07/22 Python
50行Python代码实现视频中物体颜色识别和跟踪(必须以红色为例)
2019/11/20 Python
Django 解决distinct无法去除重复数据的问题
2020/05/20 Python
Java ExcutorService优雅关闭方式解析
2020/05/30 Python
python 密码学示例——凯撒密码的实现
2020/09/21 Python
小白教你PyCharm从下载到安装再到科学使用PyCharm2020最新激活码
2020/09/25 Python
PAUL HEWITT手表美国站:德国北部时尚生活配饰品牌,船锚元素
2017/11/18 全球购物
英国花园药房: The Garden Pharmacy
2017/12/28 全球购物
中层干部培训方案
2014/06/16 职场文书
在职党员进社区活动总结
2014/07/05 职场文书
2014单位领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
班子四风对照检查材料思想汇报
2014/09/29 职场文书
新党章的学习心得体会
2014/11/07 职场文书
2015年反腐倡廉工作总结
2015/05/14 职场文书
2016年中秋节慰问信
2015/12/01 职场文书
MySQL创建高性能索引的全步骤
2021/05/02 MySQL