Heim  >  Artikel  >  Datenbank  >  深度解析mysql登录原理_MySQL

深度解析mysql登录原理_MySQL

WBOY
WBOYOriginal
2016-05-27 13:46:321152Durchsuche

使用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登录原理_MySQL

MYSQL握手协议

 

TCP连接建立成功后,mysql客户端与mysql服务端开始进行通讯,进行mysql认证过程。(1)服务端首先会发一个握手包到客户端,(2)然后客户端向服务端发送认证信息(用户名,密码等),(3)服务端收到认证包后,会检查用户名与密码是否合法,并发送包告知客户端认证信息。如果合法,则登陆成功,否则,登陆失败。连接报错。有时候,我们通过show processlist看到User处于unauthenticated user ,这说明此时连接过程正处于第1步和第2步之间,服务端等待客户端发认证信息的过程中。

 

15922528 unauthenticated user   10.xx.2.74:53216 NULL   Connect NULL   Reading from net NULL

15923418 unauthenticated user   connecting host NULL   Connect NULL   login   NULL 

tcpdump抓包验证

 

下面我们通过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

-S 将tcp的序列号以绝对值形式输出,而不是相对值。 

-nn 不进行端口名称的转换。

-tttt 在每一行中输出由date处理的默认格式的时间戳。

-i eth0 指定监听的网络接口

host 10.bb.yy.104 and port 3306  设置监听10.bb.yy.104:3306的网络包

-c 100 表示监听100包就结束。

 

(2).在客户端上,利用mysql命令远程连接服务端10.bb.yy.104,

 

mysql –h10.bb.yy.104 –P3306 –uxxx –pxx

 

登陆成功后,然后直接执行exit,退出

 

(3)分析tcpdump抓取的网络包,重点分析建立TCP连接,MYSQL认证和TCP断开连接的过程。如下图,图中第1部分是TCP连接建立的过程,第2部分是MYSQL认证的过程,第3部分是登陆成功后,发送基本元数据信息的过程,第4部分是断开连接的过程。通过图中的标示,我们可以清晰的看到TCP建立连接的3次握手,MYSQL认证以及TCP断开连接的4次挥手过程。

深度解析mysql登录原理_MySQL

建立连接

 

这个过程主要体现在第一部分,客户端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 –uxxx –pxxx  [TCP通讯方式]

mysql  -uxxx –pxxx –S/usr/mysql/mysql.sock  [unix socket通信方式]

(2).监听socket是否与通信socket公用一个端口?

 

我们知道,服务端一直有一个监听socket在3306端口监听,等待新进来的客户请求,一旦一个请求过来,服务端会重新创建一个新的通信socket,这个新的socket专门用于与这个客户通信,而监听socket则继续监听。虽然是2个套接字,但监听socket和通信socket都是同一个端口,通过netstat可以确认这个问题。

 

(3).连接超时参数connect_timeout在何时作用?

 

这个参数实质就是在MYSQL认证过程起作用,如果在这个过程中,客户端超过connect_timeout时间仍然没有发送密码认证包过来,则会主动断开连接。

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:mysql事物_MySQLNächster Artikel:MySQL 清空慢查询文件_MySQL