MySQL是典型的C/S架構(gòu)
(客戶端/服務器架構(gòu)),客戶端進程向服務端進程發(fā)送一段文本(MySQL指令),服務器進程進行語句處理然后返回執(zhí)行結(jié)果。
問題來了。服務器進程對客戶端發(fā)送的請求究竟做了什么處理呢?本文以查詢請求為例,講解MySQL服務器進程的處理流程。
如下圖所示,服務器進程在處理客戶端請求的時候,大致需要進行3個步驟:
- 處理連接
- 解析與優(yōu)化
- 存儲引擎
接下來我們來詳細了解一下這3步具體都做了什么。
1. 處理連接
客戶端向服務器發(fā)送請求并最終收到響應,本質(zhì)上是一個進程間通信的過程。
MySQL有專門用于處理連接的模塊——連接器。
1.1 客戶端和服務端的通信方式
1.1.1 TCP/IP協(xié)議
TCP/IP
協(xié)議是MySQL客戶端和服務器最常用的通信方式。
我們平時所說的MySQL服務器默認監(jiān)聽的端口是3306
,這句話的前提是客戶端進程和服務器進程使用的是TCP/IP
協(xié)議進行通信。
我們在使用mysql
命令啟動客戶端程序時,只要在-h
參數(shù)后跟隨IP地址作為服務器進程所在的主機地址,那么通訊方式便是TCP/IP
協(xié)議。
如果客戶端進程和服務器進程位于同一臺主機,且要使用
TCP/IP
協(xié)議進行通信,則IP地址需要指定為127.0.0.1,而不能使用localhost
1.1.2 UNIX域套接字
如果客戶端進程和服務器進程都位于類UNIX操作系統(tǒng)(MacOS、Centos、Ubuntu等)的主機之上,并且在啟動客戶端程序時沒有指定主機名,或者指定的主機名為localhost
,又或者指定了--protocol=socket
的啟動參數(shù),那么客戶端進程和服務器進程就會使用UNIX域套接字
進行進程間通信。
MySQL服務器進程默認監(jiān)聽的UNIX域套接字
文件為/temp/mysql.sock
,客戶端進程啟動時也默認會連接到這個UNIX域套接字文件之上。
如果不明白
UNIX域套接字
到底是什么也沒關系,只要知道這是進程之間的一種通訊方式就可以了,這里提及的主要目的是希望讀者知曉MySQL客戶端和進程通訊方式不止于TCP/IP
協(xié)議
1.1.3 命名管道和共享內(nèi)存
如果你的MySQL是安裝在Windows主機之上,客戶端和服務器進程可以使用命名管道和共享內(nèi)存的方式進行通信。
不過使用這些通信方式需要在服務端和客戶端啟動時添加一些啟動參數(shù)。
- 使用命名管道進行通信。需要在啟動服務器時添加
--enable-named-pipe
參數(shù),同時在啟動客戶端進程時添加--pipe
或者--protocol=pipe
參數(shù) - 使用共享內(nèi)存進行通信。需要在啟動服務器時添加
--shared-memory
參數(shù),啟動成功后,共享內(nèi)存便成為本地客戶端程序的默認連接方式;也可以在啟動客戶端進程的命令中加上--protocol=memory
參數(shù)明確指定使用共享內(nèi)存進行通信
如果不明白命名管道和共享內(nèi)存到底是什么沒關系,只要知道這是進程之間的一種通訊方式就可以了,這里提及的主要目的是希望讀者知曉MySQL客戶端和進程通訊方式不止于
TCP/IP
協(xié)議
1.2 權限驗證
確認通信方式并且成功建立連接之后,連接器就要開始驗證你的身份了,使用的信息就是你的用戶名和密碼。
- 如果用戶名或者密碼錯誤,客戶端連接會立即斷開
- 如果用戶名密碼認證通過,連接器會到權限表里面查出當前登陸用戶擁有的權限。之后這個連接里面的權限判斷邏輯,都將依賴于此時讀到的權限。
1.3 查看MySQL連接
每當一個客戶端連接到服務端時,服務端進程都會創(chuàng)建一個單獨的線程來處理當前客戶端的交互操作。
那么如何查看MySQL當前所有的連接?
mysql> show global status like 'Thread%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 0 |
| Threads_connected | 1 |
| Threads_created | 1 |
| Threads_running | 1 |
+-------------------+-------+
各字段含義如下表
字段 | 含義 |
---|---|
Threads_cached | 緩存中的線程連接數(shù) |
Threads_connected | 當前打開的連接數(shù) |
Threads_created | 為處理連接創(chuàng)建的線程數(shù) |
Threads_running | 非睡眠狀態(tài)的連接數(shù),通常指并發(fā)連接數(shù) |
建立連接之后,除非客戶端主動斷開連接,否則服務器會等待客戶端發(fā)送請求。但是線程的創(chuàng)建和保持是需要消耗服務器資源的,因此服務器會把長時間不活動的客戶端連接斷開。
有2個參數(shù)控制這個自動斷開連接的行為,每個參數(shù)都默認為28800秒,8小時。
-- 非交互式超時時間,如JDBC連接
mysql> show global variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 28800 |
+---------------+-------+
-- 交互式超時時間,如數(shù)據(jù)庫查看工具Navicat等
mysql> show global variables like 'interactive_timeout';
+---------------------+-------+
| Variable_name | Value |
+---------------------+-------+
| interactive_timeout | 28800 |
+---------------------+-------+
既然連接消耗資源,那是不是MySQL的最大連接數(shù)也有默認限制呢?沒錯!默認最大連接數(shù)為151。
mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
題外話:細心的讀者可能會發(fā)現(xiàn)MySQL某些查詢語句帶有
global
關鍵字,這個關鍵字有什么含義呢?
MySQL的系統(tǒng)變量有兩個作用范圍(不區(qū)分大小寫),分別是
GLOBAL
(全局范圍):變量的設置影響服務器和所有客戶端SESSION
(會話范圍):變量的設置僅影響當前連接(會話)
但是并非每個參數(shù)都具有兩個作用范圍,比如允許同時連接到服務器的客戶端的數(shù)量max_connections
就只有全局級別。
當沒有帶作用范圍關鍵字時,默認是SESSION
級別,包括查詢和修改操作。
比如修改一個參數(shù)之后,在當前窗口生效了,但是在其他窗口卻沒有生效
show VARIABLES like 'autocommit';
set autocommit = on;
因此,如果只是臨時修改,請使用SESSION
級別,如果需要當前設置在其他會話中生效,需要使用GLOBAL
關鍵字。
到此為止,服務器進程已經(jīng)和客戶端進程建立了連接,下一步將處理客戶端傳來的請求了。
-
服務器
+關注
關注
12文章
9024瀏覽量
85186 -
TCP
+關注
關注
8文章
1351瀏覽量
78989 -
MySQL
+關注
關注
1文章
802瀏覽量
26445 -
服務端
+關注
關注
0文章
66瀏覽量
6987
發(fā)布評論請先 登錄
相關推薦
評論