1. 程式人生 > 實用技巧 >MySQL 資料庫連線原理和效能優化

MySQL 資料庫連線原理和效能優化

常見的 MySQL 客戶端

MySQL 服務端啟動之後,就可以通過客戶端建立與服務端的連線,然後傳送查詢/更新請求了。

我們可以通過 MySQL 安裝目錄 bin 目錄下的 mysql 二進位制檔案在終端視窗通過命令列建立與 MySQL 服務端的連線,也可以通過圖形化客戶端軟體建立這種連線(比如 MySQL Workbench、Navicat For MySQL、DataGrip、TablePlus、Sequel Pro 等),此外,我們在 PHP、Go、Python、Java 這些後端程式語言中使用的資料庫 SDK 也是一種 MySQL 客戶端,只不過這些 SDK 對資料庫連線做了封裝而已。

以上都是日常開發過程中經常打交道的 MySQL 客戶端,這裡,為了更接近底層原理,我們使用 mysql

命令建立與服務端的連線。

mysql 命令解析

我們可以通過如下命令格式建立資料庫連線:

1
mysql -h主機名 -P埠號 -u使用者名稱 -p密碼

注:如果 MySQL 服務端監聽的埠號是預設的 3306 的話,可以省略埠號(如果想要使用其他埠號,可以在啟動服務端時通過命令列引數或者配置檔案指定)。

我們以預設的 root 使用者為例,在終端視窗通過如下命令即可建立與本地 MySQL 服務端的連線:

這裡我們通過 -h 指定 MySQL 服務端所在的主機 IP 地址,這裡是本地 IP 地址 127.0.0.1,通過 -u 指定使用者名稱是 root

,通過 -p 指定對應的密碼是 root

雖然可以通過這種方式比較便捷地指定密碼資訊,但是如果是連線到生產環境 MySQL 伺服器,則不建議這麼做,因為這樣會導致密碼的洩露,取而代之地,可以通過如下這種互動式方式輸入密碼發起連線請求:

這樣一來,輸入的密碼資訊就不可見了。

連線成功後,我們就可以通過這個互動式介面來操作 MySQL 資料庫了。在進行下一步操作之前,我們先來看看 MySQL 客戶端是如何建立與服務端的連線的。

資料庫連線過程

不管是 MySQL 服務端還是客戶端,本質上都是計算機的程序,所以這個連線過程和通過瀏覽器(HTTP 客戶端)請求指定網站(HTTP 服務端)連線建立過程並無二致,都是程序之間的通訊。只不過後者是 HTTP 請求,基於 HTTP 協議,而前者是 TCP 請求,基於 TCP 協議。

注:雖然 MySQL 也支援 TCP 請求之外的其他連線建立方式,比如 Unix 套接字,但是我們日常使用的通常都是基於 TCP 連線的,這裡就以此為例進行講解。

學院君在網路協議的傳輸層協議中已經介紹過 TCP 通訊的原理,既然是 TCP 請求,那麼通訊的雙方 —— MySQL 客戶端和服務端需要具備必要的程序資訊:源 IP 地址、源埠號、目標 IP 地址、目標埠號,這樣才能建立可靠連線,這裡的目標 IP 地址就是 MySQL 服務端所在的 IP 地址,上面的示例是 127.0.0.1,目標埠號就是 MySQL 服務端程序的埠號,預設是 3306

所以從這個角度來說,通過 mysql 命令建立與服務端的連線和通訊,必須指定服務端主機(IP 地址或者主機名)和埠號(預設是 3306,可以省略,但如果不是 3306,則必須指定)。

在完成經典的 TCP 握手後,服務端就要開始認證你的身份,這個時候用的就是你輸入的使用者名稱和密碼:

  • 如果使用者名稱或密碼不對,就會收到一個 Access denied for user 的錯誤,然後客戶端程式結束執行:
  • 如果使用者名稱密碼認證通過,聯結器會到許可權表裡面查出你擁有的許可權,之後,這個連線裡面的許可權判斷邏輯,都將依賴於此時讀到的許可權。這就意味著,一個使用者成功建立連線後,即使對這個使用者的許可權做了修改,也不會影響已經存在連線的許可權,只有新建的連線才會使用新的許可權設定。

資料庫連線狀態

連線完成後,如果你沒有後續的動作,這個連線就處於空閒狀態,你可以在 show processlist 命令中看到它:

其中的 Command 列顯示為 Sleep 的行,表示一個空閒連線。

客戶端如果太長時間沒動靜,聯結器就會自動將它斷開,這個時間是由引數 wait_timeout 控制的,預設值是 28800 秒(也就是 8 小時)。你可以通過 show global variables 命令檢視這個配置值:

你可以通過 MySQL 配置檔案修改這個預設配置(mysqld 分組下配置即可)。

如果連線被斷開之後,客戶端再次傳送請求的話,就會收到一個錯誤提醒:Lost connection to MySQL server during query

長連線與短連線

在 MySQL 資料庫中,還有長連線與短連線的概念:

  • 長連線是指連線成功後,如果客戶端持續有請求,則一直使用同一個連線,對應在 Web 應用中,就是後端程式與資料庫之間的連線建立之後,就會一直重用這個連線(為了提升資料庫併發性,可以建立一個數據庫連線池);
  • 短連線則是指每次執行完很少的幾次查詢就斷開連線,下次查詢再重新建立一個,對應在 Web 應用中,就是後端程式與資料庫建立連線,完成查詢/更新後,就斷開連線,下次操作資料庫再重連。

這個和 HTTP 長連線和短連線的概念很像,並且顯然,無論是 HTTP 還是 MySQL,使用長連線都能有效減少建立連線過程帶來的損耗,進而提升效能。

不過在 MySQL 中,使用長連線會有一定的副作用 —— 有些時候會導致 MySQL 佔用記憶體漲得特別快。這是因為 MySQL 在執行過程中臨時使用的記憶體是管理在連線物件裡面的,這些資源只有在連線斷開的時候才會釋放。對於這個問題,通常有兩種解決方案:

  • 定期斷開長連線:使用一段時間,或者程式裡判斷執行過一個佔用較大記憶體的查詢後,主動斷開連線;
  • 如果使用的是 MySQL 5.7 或者更高版本,可以在每次執行一個比較大的操作後,通過執行 mysql_reset_connection 來重新初始化連線資源。

關於 MySQL 客戶端與服務端的連線,以及連線狀態和型別我們就簡單介紹到這裡,下篇教程,我們更進一步,來探究一條 SQL 查詢語句在 MySQL 客戶端和服務端之間都經歷了哪些曼妙之旅,最後把查詢結果返回給客戶端的。