解读 MySQL Client/Server Protocol: Connection & Replication(上)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 解读 MySQL Client/Server Protocol: Connection & Replication

解读 MySQL Client/Server Protocol: Connection & Replication

MySQL 客户端与服务器之间的通信基于特定的 TCP 协议,本文将会详解其中的 Connection 和 Replication 部分,这两个部分分别对应的是客户端与服务器建立连接、完成认证鉴权,以及客户端注册成为一个 slave 并获取 master 的 binlog 日志。

Connetcion Phase

MySQL 客户端想要与服务器进行通信,第一步就是需要成功建立连接,整个过程如下图所示:

connection-phase

1.client 发起一个 TCP 连接。2.server 响应一个 Initial Handshake Packet(初始化握手包),内容会包含一个默认的认证方式。3.这一步是可选的,双方建立 SSL 加密连接。4.client 回应 Handshake Response Packet,内容需要包括用户名和按照指定方式进行加密后的密码数据。5.server 响应 OK_Packet 确认认证成功,或者 ERR_Packet 表示认证失败并关闭连接。

Packet

一个 Packet 其实就是一个 TCP 包,所有包都有一个最基本的结构:

packet

如上图所示,所有包都可以看作由 header 和 body 两部分构成:第一部分 header 总共有 4 个字节,3 个字节用来标识 body 即 payload 的大小,1 个字节记录 sequence ID;第二部分 body 就是 payload 实际的负载数据。

由于 payload length 只有 3 个字节来记录,所以一个 packet 的 payload 的大小不能超过 2^24 = 16 MB ,示例:

packet-example

Packet :

当数据不超过 16 MB 时,准确来说是 payload 的大小不超过 2^24-1 Byte(三个字节所能表示的最大整数 0xFFFFFF),发送一个 packet 就够了。当数据大小超过了 16 MB 时,就需要把数据切分成多个 packet 传输。当数据 payload 的刚好是 2^24-1 Byte 时,一个包虽然足够了,但是为了表示数据传输完毕,仍然会多传一个 payload 为空的 packet 。


Sequence ID:包的序列号,从 0 开始递增。在一个完整的会话过程中,每个包的序列号依次加一,当开始一个新的会话时,序列号重新从 0 开始。例如:在建立连接的阶段,server 发送 Initial Handshake Packet( Sequence ID 为 0 ),client 回应 Handshake Response Packet( Sequence ID 为 1 ),server 再响应 OK_Packet 或者 ERR_Packet( Sequence ID 为 2 ),然后建立连接的阶段就结束了,再有后续的命令数据,包的 Sequence ID 就重新从 0 开始;在命令阶段(client 向 server 发送增删改查这些都属于命令阶段),一个命令的请求和响应就可以看作一个完整的会话过程,比如 client 先向 server 发送了一个查询请求,然后 server 对这个查询请求进行了响应,那么这一次会话就结束了,下一个命令就是新的会话,Sequence ID 也就重新从 0 开始递增。

Initial Handshake Packet

建立连接时,当客户端发起一个 TCP 连接后,MySQL 服务端就会回应一个 Initial Handshake Packet ,这个初始化握手包的数据格式如下图所示:

handshakeV10

这个图从上往下依次是:

1 个字节的整数,表示 handshake protocol 的版本,现在都是 10 。以 NUL(即一个字节 0x00)结尾的字符串,表示 MySQL 服务器的版本,例如 5.7.18-log4 个字节的整数,表示线程 id,也是这个连接的 id。8 个字节的字符串,auth-plugin-data-part-1 后续密码加密需要用到的随机数的前 8 位。1 个字节的填充位。2 个字节的整数,capability_flags_1Capabilities Flags 的低位 2 位字节。1 个字节的整数,表示服务器默认的字符编码格式,比如 utf8_general_ci2 个字节的整数,服务器的状态标识。2 个字节的整数,capability_flags_2Capabilities Flags 的高位 2 位字节。1 个字节的整数,如果服务器具有 CLIENT_PLUGIN_AUTH 的能力(其实就是能够进行客户端身份验证,基本都支持),那么传递的是 auth_plugin_data_len 即加密随机数的长度,否则传递的是 0x00 。10 个字节的填充位,全部是 0x00 。auth_plugin_data_len 指定长度的字符串,auth-plugin-data-part-2 加密随机数的后 13 位。如果服务器具有 CLIENT_PLUGIN_AUTH 的能力(其实就是能够进行客户端身份验证,基本都支持),那么传递的是 auth_plugin_name 即用户认证方式的名称。

