mysql要先下服务端再下客户端吗(解读MySQL的客户端和服务端协议)
mysql要先下服务端再下客户端吗
解读MySQL的客户端和服务端协议如果需要从 MySQL 服务端获得很高的性能,最佳的方式就是花时间研究 MySQL 优化和执行查询的机制。一旦理解了这些,大部分的查询优化是有据可循的,从而使得整个查询优化的过程更有逻辑性。下图展示了 MySQL 执行查询的过程:
- 客户端将 SQL 语句发送到服务端。
- 服务端检查查询缓存。如果缓存中已有数据,则直接返回缓存结果;否则,将 SQL 语句传递给下一环节。
- 服务端解析、预处理和优化 SQL 语句后,传递到查询优化器中形成查询计划。
- 查询执行引擎通过调用存储引擎接口执行查询计划。
- 服务端将查询结果返回给客户端。
上述的几个步骤都有其复杂性,接下来几篇文章将详细讲述各个环节。查询优化过程尤其复杂,并且理解这一环节很重要。
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添加注释视图(mysql创建表添加字段注释的实现方法)
- mysql事件教程(关于MySQL报警的一次分析处理详解)
- mysql所有用户命令(MySQL用户管理与PostgreSQL用户管理的区别说明)
- mysql死锁情况(MySQL kill不掉线程的原因)
- mysql使用步骤(聊一聊MySQL角色Role功能)
- mysql锁机制图解(详解mysql 中的锁结构)
- mysql 高级查询语法(MySQL查询语句进阶知识集锦)
- mysql8.0.15安装详细教程(mysql8.0.11数据目录迁移的实现)
- 如何正常查看mysql存储数据文件(Mysql文件存储图文详解)
- mysql主从复制原理详解(详解MySQL kill 指令的执行原理)
- mysql记录binlog的方式(MySQL使用binlog日志做数据恢复的实现)
- mysql触发器怎么添加(MySQL触发器的使用场景及方法实例)
- mysql用户登录命令(mysql的登陆和退出命令格式)
- mysql统计函数详解(浅析MySQL的基数统计)
- mysql建立分区表指令(MySQL高级特性——数据表分区的概念及机制详解)
- mysql索引原理和优化(Mysql 索引该如何设计与优化)
- 2主力后腰缺阵 泰山队奇兵有望获重用,赛季0出场,迎来中超首秀(泰山队奇兵有望获重用)
- 三分71 生死战爆发 篮网旧将丁威迪今天成奇兵,助队赢球(三分71生死战爆发)
- 《红 雄安》系列广播剧第一集 水上奇兵雁翎队(雄安系列广播剧第一集)
- 小说 小伙穿越成刘备,用现代知识指挥作战,众谋士都看呆了(小伙穿越成刘备)
- 解析葡萄牙6-1瑞士 进攻多点开花,贡萨洛-拉莫斯一战成名(解析葡萄牙6-1瑞士)
- 这支 奇兵队 腕大 有范儿还各怀绝技,毒贩杀人犯见了都要仓皇而逃(这支奇兵队腕大)
热门推荐
- python字符串找一个最大字符(Python查找最长不包含重复字符的子字符串算法示例)
- sqlserver表空间占用率(SQL Server获取磁盘空间使用情况)
- opencv人脸识别实战(Python opencv实现人眼/人脸识别以及实时打码处理)
- sql server占cpu高
- docker怎么设置远程访问(Docker开启远程访问的实现方式)
- phpstudymysql数据库启动不了(phpstudy mysql启动不了的解决方法)
- 微信小程序计算器怎么用(微信小程序实现计算器功能)
- dedecms怎样查看网页源文件(dedecms批量更新静态时提示:没有该栏目数据 可能缓存的解决方法)
- linux解压zip文件的命令(Linux gzip 命令的使用)
- python爬虫开源代码(Python实现的文轩网爬虫完整示例)