如何理解PHP與MySQL通訊

如何理解PHP與MySQL通訊,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

網(wǎng)站建設(shè)公司,為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計(jì)及定制網(wǎng)站建設(shè)服務(wù),專注于成都定制網(wǎng)站,高端網(wǎng)頁制作,對(duì)成都房屋鑒定等多個(gè)行業(yè)擁有豐富的網(wǎng)站建設(shè)經(jīng)驗(yàn)的網(wǎng)站建設(shè)公司。專業(yè)網(wǎng)站設(shè)計(jì),網(wǎng)站優(yōu)化推廣哪家好,專業(yè)成都網(wǎng)站營銷優(yōu)化,H5建站,響應(yīng)式網(wǎng)站。

在我們的一款WebGame的生產(chǎn)環(huán)境中,一次無意的strace抓包時(shí),發(fā)現(xiàn)了php與mysql大量通訊的數(shù)據(jù)。這種情況,在游戲服務(wù)器剛啟動(dòng)時(shí),是正常的,但如果是運(yùn)行一段時(shí)間之后,出現(xiàn)大量SELECT的SQL查詢,絕對(duì)是有問題的,而且,所操作的數(shù)據(jù)庫并不是配置庫,那意味著,我們程序員的程序出現(xiàn)了違規(guī)的操作。具體結(jié)果大約如下:

如何理解PHP與MySQL通訊

如上圖所示,php持續(xù)接收讀取進(jìn)程內(nèi)描述符為3的響應(yīng)包數(shù)據(jù),描述符為3的為php與mysql建立的TCP通訊鏈接,這點(diǎn)也可以從313行的SELECT語句來確認(rèn)。(原始數(shù)據(jù)丟失了,我模仿了一條。所以是配置庫的SQL語句)

這是什么程序,想實(shí)現(xiàn)什么邏輯?為何要取這么多數(shù)據(jù)?

跟著這里的SELECT的sql語句,我定位到了相應(yīng)的程序段:

