zoukankan      html  css  js  c++  java
  • 浅谈MySQL Capabilities --从调研PHP mysqlnd源码细节角度认识

    今天一起来研究下MySQL Capabilities,这个非常重要,如果大家有想法自己动手实现一个MySQL客户端或者Proxy工具,那么就得先了解一下这块,正好PHP 5.3以上版本由于官方为了规避许可协议和版权的问题而开发mysqlnd驱动(mysql native driver),而且据资料显示其性能比libmysql驱动要高不少,直接步入正题,在开始前,说明一下,以下的源码部分是来源于php 5.5.10版本。

    假如有这么一个场景:

    运维A:老大,最近调研发现php 5.5版本性能提升了不少,咱们的游戏web后台php版本要不要来一下?

    老大:新版本有啥优势啊?

    运维A:新增了mysqlnd这个牛逼的驱动,咱们编译代码再也不用记着打开libmysql选项了,减少工作量之余,关键是这个驱动比libmysql牛逼多了。

    老大:但是咱们中间有一层自制的mysql proxy,这个驱动对他的支持是否友好?

    运维A:这个...,得测试一下哈

    ….

    baba,编译php 5.5版本几个小时过去了,终于搞定了,写个小程序连接一下mysql proxy…

    事情发生了,怎么回事?怎么连不上了?发生什么事了?马上打电话给mysql proxy开发小组咨询一下为啥php 5.5版本连接不上mysql proxy?于是mysql proxy开发小组开始深入调研一下,原来proxy的Capabilities没设置好,顺手还研究了一下php mysqlnd的源码,发现原来真相在ext/mysqlnd/mysqlnd_enum_n_def.h的第105行的MYSQLND_CAPABILITIES宏,原来mysqlnd默认开启的标志还真不少,而咱的proxy实现还没支持这么多标志,所以只能断开链接了

    105 #define MYSQLND_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | 
    
    106                 CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | 
    
    107                 CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS | CLIENT_LOCAL_FILES | CLIENT_PLUGIN_AUTH)

    接下来再看看这个标志是在哪里调用,发现原来隐藏在ext/mysqlnd/mysqlnd.c的第713 

    705 /* {{{ mysqlnd_conn_data::get_updated_connect_flags */
    
     706 static unsigned int                                                                                                                                              
    
     707 MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags)(MYSQLND_CONN_DATA * conn, unsigned int mysql_flags TSRMLS_DC)
    
     708 {                                
    
     709     MYSQLND_NET * net = conn->net;
    
     710                                 
    
     711     DBG_ENTER("mysqlnd_conn_data::get_updated_connect_flags");
    
     712     /* we allow load data local infile by default */
    
     713     mysql_flags |= MYSQLND_CAPABILITIES;
    
     714                                 
    
     715     mysql_flags |= conn->options->flags; /* use the flags from set_client_option() */
    
     716                                 
    
     717     if (PG(open_basedir) && strlen(PG(open_basedir))) {
    
     718         mysql_flags ^= CLIENT_LOCAL_FILES;
    
     719     }                           
    
     720                   
    
     721 #ifndef MYSQLND_COMPRESSION_ENABLED
    
     722     if (mysql_flags & CLIENT_COMPRESS) {
    
     723         mysql_flags &= ~CLIENT_COMPRESS;
    
     724     }                           
    
     725 #else             
    
     726     if (net && net->data->options.flags & MYSQLND_NET_FLAG_USE_COMPRESSION) {
    
     727         mysql_flags |= CLIENT_COMPRESS;
    
     728     }                           
    
     729 #endif            
    
     730 #ifndef MYSQLND_SSL_SUPPORTED    
    
     731     if (mysql_flags & CLIENT_SSL) {
    
     732         mysql_flags &= ~CLIENT_SSL;
    
     733     }             
    
     734 #else             
    
     735     if (net && (net->data->options.ssl_key || net->data->options.ssl_cert ||
    
     736         net->data->options.ssl_ca || net->data->options.ssl_capath || net->data->options.ssl_cipher))
    
     737     {                      
    
     738         mysql_flags |= CLIENT_SSL;
    
     739     }                      
    
     740 #endif                     
    
     741                            
    
     742     DBG_RETURN(mysql_flags);                                                                                                                                     
    
     743 }                          
    
     744 /* }}} */

    get_updated_connect_flags又是在哪里调用呢?再调研一下,发现是在ext/mysqlnd/mysqlnd.c的第956

    828 /* {{{ mysqlnd_conn_data::connect */
    
     829 static enum_func_status   
    
     830 MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
    
     831                          const char *host, const char *user,
    
     832                          const char *passwd, unsigned int passwd_len,
    
     833                          const char *db, unsigned int db_len,
    
     834                          unsigned int port,
    
     835                          const char *socket_or_pipe,
    
     836                          unsigned int mysql_flags
    
     837                          TSRMLS_DC)
    
     838 {
    
    … ...
    
     956     mysql_flags = conn->m->get_updated_connect_flags(conn, mysql_flags TSRMLS_CC);
    
     957     
    
     958     if (FAIL == conn->m->connect_handshake(conn, host, user, passwd, passwd_len, db, db_len, mysql_flags TSRMLS_CC)) {
    
     959         goto err;
    
     960     }

    而再找找connect,发生是在ext/mysqlnd/mysqlnd.c 的第1131行里调用,mysqlnd_connect看起来有点熟悉,没错这个就是官方开发的mysqlnd驱动,而大名顶顶的PDO正是调用这个来连接mysql,具体编译方式大家再google一下,这里就不展开了。

    1107 /* {{{ mysqlnd_connect */                                                                                                                                        
    
    1108 PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn_handle,
    
    1109                          const char * host, const char * user,
    
    1110                          const char * passwd, unsigned int passwd_len,
    
    1111                          const char * db, unsigned int db_len,
    
    1112                          unsigned int port,
    
    1113                          const char * socket_or_pipe,
    
    1114                          unsigned int mysql_flags
    
    1115                          TSRMLS_DC)
    
    1116 {                        
    
    1117     enum_func_status ret = FAIL;
    
    1118     zend_bool self_alloced = FALSE;
    
    1119                          
    
    1120     DBG_ENTER("mysqlnd_connect");
    
    1121     DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u", host?host:"", user?user:"", db?db:"", port, mysql_flags);
    
    1122                          
    
    1123     if (!conn_handle) { 
    
    1124         self_alloced = TRUE;
    
    1125         if (!(conn_handle = mysqlnd_init(FALSE))) {
    
    1126             /* OOM */   
    
    1127             DBG_RETURN(NULL);
    
    1128         }               
    
    1129     }                   
    
    1130                         
    
    1131     ret = conn_handle->m->connect(conn_handle, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags TSRMLS_CC);
    
     

    总结:

    php mysqlnd驱动源码可以学习到如何设计一个mysql客户端,并且在设计过程中如何设计MySQL Capabilities

    具体的MySQL Capabilities说明可详细阅读http://dev.mysql.com/doc/internals/en/capability-flags.html

    以上就是今天要分享的小细节,希望对大家理解MySQL Capabilities方面的相关细节有所帮助,祝玩得开心!


    如果文章对你有用,请支持我继续挖出更多的坑,世界因你存在而美!

  • 相关阅读:
    L1和L2正则
    Python基础(一)
    消息分发
    StringList 自定义快速排序
    Delphi Length函数
    接口的委托实现(通过接口)
    接口委托实现--通过类的对象
    排序
    Socket编程(摘抄)
    Delphi线程同步
  • 原文地址:https://www.cnblogs.com/lispking/p/3606107.html
Copyright © 2011-2022 走看看