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方面的相关细节有所帮助,祝玩得开心!


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

  • 相关阅读:
    Software Solutions CACHE COHERENCE AND THE MESI PROTOCOL
    CACHE COHERENCE AND THE MESI PROTOCOL
    Multiprocessor Operating System Design Considerations SYMMETRIC MULTIPROCESSORS
    Organization SYMMETRIC MULTIPROCESSORS
    PARALLEL PROCESSING
    1分钟内发送差评邮件
    Secure Digital
    SYMMETRIC MULTIPROCESSORS
    A Taxonomy of Parallel Processor Architectures
    parallelism
  • 原文地址:https://www.cnblogs.com/lispking/p/3606107.html
Copyright © 2011-2022 走看看