/*  **  業(yè)務(wù)邏輯的代碼  */  public function SItem($roleId,$baseId) {      //...      // ############寫出下面這種代碼的人都得死.##################      $this->dbrRole->select('*');      $this->dbrRole->from('role_items');      $this->dbrRole->where('role_id',$roleId);      $this->dbrRole->where('baseId',$baseId);      $result = $this->dbrRole->get()->row(); //看上去,這里好像正常,我們都以為框架會(huì)給我們只取一條。      //...  }

我們從代碼上來看,好像明白程序員想根據(jù)對(duì)應(yīng)的role_id到role_items表里取一條想符合的數(shù)據(jù),所以,他調(diào)用了row方法,來取一條。看上去,這里好像正常,我們都以為框架會(huì)給我們只取一條。但實(shí)際上,框架是如何處理的呢?

我們來看下框架的對(duì)應(yīng)row方法的實(shí)現(xiàn)過程。對(duì)了,我們是CodeIgniter框架的一個(gè)較老的版本。

/*  **  框架中,DB drive中,row相關(guān)方法的代碼  **  */ public function row($n = 0,$type = 'array'){      if(!is_numeric($n)){          if(! is_array($this->_rowData)){              $this->_rowData = $this->rowArray(0);          }          if(isset($this->_rowData[$n])){              return $this->_rowData[$n];          }          $n = 0;      }      return ($type == 'object') ? $this->rowObject($n) : $this->rowArray($n);  }   //繼續(xù)跟進(jìn)rowArray方法  public function rowArray($n = 0){      $result = $this->resultArray();      if(count($result) == 0){          return $result;      }       if($n != $this->_current && isset($result[$n])){          $this->_current = $n;      }       return $result[$this->_current];  }   //繼續(xù)跟進(jìn)resultArray方法 ###這個(gè)方法是重點(diǎn)###  public function resultArray(){      if(count($this->resultArray) > 0){          return $this->resultArray;      }       if(false === $this->resulter || 0 == $this->recordCount()){          return array();      }       $this->_dataSeek(0);      while($row = $this->_fetchAssoc()){          $this->resultArray[] = $row;    //###########這個(gè)數(shù)組每次都增加_fetchAssoc()結(jié)果的內(nèi)存大小數(shù)量#########################      }      return $this->resultArray;  }   //繼續(xù)跟進(jìn)_fetchAssoc方法  /*  ** 對(duì)應(yīng)driver的_fetchAssoc方法的代碼  */ protected function _fetchAssoc(){      return mysql_fetch_assoc($this->resulter);  }

我們可以看到CodeIgniter框架的resultArray方法使用mysql(我們的php調(diào)用mysql的api用的是mysql函數(shù),有點(diǎn)繞,后面解釋)的mysql_fetch_assoc函數(shù)對(duì)緩沖區(qū)的數(shù)據(jù)進(jìn)行遍歷轉(zhuǎn)換。將所有緩沖區(qū)的數(shù)據(jù)全部復(fù)制給$this->resultArray屬性,再判斷row方法中所需要的key的結(jié)果是否存在,再與返回的。

也就是說,框架層并沒有只從mysql server(潛意識(shí)上的mysql server)那邊取一條給我們調(diào)用者,而是取了所有結(jié)果,再返回一條。(先別噴,后面解釋) 當(dāng)然,CI這種做法,也不是錯(cuò)。但我覺得有更好的改進(jìn)方法。

這個(gè)問題,我們組的dietoad (征婚) 發(fā)現(xiàn)了這個(gè)問題,并給了修復(fù)方案。有些同學(xué)認(rèn)為,這是程序員的錯(cuò),程序員的SELECT語句沒有加limit來限制條數(shù)。這我絕對(duì)贊同,而且,覺得寫出這種代碼的人都得死。

  1. 業(yè)務(wù)層:為這種業(yè)務(wù)需求的SQL語句加上limit限制

  2. 框架層:框架對(duì)于這種需求,自動(dòng)控制,發(fā)現(xiàn)這種情況,直接返回1條

對(duì)于解決方案1,我寫了一個(gè)正則,匹配select()方法被調(diào)用之后,row()方法被調(diào)用之前,中間沒有使用limit()方法的所有代碼,結(jié)果,發(fā)現(xiàn)量并不小。后來,我們決定兩種方案同時(shí)實(shí)施,防止第二種出現(xiàn)漏掉的情況。

dietoad給出如下改進(jìn):

/*  **  //改進(jìn)為當(dāng)_rowData不存在時(shí),從_rowData的數(shù)量開始取,取小于$n條記錄,避免 上面 resultArray方法中從緩沖區(qū)取所有數(shù)據(jù),復(fù)制雙倍數(shù)據(jù),占用內(nèi)存的情況  */ public function row ($n = 0, $type = 'array')  {      if(isset($this->_rowData[$n]))      {          return $this->_rowData[$n];      }      if (! is_numeric($n))      {          return $this->rowObject($n);      }       $ln=count($this->_rowData);      //繼續(xù)上次位置      while($ln++<=$n&&$r=$this->_fetchAssoc())      {         $this->_rowData[]=$r;      }      //需要幾條就讀幾條      //防止記錄集為空?qǐng)?bào)warning      return isset($this->_rowData[$n])?$this->_rowData[$n]:array();  }

在今年的4月末,鄙人寫過另一篇關(guān)于CodeIgniter框架的設(shè)計(jì)缺陷問題,給我們游戲項(xiàng)目帶來較大的影響,后來提交到github issues,并沒得到回復(fù),想了想,雖然官方的2.1.3版本中,也存在這個(gè)小問題。不過我覺得,這就不提交了,或許,我們的做法也符合他們的設(shè)計(jì)初衷。不過,我們還是在我們的項(xiàng)目中改進(jìn)了。

如此改進(jìn)之后,我們使用php的memory_get_usage()函數(shù)觀察前后兩個(gè)row()方法的結(jié)果時(shí),果然發(fā)現(xiàn)內(nèi)存使用情況有較大改善(改善幅度取決于SELECT的返回?cái)?shù)據(jù)量)。

似乎,到這里就應(yīng)該結(jié)束了,問題就這么被發(fā)現(xiàn),被解決了。

但,我總覺得少了些什么呢?當(dāng)我再次strace抓包時(shí),發(fā)現(xiàn)仍然存在大量的數(shù)據(jù)通訊,就像文章開頭的那副截圖一模一樣。然而,這又是什么原因呢?

