加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MYSQL CLENT SERVER数据包传输及net packet buffer用途解析

发布时间:2022-03-29 09:12:31 所属栏目:MySql教程 来源:互联网
导读:水平有限再加上源码的复杂性,难免出现错误,请共同研究予以纠正 本文参考源码: Net_serv.cc(主要参考) Mysql.h.pp Mysql_socket.h Violite.h Viosocket.c Vio.c 参考书籍: 深入理解MYSQL核心技术 MYSQL核心内幕 internals-en MYSQL官方手册 LINUX系统编
      水平有限再加上源码的复杂性,难免出现错误,请共同研究予以纠正
本文参考源码:
Net_serv.cc(主要参考)
Mysql.h.pp
Mysql_socket.h
Violite.h
Viosocket.c
Vio.c
参考书籍:
深入理解MYSQL核心技术
MYSQL核心内幕
internals-en
MYSQL官方手册
LINUX系统编程手册
 
注意:
     1、本文将主要解析非压缩MYSQL NET包,而尽量不考虑压缩的MYSQL NET包来减小难度
     2、本文主要以TCP->IP->以太网为蓝本进行描述,不考虑其他协议如(UDP)
     3、本文主要以Net_serv.cc的my_net_write来描述写入socket阶段,而没有考虑net_write_command
        实际上net_write_command函数是client传递命令包的主要函数入口,调用的下层函数一致
    4、写入阶段可以达到net buffer满写入也可以调用net_flush()写入,但是这里无力研究net_flush()只研究满写入的情况
 
一、基本概念
在这之前我们必须明白如下的一些基本概念,否则不利于阅读
 
1、socket:是一种进程间通信的方式,可以用于多态计算机和本地两个进程进行通信,类似管道是双向
           通信的一种方式,在网络上主要通过绑定IP和端口和识别唯一的网络服务端,在本地通过绑
           定一个本地文件进行通信,它工作在LINUX 内核态。
2、通信协议:协议也就是客户端和服务端事先商量好的一种格式,如果格式不对则解包失败,比如TCP
                    协议格式如下,MYSQL有自己的通信协议。
   
3、MYSQL协议:MYSQL作为大型数据库系统,他有着自己的协议,至少包含如下一些数据包。
              1、握手阶段
                 --服务端到客户端 初始化握手包
                 --客户端到服务端 客户端认证包
                 --服务端到客户端 OK包、ERROR包
              2、连接建立阶段
                --客户端到服务端 命令(command)包
                --服务端到客户端 OK包、ERROR包、结果集包            
              其中结果集包包含:
              1、包头包
              2、FILED属性包
              3、EOF包
              4、行数据包        
              FILED属性包:为列属性每个列都会有一个
              行数据包:为返回数据每行一个包
              如果一个SELECT 返回 2行3列数据
              会包含3(列)+2(行)+1(包头包)+2(EOF包)个数据包
              由于MYSQL数据包的复杂性本文并不准备解析MYSQL协议各种包,可以参考:
             MYSQL核心内幕
             internals-en
            
4、MYSQL NET包:它是实际的传输包的大小,大小最大为16M-1,这是在源码中定义死了的,每个MYSQL NET包
               包含一个包头,至少包含4个字节(非压缩包,如果压缩包会多3个字节),如下:
               3 bytes:(压缩后)payload长度
               1 bytes:序号
         (压缩)3 bytes:压缩前payload长度
               其中payload就是实际数据
      
               为什么有一个序号呢?因为为了保证每个命令发送的包是有序的,比如一个结果
               集合包会包含多个包,而其中的行数据包(SERVER->CLIENT的时候每一行数据是一个MYSQL数据包)
               包很可能大于16M-1,那么我们就需要将整个结果集包分为多个MYSQL NET包进行传输,当到达
               client的时候保证他顺序。当然并不是每个MYSQL NET包都很大,比如一些MYSQL数据包如OK包,就很
               小,我们知道在以太网传输的最大帧为MTU 1500字节,那么可能出现一个以太网帧包含多个MYSQL NET
               包(如OK包),也可能一个MYSQL NET包在多个以太网帧中,同时可能出现一个MYSQL数据包在多个MYSQL
               NET包中,但是最小一个MYSQL NET包至少包含一个MYSQL数据包(如OK包),当然TCP
               注意当一个MYSQL数据包分为多个MYSQL NET包的时候其最后会紧跟一个长度为0作为结束的标识,源码中
               /* End of big multi-packet. */
                   if (!pkt_len)
                   goto end;
             我们约定它叫做MYSQL NET包    
5、NET结构体说明
 
   可以看到NET结构中封装了一个BUFFER,而这个BUFFER正是由参数net-buffer-length控制
    其大小不能超过参数max-allowed-packet大小的这个buffer,本文约定将它叫做net buffer。
   net-buffer-length 默认16K最大为1M
   max-allowed-packet 默认4M最大1G
   结构体还封装了2个unsigned int的变量write_timeout,read_timeout. 他们正是
net-wirte-timeout,net-read-timeout参数指定,用来表示在返回一个ETIMEDOUT错误前能够
KEEPLIVE最大的时间。
  设置超时的底层调用很有可能是
  ret= mysql_socket_setsockopt(vio->mysql_socket, SOL_SOCKET, optname,optval, sizeof(timeout));
  之类的调用   
  另外结构体还封装了retry_count这是在遇到EINTR错误的时候重试的次数由参数net-retry-count
控制,在后面将会讲述       
 
6、LINUX ETIMEDOUT、EINTR、EWOULDBLOCK、EAGAIN
  #define    ETIMEDOUT    110    /* Connection timed out */
  #define    EINTR         4    /* Interrupted system call */
  #define    EAGAIN        11    /* Try again */
  #define    EWOULDBLOCK    EAGAIN    /* Operation would block *
 
7、LINUX平台下MYSQL读取和写入scoket函数
位于Mysql_socket.h中
send(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
当然如果是WIN_32平台send和recv函数有底层封装。

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读