天天看點

【轉載】MySQL用戶端伺服器協定

查詢的實行路徑:

【轉載】MySQL用戶端伺服器協定

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

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

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

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

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

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

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

繼續閱讀