我順手寫了個(gè)內(nèi)存占用的測(cè)試代碼如下:

$db = mysql_connect('192.168.xx.xx','xxxx','xxxx');  $sql = 'SELECT * from items';  mysql_select_db('jv01',$db);  echo 'SELECT_DB: ',convert(memory_get_usage()),"\n";     //619.26 kb   $r = mysql_query($sql,$db);  echo 'QUERY_SQL: ',convert(memory_get_usage()),"\n";    //619.98 kb  ###什么?查詢完之后,內(nèi)存大小居然只增加了不到1k?我那個(gè)表可是幾十M的數(shù)據(jù)啊   //sleep(50);  // hold住進(jìn)程,別銷毀,留著看當(dāng)前進(jìn)程的內(nèi)存分配1  $arr = array();  while ($rs = mysql_fetch_assoc($r))  {      $arr[]=$rs;  }  echo 'FETCH_RS: ',convert(memory_get_usage()),"\n";    //27.11 mb  ###什么?剛剛不是只增加了1k嗎?這里的遍歷的結(jié)果集怎么突增幾十M啊?尼瑪這到底是什么情況?   unset($arr);  echo 'UNSET: ',convert(memory_get_usage()),"\n";    //620.12 kb  #### $arr z占了 幾十M   mysql_free_result($r);  echo 'FREE_R: ',convert(memory_get_usage()),"\n";    //620 kb    ### 結(jié)果集居然只有0.12 k?這不扯淡么? 莫非。。。莫非緩沖區(qū)的數(shù)據(jù)php統(tǒng)計(jì)不到?莫非不是調(diào)用zend 內(nèi)存申請(qǐng)函數(shù)來申請(qǐng)內(nèi)存的?    //sleep(50);  // hold住進(jìn)程,別銷毀,留著看當(dāng)前進(jìn)程的內(nèi)存分配2  function convert($size)  {   $unit=array('b','kb','mb','gb','tb','pb');   return @round($size/pow(1024,($i=floor(log($size,1024)))),2).' '.$unit[$i];  }  /*  //返回結(jié)果如下:  SELECT_DB: 619.26 kb  QUERY_SQL: 619.98 kb  FETCH_RS: 27.11 mb  UNSET: 620.12 kb  FREE_R: 620 kb  */

看到結(jié)果時(shí),我不禁XX一緊,什么?這你媽什么情況?查詢完之后,內(nèi)存大小居然只增加了不到1k?我那個(gè)表可是幾十M的數(shù)據(jù)???遍歷結(jié)果集之后,怎么突增幾十M啊?尼瑪這到底是什么情況?strace返回的大量數(shù)據(jù)到底存在哪的?算不算php進(jìn)程申請(qǐng)的?

后來,我再次執(zhí)行如上程序,再定時(shí)用free、/proc/PID/maps 之類系統(tǒng)工具,查看系統(tǒng)的內(nèi)存使用情況,確認(rèn)了當(dāng)前進(jìn)程的內(nèi)存占用確實(shí)存在。那么可能的情況就是memory_get_usage()函數(shù)并沒有獲取到 mysql_query之后的內(nèi)存占用情況。由于比較懷疑,末學(xué)跟進(jìn)了memory_get_usage()函數(shù)的源碼,該函數(shù)直接交給 zend_memory_usage函數(shù)處理。

//這個(gè)是php的memory_get_usage()函數(shù)的 相關(guān)代碼,見Zend_alloc.c  line:2640  ZEND_API size_t zend_memory_usage(int real_usage TSRMLS_DC)  {      if (real_usage) {          return AG(mm_heap)->real_size;      } else {          size_t usage = AG(mm_heap)->size;  #if ZEND_MM_CACHE          usage -= AG(mm_heap)->cached;  #endif         return usage;      }  }      //這個(gè)是Zend內(nèi)存分配函數(shù)的代碼  //Zend_alloc.c  line:2418  ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)  {      TSRMLS_FETCH();       if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {          return AG(mm_heap)->_malloc(size);      }      return _zend_mm_alloc_int(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);  }

