diff --git a/docs/src/design/images/mysql-auth.png b/docs/src/design/images/mysql-auth.png new file mode 100644 index 0000000000000000000000000000000000000000..b3d5c48286c54bd4d2fdf195ffdbb4100e52f3cb Binary files /dev/null and b/docs/src/design/images/mysql-auth.png differ diff --git a/docs/src/design/images/mysql-command-packet.png b/docs/src/design/images/mysql-command-packet.png new file mode 100644 index 0000000000000000000000000000000000000000..f07daade25b6e0571a7015c9f7fe089a5dbea562 Binary files /dev/null and b/docs/src/design/images/mysql-command-packet.png differ diff --git a/docs/src/design/images/mysql-error-packet.png b/docs/src/design/images/mysql-error-packet.png new file mode 100644 index 0000000000000000000000000000000000000000..c170a5497c237e52b50e762a15879dc8f05f146c Binary files /dev/null and b/docs/src/design/images/mysql-error-packet.png differ diff --git a/docs/src/design/images/mysql-flow.png b/docs/src/design/images/mysql-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..70a74c544b9087b3275a1deebff68e180a238924 Binary files /dev/null and b/docs/src/design/images/mysql-flow.png differ diff --git a/docs/src/design/images/mysql-handshake.png b/docs/src/design/images/mysql-handshake.png new file mode 100644 index 0000000000000000000000000000000000000000..b8e03a97736bd5e1d25302dfc72c8194def85d81 Binary files /dev/null and b/docs/src/design/images/mysql-handshake.png differ diff --git a/docs/src/design/images/mysql-ok-eof-packet.png b/docs/src/design/images/mysql-ok-eof-packet.png new file mode 100644 index 0000000000000000000000000000000000000000..1765055d31516c1447376e60f671fede49d224b0 Binary files /dev/null and b/docs/src/design/images/mysql-ok-eof-packet.png differ diff --git a/docs/src/design/images/mysql-ok-packet.png b/docs/src/design/images/mysql-ok-packet.png new file mode 100644 index 0000000000000000000000000000000000000000..1765055d31516c1447376e60f671fede49d224b0 Binary files /dev/null and b/docs/src/design/images/mysql-ok-packet.png differ diff --git a/docs/src/design/images/mysql-packet-flow.png b/docs/src/design/images/mysql-packet-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..42ff49a48c6c5d24953cd19728591db016a3cf7d Binary files /dev/null and b/docs/src/design/images/mysql-packet-flow.png differ diff --git a/docs/src/design/images/mysql-result-set-packet.png b/docs/src/design/images/mysql-result-set-packet.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9d1aa8048990b3ae0364f62e09dfe49c29dc21 Binary files /dev/null and b/docs/src/design/images/mysql-result-set-packet.png differ diff --git a/docs/src/design/introduction.md b/docs/src/design/introduction.md index 9e7aa66e765aa0ded9137511e944e1ea3b359c34..fb926791417b27355d21968621fde628dec425ed 100644 --- a/docs/src/design/introduction.md +++ b/docs/src/design/introduction.md @@ -3,4 +3,5 @@ - [事务](./miniob-transaction.md) - [CLog](./miniob-clog.md) - [SQL Parser](./miniob-sql-parser.md) +- [MySQL Protocol](./miniob-mysql-protocol.md) - [Doxy文档](./doxy/html/index.html) \ No newline at end of file diff --git a/docs/src/design/miniob-mysql-protocol.md b/docs/src/design/miniob-mysql-protocol.md new file mode 100644 index 0000000000000000000000000000000000000000..5b5baa6f78b6077338d2801eed556ed4d3d10853 --- /dev/null +++ b/docs/src/design/miniob-mysql-protocol.md @@ -0,0 +1,84 @@ +> 本篇文档介绍MySQL的通讯流程以及MiniOB对它的支持与实现 + +# MiniOB 通讯协议简介 + +MiniOB 支持使用客户端/服务端模式,客户端与服务端需要通过通讯来交互。当前服务端支持普通的文本协议与MySQL协议。 +普通的文本协议非常简单,每个请求和应答都使用字符串来传递,字符串以'\0'字符结尾,因此文本协议不能支持二进制数据的传输。 +MySQL 是一个非常流行的开源数据库,它有非常丰富的周边生态工具,如果MiniOB可以支持MySQL协议,后续就可以逐步扩展支持这些工具。 + +# MySQL 通讯协议 + +MySQL 服务端与客户端交互的过程。 + +![mysql-flow](images/mysql-flow.png) + +1. 三次握手建立 TCP 连接。 +2. 建立 MySQL 连接,也就是认证阶段。 +服务端 -> 客户端:发送握手初始化包 (Handshake Initialization Packet)。 +客户端 -> 服务端:发送验证包 (Client Authentication Packet)。 +服务端 -> 客户端:认证结果消息。 +3. 认证通过之后,客户端开始与服务端之间交互,也就是命令执行阶段。 +客户端 -> 服务端:发送命令包 (Command Packet)。 +服务端 -> 客户端:发送回应包 (OK Packet, or Error Packet, or Result Set Packet)。 +4. 断开 MySQL 连接。 +客户端 -> 服务器:发送退出命令包。 +5. 四次握手断开 TCP 连接。 + +## MySQL Packet +MySQL 协议通过packet来交互。每个packet都包含一个packet header和packet payload。 +packet header包含payload的长度和当前消息包的sequence。sequence是从1开始,每发出一个消息包,sequence都会加1。 +每个消息包都由一些字段构成,字段的类型有很多种,主要有整形和字符串。每种类型又有多种编码方式,比如字符串有固定长度的、以'\0'结尾的和带长度编码的。这些可以参考 mysql_communicator.cpp::store_xxx 函数。 + +> 注意,MySQL协议中数字都是小端编码。而MiniOB没有对大小端做处理,所以当前只能运行在小端的机器上。 + +## 认证阶段 +完成MySQL客户端与MiniOB的建连。 +构造handshake包,解析验证包, 返回OK包,确保server与客户端的建连。 + +**握手包handshake格式** + +mysql-handshake + +在accept接收到新的连接时,server端需要先发起handshake握手包给客户端。 + +**认证报文** + +mysql-auth + +这里有两次hash加密,基于随机挑战码和密码加密后返回给server端。 + +MyqlCommunicator::init是在刚接收到新的客户端连接时的接口,它会构造一个握手包发给客户端。在第一次接收客户端数据时,即在MysqlCommunicator::read_event中,如果判断还没有做过鉴权,就会做一个特殊处理,判断是否可以认证通过。不过当前MiniOB不会真的做密码验证。如果已经做过鉴权,就会认为接收的数据包是一个普通的命令消息。在接收到客户端的认证报文后,需要返回OK包给客户端。 + +**OK包报文** + +mysql-ok-packet + +## 请求交互阶段 + +在完成鉴权后,客户端就可以发送普通的请求命令到服务端,比如 "select * from t;" 查询语句。 + +mysql-command-packet + +MiniOB 仅考虑支持普通的文本查询命令。普通的文本查询命令,包格式也符合MySQL Packet的要求。其payload的第一个字节是command,接着就是请求命令,也就是SQL语句。 + +SQL请求的返回数据类型比较丰富,有OK、Error、EOF和ResultSet。 +如果SQL请求不需要返回行数据,那直接返回处理结果即可,比如OK或者Error。 +如果需要返回行数据,比如 "select * from t;" 查询请求,需要通过ResultSet包来返回客户端这些数据。有时候为了表示没有更多的数据,需要返回一个EOF包。 + +**OK/EOF包** + +mysql-ok-eof-packet + +**Error包** + +mysql-error-packet + +**ResultSet** + +mysql-result-set-packet + +**抓包** + +抓包可以很清晰的看到整个流程。 + +mysql-packet-flow