对于 MySQL 5.x 版本,默认的用户身份认证方式叫做 mysql_native_password(对应上面的 auth_plugin_name),这种认证方式的算法是:

SHA1( password ) XOR SHA1( "20-bytes random data from server" <concat> SHA1( SHA1( password ) ) )

其中加密所需的 20 个字节的随机数就是 auth-plugin-data-part-1( 8 位数)和 auth-plugin-data-part-2( 13 位中的前 12 位数)组成。

注意:MySQL 使用的小端字节序。

看到这,你可能还对 Capabilities Flags 感到很困惑。

Capabilities Flags

Capabilities Flags 其实就是一个功能标志,用来表明服务端和客户端支持并希望使用哪些功能。为什么需要这个功能标志?因为首先 MySQL 有众多版本,每个版本可能支持的功能有区别,所以服务端需要表明它支持哪些功能;其次,对服务端来说,连接它的客户端可以是各种各样的,这些客户端希望使用哪些功能也是需要表明的。

Capabilities Flags 一般是 4 个字节的整数:

capability

如上图所示,每个功能都独占一个 bit 位。

Capabilities Flags 通常都是多个功能的组合表示,例如要表示 CLIENT_PROTOCOL_41CLIENT_PLUGIN_AUTHCLIENT_SECURE_CONNECTION 这三个功能,那么就把他们对应的 0x000002000x000800000x00008000 进行比特位或运算就能得到最终的值 0x00088200 也就是最终的 Capabilities Flags

根据 Capabilities Flags 判断是否支持某个功能,例如 Capabilities Flags 的值是 0x00088200,要判断它是否支持 CLIENT_SECURE_CONNECTION 的功能,则直接进行比特位与运算即可,即 Capabilities Flags & CLIENT_SECURE_CONNECTION == CLIENT_SECURE_CONNECTION

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1月前
|
SQL 关系型数据库 MySQL
|
2月前
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
2月前
|
关系型数据库 MySQL 数据库
docker启动mysql多实例连接报错Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’
docker启动mysql多实例连接报错Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’
178 0
|
3月前
|
数据采集 关系型数据库 MySQL
大数据-业务数据采集-FlinkCDC The MySQL server is not configured to use a ROW binlog_format
大数据-业务数据采集-FlinkCDC The MySQL server is not configured to use a ROW binlog_format
41 1
|
3月前
|
关系型数据库 MySQL Java
【Azure 应用服务】应用服务连接 Azure MySQL 一直失败,报错 Create connection error
【Azure 应用服务】应用服务连接 Azure MySQL 一直失败,报错 Create connection error
|
4月前
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
304 3
|
4月前
|
网络协议 关系型数据库 MySQL
启动mysql时的异常为:[ERROR] Can‘t start server: Bind on TCP/IP port. Got error: 98: Address already in used
启动mysql时的异常为:[ERROR] Can‘t start server: Bind on TCP/IP port. Got error: 98: Address already in used
|
4月前
|
安全 关系型数据库 MySQL
【Python】已解决:pymysql.err.OperationalError:(2003 “Can’t connect to MySQL server on ‘localhost’ ([WinEr
【Python】已解决:pymysql.err.OperationalError:(2003 “Can’t connect to MySQL server on ‘localhost’ ([WinEr
516 1
|
5月前
|
Web App开发 关系型数据库 MySQL
ucenter info:can not connect to MySQL server 报错!怎么解决
ucenter info:can not connect to MySQL server 报错!怎么解决
39 1
|
4月前
|
关系型数据库 MySQL 数据库
2003-Can`t connect to Mysql server on ‘154.8.165.152‘(10038)
2003-Can`t connect to Mysql server on ‘154.8.165.152‘(10038)