php的內(nèi)存管理 (中文地址:php-zend的內(nèi)存管理中文版)這塊,對(duì)于末學(xué)來說,太復(fù)雜了,只是稍微看懂直接 返回了mm_heap結(jié)構(gòu)體的real_size/size的值。(兩篇都是鳥哥寫的,中文的地址也就是鳥哥博客最近一直打不開,抽風(fēng)得厲害)

那mysql_query的結(jié)果集,存在哪的呢?如何申請(qǐng)內(nèi)存的,莫非不是調(diào)用zend的_emalloc內(nèi)存分配函數(shù)的?這得先明確mysql客戶端類庫問題,也就是我們使用哪個(gè)類庫?libmysql還是mysqlnd,通過查看編譯參數(shù),發(fā)現(xiàn)(我的虛擬機(jī))是libmysql,編譯參數(shù)是這樣的

./configure'  '--prefix=/services/php_5.3.19' '--with-config-file-path=/services/php_5.3.19/etc' '--with-pdo-mysql=/usr/bin/mysql_config' '--with-mysql=/usr/bin/mysql_config' '--with-mysqli=/usr/bin/mysql_config' '--enable-bcmath' '--enable-fpm   //生產(chǎn)服務(wù)器如下:  ./configure'  '--prefix=/services/php' '--with-config-file-path=/services/php/etc' '--with-pdo-mysql=mysqlnd' '--with-mysql=mysqlnd' '--with-mysqli=mysqlnd' '--enable-bcmath' '--enable-fpm

有點(diǎn)亂:

mysql、mysqli、pdo-mysql、libmysql、mysqlnd 好多名詞,有點(diǎn)亂,沒關(guān)系,一張圖讓你清晰起來:

如何理解PHP與MySQL通訊

mysql、mysqli、pdo-mysql、libmysql、mysqlnd之間關(guān)系

mysqlnd跟libmysql一樣,都是直接與mysql server通訊的驅(qū)動(dòng)類庫。 而php程序員使用的mysql、mysqli、pdo-mysql是面向程序員調(diào)用的API接口。。

繼續(xù):

libmysql類庫是MYSQL官方提供的類庫,每次PHP編譯都是指定參數(shù)來確定mysql\mysqli\pdo-mysql所使用的連接驅(qū)動(dòng)是哪個(gè)。并且,前提你的得先裝好mysql的客戶端(libmysql類庫),以確保有l(wèi)ibmysqlclient.so ,

末學(xué)抱著試試看的心態(tài),心情沉重的打開了libmysql的源碼,終于在Safemalloc.c的line:120附近找到類似libmysqlclient申請(qǐng)內(nèi)存的代碼

//libmysql客戶端庫Safemalloc.c  line:120  /* Allocate some memory. */  void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags)  {    ...      /*      Test for memory limit overrun.      If compiled with DBUG, test for error injection. Described in my_sys.h.    */   if ((size + sf_malloc_cur_memory > sf_malloc_mem_limit)        IF_DBUG(|| my_malloc_error_inject))    {      IF_DBUG(if (my_malloc_error_inject)                errno= ENOMEM;              my_malloc_error_inject= 0);      irem= 0;    }    else   {      /* Allocate the physical memory */     irem= (struct st_irem *) malloc (ALIGN_SIZE(sizeof(struct st_irem)) +                       sf_malloc_prehunc +                       size + /* size requested */                      4 +    /* overrun mark */                      sf_malloc_endhunc);    //系統(tǒng)的內(nèi)存分配函數(shù) malloc    }    ...    }     //下面是mysqlnd驅(qū)動(dòng)的代碼,為了省的再弄一個(gè)代碼高亮的區(qū)塊,特意放一起了.  // Mysqlnd客戶端庫Mysqlnd_alloc.c line:77  /* {{{ _mysqlnd_emalloc */ void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)  {  ...          ret = _emalloc(REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);    //調(diào)用zend的內(nèi)存分配函數(shù) _emalloc  ...      if (ret && collect_memory_statistics) {          *(size_t *) ret = size;          MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);      }      TRACE_ALLOC_RETURN(FAKE_PTR(ret));  }  /* }}} */

也就是說,libmysql沒有調(diào)用zend的內(nèi)分分配函數(shù)_emalloc,就沒法將內(nèi)存的使用情況記錄到mm_heap結(jié)構(gòu)體中,也就是PHP的memory_get_usage()函數(shù)統(tǒng)計(jì)不到的原因。好了,雖然末學(xué)不是很能讀懂源碼,但似乎符合問題發(fā)生的現(xiàn)象了。

