【轉載】MySQL客戶端伺服器協議

摩雲飛發表於2016-05-11

查詢的實行路徑:

      這個協議是半雙工的,這意味著 MySQL 伺服器在某個給定的時間,可以傳送或接收資料,但是不能同時傳送和接收。這也意味著沒有辦法截斷訊息。

      這種協議讓 MySQL 的溝通簡單而又快捷,但是它也有一些限制。其中一個就是無法進行流程控制,一旦一方傳送訊息,另一方在傳送回覆之前就必須提取完整的訊息。這像來回拋球的遊戲:在任意時刻,只有某一方有球,而且除非有球在手上,否則就不能把球拋回去(傳送訊息)。

      客戶端用一個資料包將查詢傳送到伺服器。這就是為什麼 max_packet_size 這個配置引數對於大查詢很重要的一個原因(如果查詢過大,那麼伺服器會拒絕接收資料並且丟擲一個錯誤)。一旦客戶端傳送了查詢,那就意味著“球”已經不在自己手中,唯一能做的事情就是等待結果。

      但是,伺服器傳送的響應由許多資料包組成。伺服器傳送響應的時候,客戶端必須接收完整的結果集。它不能只提取幾行資料後就要求伺服器停止傳送剩下的資料。如果客戶端只需要其中的幾行資料,要麼等待所有資料都傳送完畢後丟掉不用的資料,要麼就笨拙地斷開連線。這兩種辦法都不好,這就是為什麼 LIMIT 子句很重要的原因。

      還有另外一種理解方式,當客戶端從伺服器提取資料的時候,它認為所有資料都是從伺服器“”過來的,但實際情況是伺服器在產生這些資料的同時就把它們“”到客戶端。客戶端只需要接收推出來的資料,根本沒辦法告訴伺服器停止傳送資料。

      絕大多數連線 MySQL 的類庫,能讓你提取完整的結果,然後快取到記憶體中,或者只是提取需要的資料。預設的行為通常是提取所有資料後快取。這很重要,因為 MySQL 只有在所有資料被提取之後,才會釋放點所有的鎖和資源。查詢的狀態會是“傳送資料”。如果客戶端類庫一次性提取了所有的資料,那麼就可以減少伺服器所做的工作,讓伺服器可以儘可能快地完成所有的清理工作。

      大部分客戶端類庫可以讓使用者像直接從伺服器上提取資料一樣處理結果,但是它實際上只是在類庫的記憶體中處理資料。這種機制在大多數時候都工作良好,但是對於很龐大的結果集也許會需要很長的時間和很多記憶體。如果不快取資料,那麼就可以使用較少的記憶體,並且儘快開始工作。這麼做的缺點就是在應用程式和類庫互動的時候,伺服器端的鎖和資源都是被鎖定的。




相關文章