淺談MySQL Capabilities --從調研PHP mysqlnd源碼細節角度認識

今天一塊兒來研究下MySQL Capabilities,這個很是重要,若是你們有想法本身動手實現一個MySQL客戶端或者Proxy工具,那麼就得先了解一下這塊,正好PHP 5.3以上版本因爲官方爲了規避許可協議和版權的問題而開發mysqlnd驅動(mysql native driver),並且據資料顯示其性能比libmysql驅動要高很多,直接步入正題,在開始前,說明一下,如下的源碼部分是來源於php 5.5.10版本。php

假若有這麼一個場景:html

運維A:老大,最近調研發現php 5.5版本性能提高了很多,我們的遊戲web後臺php版本要不要來一下?mysql

老大:新版本有啥優點啊?web

運維A:新增了mysqlnd這個牛逼的驅動,我們編譯代碼不再用記着打開libmysql選項了,減小工做量之餘,關鍵是這個驅動比libmysql牛逼多了。sql

老大:可是我們中間有一層自制的mysql proxy,這個驅動對他的支持是否友好?小程序

運維A:這個...,得測試一下哈運維

….socket

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方面的相關細節有所幫助,祝玩得開心!

相關文章
相關標籤/搜索