好像,末學(xué)又想到一個(gè)問題,如果libmysql保存的結(jié)果集所占用的內(nèi)存的話,那么php的配置文件中的memory_limit也就無法限制他的內(nèi)存使用情況了?也就是說,如果我們很理想的根據(jù)系統(tǒng)剩余內(nèi)存分配了若干個(gè)php-fpm進(jìn)程來啟動(dòng)運(yùn)行的話,如果發(fā)生這情況,將會(huì)出現(xiàn)內(nèi)存不夠用的情況,libmysql占用的內(nèi)存沒有被統(tǒng)計(jì)到。。。結(jié)果是顯然的,果然限制不了它。

如何理解PHP與MySQL通訊 
libmysql與mysqlnd跟memory_limit之間的關(guān)系

那mysqlnd可以嗎?mysqlnd的內(nèi)存分配是使用zend的_emalloc函數(shù)嗎?是的,沒錯(cuò)mysqlnd 是我們的大救星。Mysqlnd_alloc.c line:77里代碼中,明確看到了。各位SA在編譯php時(shí),一定要使用mysqlnd作為php連接mysql server的類庫驅(qū)動(dòng)哦。

Mysqlnd的好處可不止這么一點(diǎn)點(diǎn)啊。

內(nèi)存還是內(nèi)存:

末學(xué)苦于薄弱的英語,冒死翻過GFW,終于在“萬惡的資本主義”國家的網(wǎng)站上找到了這些資料,mysqlnd將比libmysql節(jié)省將近40%的內(nèi)存占用哦。如圖:

如何理解PHP與MySQL通訊

mysqlnd比libmysql節(jié)省40%的內(nèi)存占用

,而且,memory_limit參數(shù)可以管的了它哦&hellip;

速度,速度:

國外友人給了一份測(cè)試結(jié)果,比較的API是mysql\mysqli,比較的驅(qū)動(dòng)是libmysql\mysqlnd

  1. 使用mysqlnd驅(qū)動(dòng)的ext\mysqli接口速度最快

  2. 使用libmysql驅(qū)動(dòng)的ext\mysqli接口慢了6%

  3. 使用libmysql驅(qū)動(dòng)的ext\mysql接口慢了3%

并且給出了mysqli在兩個(gè)驅(qū)動(dòng)下的執(zhí)行時(shí)間:

如何理解PHP與MySQL通訊

mysqli_select_varchar_buffered

還有,還有哦&hellip;mysqlnd還支持各種debug調(diào)試哦,各種strace跟蹤哦&hellip;還支持&hellip;.算了,你自己下載mysqlnd相比libmysql的優(yōu)點(diǎn)看吧。末學(xué)可是搜了很久才搜到這個(gè)ppt。

推薦:

1,再推薦一片關(guān)于mysqlnd持久鏈接的文章:PHP 5.3: Persistent Connections with ext/mysqli

2,你的應(yīng)用的cache的存儲(chǔ)是程序員自己根據(jù)DB數(shù)據(jù)結(jié)果,查詢條件,hash取值,存到memcache中的嗎?想不想嘗試下自動(dòng)實(shí)現(xiàn)的?mysqlnd的插件可以嘗試下:PHP: Client side caching for all MySQL extensions ,支持memcached,apc,sqlit哦。

回到開始:

有人說,當(dāng)php調(diào)用mysql_query時(shí),mysql server會(huì)返回本次查詢的結(jié)果到php所在服務(wù)器的緩沖區(qū)中。當(dāng)程序調(diào)用mysql_fetch_assoc/mysql_fetch_row /mysql_fetch_array/mysql_fetch_object之類函數(shù)時(shí),都是調(diào)用php_mysql_fetch_hash函數(shù)去緩沖區(qū)讀取數(shù)據(jù)的。我要是用mysql_unbuffered_query()函數(shù)呢?讓結(jié)果集不直接在查詢之后返回,當(dāng)調(diào)用mysql_fetch_x函數(shù)時(shí),再拉回來呢? 這&hellip;你讓mysql server的緩沖區(qū)來存儲(chǔ)這些數(shù)據(jù)么?你以為客戶端就你自己么?其他的客戶端也要連的啊,尤其是php,如果用 mysql_unbuffered_query()函數(shù),他們都會(huì)將結(jié)果集放到mysql server的緩沖區(qū)的,mysql server的內(nèi)存占用豈不是成本增長(zhǎng)&hellip;你想讓DBA砍死你?
手冊(cè)上也說了,mysql_unbuffered_query返回的結(jié)果集之上不能使用 mysql_num_rows() 和 mysql_data_seek()。我?guī)缀鯖]用過這個(gè)函數(shù),這算非主流的函數(shù)么?

