HP层到MySQL层Phptosql组件层次结构如下图所示:ext/mysqli和ext/mysql是客户端的扩展程序库(库函数),分别是在客户端脚本级库中扩展。Mysqli库是mysql库的扩展版,扩展版增加了BindColumn绑定。PDO(PHPDataObject)是另一个面向数据对象的扩展库。这些扩展库直接面向程序员,其底层实现是mysql连接引擎(如mysqlnd、libmysql)(参考http://bbs.chinaunix.net/thread-3679393-1-1.html,http://博客.csdn.net/treesky/article/details/7286098)。mysqlnd和libmysql是PHP端(客户端)的数据库连接驱动引擎。libmysql是一个通用的数据库连接引擎,mysqlnd是专门为PHP开发的连接引擎,属于Zend。当PHP调用扩展库(ext/mysqli和ext/mysql)中的mysql_query()函数查询数据库时,Zend引擎会通过mysql(mysqlnd和libmysql)查询引擎向MySQL服务器发送查询请求。MySQL层的数据查询MySQL服务器端收到客户端的查询请求后,查询执行流程如上图所示:1.查询缓存,如果命中,直接返回结果集给客户端,否则走tostep22.对SQL语句依次进行解析、预处理、查询优化等操作,最终生成查询执行计划(select查询执行计划可以通过explainselect查看)3.查询执行引擎onMySQL服务器会根据查询执行计划调用存储引擎查询数据。当执行完最后一层关联的SQL语句时,会生成查询结果集4.查询结果集发送给客户端,返回有两种方式:MySQL服务器缓存结果集或者做不缓存它,这是由参数SQL_BUFFER_RESULT设置的。并且,如果用户设置了SQL_CACHE,则此查询的结果集的副本将存储在查询缓存中(与步骤1相关)。SQL_CACHE参数的启示:将复杂(多关联)查询分解为多个简单查询,因为1)简单查询的缓存命中,2)复杂查询结果的缓存容易失败(关联的表太多)3)简单的查询锁持有率低MySQLServer到PHP层通信方式MySQLServer与客户端的通信采用“半双工通信”,即:客户端和服务器端只有一个可以读,另一个必须是写。优点:协议简单,客户端和服务端写权限互斥。缺点:不能进行流量控制。一端开始发送消息,另一端必须完全接受消息才能响应。启示:服务器查询后的结果集发送给客户端,客户端(客户端的查询引擎,如mysqlnd)必须完全接受。所以,如果只需要几行,记得在sql语句中加上limit,少用select*。结果集返回方式在结果集返回中,每一行记录通过client-server通信协议打包,然后交给下层tcp协议;当然在tcp层可以先缓存每一行记录的协议包,大包发送出去(对应用层透明)。MySQL服务器只有将所有结果集发送给客户端后,才能释放结果集占用的缓冲区。服务器端缓存方式客户端命令:mysql_unbuffer_query(),客户端sql驱动扩展(mysqlnd)中没有设置结果集缓存,所以f??ecth_array_xxx从结果集中读取一条记录时,需要从服务器端读取-边缓冲器。服务器端非缓存模式客户端命令:mysql_query(),在客户端sql驱动扩展(mysqlnd)中设置buffer来缓存服务器的结果集,所以当fecth_array_xxx从结果集中读取一条记录时,是直接从mysqlnd中获取扩展缓冲区中的行。总结如果结果集很大:server端的no-cache模式可以减轻server端的内存压力,但是在client端会占用内存。这仅取决于情况。PHP层到用户层在客户端,服务器端连接mysql扩展引擎(libmysql或mysqlnd),用户层通过扩展库(ext/mysql或ext/)与mysql引擎交互mysqli)(灵感是调用引擎的api读取结果集)。引擎libmysql和mysqlnd的机制不同。主要区别是mysqlnd是用php写的,编译成zend。而libmysql是一个通用库,zend连接数据库需要调用这个库。在这种情况下,mysqlnd和zend的内聚性更好,数据传输到用户层时,少了一份数据。具体结构差异如下图所示。图中,五角星代表缓存缓冲区。ext/mysqli和ext/mysql是客户端的扩展程序库(库函数):在客户端脚本层面,mysqlInd和libmysql是MySQLServer端的驱动程序。其中,libmysql是通用的MySQL查询驱动,mysqlnd是基于Zend引擎专门为PHP设置的SQL驱动,即mysqlnd的数据驱动动作需要与Zend和mysqlserver交互,而libmysql直接与mysql服务器。比较:ext/mysqli(或ext/mysql)和libmysql的数据库查询过程如下:1)mysqi向libmysql驱动发送查询请求2)libmysql执行请求,得到结果集存储在libmysql缓冲区中3)Mysqli申请内存:zval指定的buffer4)Mysqii将libmysql的结果集复制到zval指定的buffer中。ext/mysqli(或ext/mysql)和mysqlnd数据库查询的过程是:1)mysqi向mysqlnd驱动发送查询请求2)mysqlnd驱动通过zend引擎执行sql查询,结果集的每一行是由一个buffer存储(每个buffer是分散的)3)mysqlnd创建多个zvals并指向这些buffer例如:在ext/mysql&libmysql中,libmysql驱动执行SQL语句后,得到结果集Row1~Row3,并且然后ext/mysql将结果集复制到zendbuffer中,然后mysqli_fetch_xxx函数从这个区域的内存中读取结果集的内容。在ext/mysqli&mysqlInd中,mysqlnd驱动执行SQL语句得到结果集Row1~Row3,其中每一行直接由zend的一个buffer存储,由一个zval指向。客户端通过映射直接从该内存区读取结果来实现mysqli_fetch_xxx。总结mysqlnd和zend更有凝聚力。在sql查询驱动中,mysqlnd通过zend引擎访问数据库,并将结果直接存储在zend的buffer中。与libmysql驱动(独立于zend)相比,少了一份结果集Cache副本。参考《高性能MySQL》http://www.cnxct.com/libmysql-mysqlnd-which-is-best-and-what-about-mysqli-pdomysql-mysql/http://www.cnxct.com/wp-content/uploads/2012/12/andrey-mysqlnd.pdf版权声明:本文为博主(http://blog.csdn.net/ordeder)原创文章,未经博主许可不得转载。以上介绍了PHP查询数据到MySQL的过程概览,包括方面,希望对对MySql感兴趣的朋友有所帮助。电脑/手机提示:取消共享文档默认情况下,如果您在WindowsXP中打开我的电脑,您会在硬盘图标上方看到一些文件夹。这些是“共享文件夹”,这里是用户用来共享文件的每个文件夹。我们可以让这些文件夹在我的电脑中消失。原理很简单。随便打开注册表,找到如下位置:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\DelegateFolders,把{59031a47-3f72-44a7-89c5-5595fe6b30ee}键值删除,下次打开我的电脑后,这些烦人的文件夹将不复存在。
