淺談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:新增了
老大:但是咱們中間有一層自制的mysql proxy,這個驅動對他的支援是否友好?
運維A:這個...,得測試一下哈
….
baba,編譯php 5.5版本幾個小時過去了,終於搞定了,寫個小程式連線一下mysql proxy…
事情發生了,怎麼回事?怎麼連不上了?發生什麼事了?馬上打電話給mysql proxy開發小組諮詢一下為啥php 5.5版本連線不上mysql proxy?於是mysql proxy開發小組開始深入調研一下,原來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方面的相關細節有所幫助,祝玩得開心!