有人說我們方案1節(jié)省了從結(jié)果集取出,遍歷賦值給新數(shù)組的內(nèi)存占用,并沒有減少網(wǎng)絡(luò)數(shù)據(jù)的傳輸。沒錯(cuò),你說的對(duì),一點(diǎn)都沒錯(cuò)。也就是說,我們的解決方案2只能稍微緩解這種問題的負(fù)面效果,徹底解決的話,還得程序?qū)由先フ_的調(diào)用,取回該要的數(shù)據(jù)。(其實(shí),如果使用mysqlnd驅(qū)動(dòng)的話,我們的改動(dòng)基本沒有優(yōu)勢(shì),節(jié)省不了內(nèi)存。mysqlnd時(shí),結(jié)果集的讀取只是引用緩沖區(qū)的數(shù)據(jù)。libmysql的話,有明顯效果。)我更加鑒定的贊同的那句話“寫出這種代碼的人都得死”。不使用mysqlnd作為php連接驅(qū)動(dòng)的SA都是耍流氓。

結(jié)論:

api推薦mysqli,驅(qū)動(dòng)推薦mysqlnd.

溫故而知新?

在回家之后,末學(xué)刷了幾局《保衛(wèi)蘿卜》,除了幾個(gè)需要養(yǎng)成才解鎖的關(guān)卡之外,均可恥的”全清”+”金蘿卜”,玩著玩著,突然想起一件事情,就是末學(xué)在去年寫過一篇博客php5.3.8中編譯pdo_mysql的艱難歷程中, 之前運(yùn)維的編譯參數(shù)中,mysqli使用的是mysqlnd,而mysql使用的是libmysql,后來再裝的pdo-mysql也使用了 libmysql了&hellip;.3個(gè)api,指定兩個(gè)連接驅(qū)動(dòng),莫非上次的錯(cuò)誤是因?yàn)檫@個(gè)?而末學(xué)的編譯參數(shù)雖然巧合的解決了問題,當(dāng)初并沒有理解真正的原因?下周驗(yàn)證一下&hellip; [2012/12/15 23:31更新]

知恥而后勇?

今天剛寫完這篇學(xué)習(xí)筆記后,回家玩游戲時(shí),想起鳥哥曾提到過mysqlnd,再次回去看看,看鳥哥如何講解mysqlnd的,我理解的是否有誤,才發(fā)現(xiàn)鳥哥這里已經(jīng)有了個(gè)Ulf Wendel博客的鏈接,末學(xué)卻在網(wǎng)絡(luò)搜索N久才找到那篇文章,同時(shí),發(fā)現(xiàn)其blog上有大量mysqlnd的文章,還暗自偷笑,以為自己發(fā)現(xiàn)了大金礦,現(xiàn)在才發(fā)現(xiàn)&hellip;.哎,慚愧慚愧&hellip;[2012/12/15 23:58更新]

末學(xué)對(duì)于本次學(xué)習(xí)經(jīng)歷中遇到的知識(shí)點(diǎn),有大量的盲區(qū),將會(huì)在以后的時(shí)間里,慢慢摸索熟悉,也歡迎各位前輩的點(diǎn)撥。

好像末學(xué)的問題太多了。

關(guān)于如何理解PHP與MySQL通訊問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

網(wǎng)站標(biāo)題:如何理解PHP與MySQL通訊
本文鏈接:http://muchs.cn/article26/pippjg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計(jì)全網(wǎng)營銷推廣、網(wǎng)站導(dǎo)航、網(wǎng)站維護(hù)、軟件開發(fā)、移動(dòng)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)