使用mysql資料庫的第一步必然是建立連線登入,然後在上面執行sql命令。無論是通過mysql的客戶端,還是通過c-api,jdbc標準介面連線資料庫,這個過程一定少不了。今天我們聊一聊mysql登陸具體過程,裡面會涉及client與server的互動,並通過tcpdump抓包給大家展現這一過程。
tcp握手協議
遠端連線資料庫,mysql採用tcp協議通訊,第一步是建立連線,即tcp的3次握手。mysql server端有乙個監聽執行緒等待client請求,
client發起請求後,首先發乙個sync包到服務端,服務端發乙個ack包作為對客戶端sync包的響應,同時發乙個sync包到客戶端,
最後客戶端再發乙個ack包作為對服務端的響應。通過3次握手,tcp連線才算真正建立起來,這個時候mysql服務端會分配乙個連線供
客戶端使用。記住,tcp的3次握手都是由tcp的協議棧完成,應用程式並無感知。但是,到目前為止,整個mysql連線過程還只完成了
第一步--建立tcp連線。
下面附上tcp建立連線和斷開連線的原理圖。
mysql握手協議
tcp連線建立成功後,mysql客戶端與mysql服務端開始進行通訊,進行mysql認證過程。(1)服務端首先會發乙個握手包到客戶端,(2)然後客戶端向服務端傳送認證資訊(使用者名稱,密碼等),(3)服務端收到認證包後,會檢查使用者名稱與密碼是否合法,並傳送包告知客戶端認證資訊。如果合法,則登陸成功,否則,登陸失敗。連線報錯。有時候,我們通過show processlist看到user處於unauthenticated user ,這說明此時連線過程正處於第1步和第2步之間,服務端等待客戶端發認證資訊的過程中。
15922528 unauthenticated usertcpdump抓包驗證10.xx.2.74:53216
null connect null reading from net null
15923418 unauthenticated user connecting host null connect null login null
下面我們通過tcpdump抓網路包來驗證我們的原理。由於測試在生產環境中進行,為了避免生產網段的ip洩露,對ip作了替換,但不影響分析過程。具體而言,10.aa.zz.142.10556代表客戶端,10.bb.yy.104.3306代表伺服器端,3306是伺服器的監聽埠號。
(1).在客戶端上開啟tcpdump命令,監聽與10.bb.yy.104.3306的通訊網路包,命令如下:
tcpdump -s -nn -tttt -i eth0 host 10.bb.yy.104 and port 3306 and tcp -c 100(2).在客戶端上,利用mysql命令遠端連線服務端10.bb.yy.104,-s 將tcp的序列號以絕對值形式輸出,而不是相對值。
-nn 不進行埠名稱的轉換。
-tttt 在每一行中輸出由date處理的預設格式的時間戳。
-i eth0 指定監聽的網路介面
host
10.bb.yy.104
and port 3306 設定監聽10.bb.yy.104
:3306的網路包
-c 100 表示監聽100包就結束。
mysql –h10.bb.yy.104 –p3306 –u*** –p***登陸成功後,然後直接執行exit,退出
(3)分析tcpdump抓取的網路包,重點分析建立tcp連線,mysql認證和tcp斷開連線的過程。如下圖,圖中第1部分是tcp連線建立的過程,第2部分是mysql認證的過程,第3部分是登陸成功後,傳送基本元資料資訊的過程,第4部分是斷開連線的過程。通過圖中的標示,我們可以清晰的看到tcp建立連線的3次握手,mysql認證以及tcp斷開連線的4次揮手過程。
建立連線
這個過程主要體現在第一部分,客戶端10.aa.zz.142.10556,首先發乙個編號為1491894492的syn包,服務端收到後,傳送了1491894492+1的ack包,並傳送了乙個2727774925的syn包,最後客戶端再傳送乙個2727774925+1的包進行應答。
mysql認證
這個過程主要體現在第二部分,服務端10.bb.yy.104:3306首先發乙個認證包給客戶端,然後客戶端再傳送包含使用者密碼的認證包給伺服器,驗證成功後,服務端最後給客戶端乙個應答,那麼整個認證過程就結束了,至於第3部分是服務端與客戶端相互傳送的一些元資料資訊,比如版本資訊之類的。
斷開連線
這個過程主要體現在第四部分,客戶端發起exit命令時,開始觸發這個動作。客戶端首先發乙個編號為1491894724的fin包,然後伺服器傳送乙個1491894724+1的ack包作為應答,並傳送乙個編號為2727775120的fin包,最後客戶端傳送2727775120+1作為應答,整個過程結束。
資料報標記解析
s=syn 發起連線標誌,一般用於建立tcp連線
p=push 傳送資料標誌,一般用於傳輸資料
f=fin 關閉連線標誌,一般用於關閉tcp連線
ack 表示應答包
rst= reset 異常關閉連線
.表示沒有任何標誌
原始碼實現
用於mysql認證**主要集中在函式native_password_authenticate中,具體呼叫層次為:login_connection->check_connection
->acl_authenticate->
do_auth_once->native_password_authenticate,函式邏輯很簡單,就是呼叫write_packet往客戶端發乙個認證包,然後呼叫read_packet等待客戶端返回包含使用者名稱、密碼等資訊的包,最後解析包中的資訊進行密碼驗證,成功後,會在呼叫protocol::send_ok發乙個認證成功網路包,這個過程可以在圖中的第二步全部體現。底層socket通訊**主要集中在sql/net_serv.cc中,具體而言讀採用介面my_net_read,寫採用介面my_net_write。 問題
(1).unix socket方式登陸與tcp方式登陸有什麼區別和聯絡?
unix socket是實現程序間通訊的一種方式,mysql支援利用unix socket來實現客戶端-服務端的通訊,但要求客戶端和服務端在同一臺機器上。對於unix socket而言,同樣也是一種套接字,監聽執行緒會同時監聽tcp socket和unix socket,接受到請求然後處理,後續的處理邏輯都是一致的,只不過底層通訊方式不一樣罷了。
mysql -h127.0.0.1 –p3306 –u*** –p*** [(2).tcp通訊方式
]mysql
-u*** –p*** –s/usr/mysql/mysql.sock [
unix socket通訊方式
]
監聽socket是否與通訊socket公用乙個埠?
我們知道,服務端一直有乙個監聽socket在3306埠監聽,等待新進來的客戶請求,一旦乙個請求過來,服務端會重新建立乙個新的通訊socket,這個新的socket專門用於與這個客戶通訊,而監聽socket則繼續監聽。雖然是2個套接字,但監聽socket和通訊socket都是同乙個埠,通過netstat可以確認這個問題。
(3).連線超時引數connect_timeout在何時作用?
這個引數實質就是在mysql認證過程起作用,如果在這個過程中,客戶端超過connect_timeout時間仍然沒有傳送密碼認證包過來,則會主動斷開連線。
參考文件
spring mvc 原理深度解析
概要 spring mvc 設計思想與體系結構組成 mvc 執行流程解析 註解配置 jsp 執行過程回顧 spring mvc執行流程解析 mvc 體系結構 流程說明 請求servlet 處理業務邏輯 設定業務model forward jsp servlet jsp servlet 解析封裝htm...
深度解析 Condition實現原理
condition指的就是conditionobject,是aqs的乙個內部類。conditionobject的原理是基於aqs的node內部類維護了兩個佇列,乙個等待佇列,乙個同步佇列 乙個是單向佇列,乙個是雙向佇列。如果某個執行緒呼叫了await方法之後,就會使當前執行緒進入到等待狀態,原理就是...
深度解析執行緒工作原理
1,執行緒的概念 乙個程式中的方法有幾條執行路徑,就有幾個執行緒 2,執行緒的建立 兩種方式 1,繼承thread class testthread extends thread 2,實現runnable介面,然後作為引數傳入到thread類的構造方法中 class testthread imple...