찾다
데이터 베이스MySQL 튜토리얼mixer: mysql协议分析_MySQL

综述

要实现一个mysql proxy,首先需要做的就是理解并实现mysql通讯协议。这样才能通过proxy架起client到server之间的桥梁。

mixer的mysql协议实现主要参考mysql官方的internal manual,并用Wireshark同时进行验证。在实现的过程中,当然踩了很多坑,这里记录一下,算是对协议分析的一个总结。

需要注意的是,mixer并没有支持所有的mysql协议,譬如备份,存储过程等,主要在于精力有限,同时也为了实现简单。

数据类型

mysql协议只有两种基本的数据类型,integer和string。

integer

integer包括fixed length integer和length encoded integer两种,对于length encoded integer,用的地方比较多,这里详细说明一下。

对于一个integer,我们按照如下的方式将其转成length encoded integer:

  • 如果value
  • 如果value >= 251 同时 value
  • 如果value >= 2 ** 16 同时 value
  • 如果value >= 2 ** 24 同时 value

相应的,对于一个length encoded integer,我们可以通过判断第一个byte的值来转成相应的integer。

string

string包括:

  • fixed length string,固定长度string
  • null terminated string,以null结尾的string
  • variable length string,通过另一个值决定长度的string
  • length encoded string,通过起始length encoded integer决定长度的string
  • rest of packet string,从当前位置到包结尾的string

Packet

在mysql中,如果client或server要发送数据,它需要将数据按照(2 ** 24 - 1)拆分成packet,给每一个packet添加header,然后再以此发送。

对于一个packet,格式如下:

<code>3              payload length1              sequence idstring[len]    payload</code>

前面3个字节表明的是该packet的长度,每个packet最大不超过16MB。第4个字节表明的是该packet的序列号,从0开始,对于多个packet依次递增,等到下一个新的命令发送数据的时候才重置为0。前面4个字节组成了一个packet的header,后面就是该packet实际的数据。

因为一个packet最大能发送的数据位16MB,所以如果需要发送大于16MB的数据,就需要拆分成多个packet进行发送。

通常,server会回给client三种类型的packet

  • OK Packet,操作成功
  • Err Packet,操作失败
  • EOF Packet,end of file

登陆交互

要实现proxy,首先需要解决的就是登陆问题,包括proxy模拟server处理client的登陆,proxy模拟client登陆server。

为了简单,mixer只支持username + password的方式进行登陆,这应该也是最通用的登陆方式。同时不支持ssl以及compression。

一个完整的登陆流程如下:

  • client首先connect到server
  • server发送initial handshake packet,包括支持的capability,一个用于加密的随机salt等
  • client返回handshake结果,包括自己支持的capability,以及用salt加密的密码
  • server验证,如果成功,返回ok packet,否则返回err packet并关闭连接

这里,不得不说实现登陆协议的时候踩过的一个很大的坑,因为我使用的是HandshakeV10协议,在文档里面,协议有这样的规定:

<code>if capabilities & CLIENT_SECURE_CONNECTION {    string[$len]   auth-plugin-data-part-2 ($len=MAX(13, length of auth-plugin-data - 8))}</code>

如果根据文档的说明,算出来auth-plugin-data-part-2的长度是13,因为auth-plugin-data的长度是20。但是,实际情况是,auth-plugin-data-part-2的长度应该为12,第13位一直为0。只有这样,我们才能根据salt算出正确的加密密码。这一点,在mysql-proxy官方的文档,以及多个msyql client driver上面,Wireshark的分析中都是如此,在go-sql-driver中,作者都直接写了如下的注释:

<code>// second part of the password cipher [12? bytes]// The documentation is ambiguous about the length.// The official Python library uses the fixed length 12// which is not documented but seems to work.</code>

可想而知,这个坑有多坑爹。至少我开始是栽在上面了。加密老是不对。

Command

搞定了登陆,剩下的就是mysql的命令支持,mixer只实现了基本的命令。主要集中在text protocol以及prepared statment里面。

COM_PING

最基本的ping实现,用来检查mysql是否存活。

COM_INIT_DB

虽然叫init db,其实压根干的事情就跟use db一样,用来切换使用db的。

COM_QUERY

可以算是最重要的一个命令,我们在命令行使用的多数mysql语句,都是通过该命令发送的。

在COM_QUERY中,mixer主要支持了select,update,insert,delete,replace等基本的操作语句,同时支持begin,commit,rollback事物操作,还支持set names和set autocommit。

COM_QUERY有4中返回packet

  • OK Packet
  • Err Packet
  • Local In File(不支持)
  • Text Resultset

这里重点说明一下text resultset,因为它包含的就是我们最常用的select的结果集。

一个text resultset,包括如下几个包:

  • 一个以length encoded integer编码的column-count packet
  • column-count个column定义packet
  • eof packet
  • 一个或者多个row packet,每个row packet有column-count个数据
  • eof packet或者err packet

对于一个row packet的里面的数据,我们通过如下方式获取:

  • 如果值为NULL,那么就是0xfb
  • 否则,任何值都是用length encoded string表示

COM_STMT_*

COM_STMT_族协议就是通常的prepared statement,当我在atlas群里面说支持prepared statement的时候,很多人以为我支持的是在COM_QUERY中使用的prepare,execute和deallocate prepare这组语句。其实这两个还是很有区别的。

为什么我不现在不想支持COM_QUERY的prepare,主要在于这种prepare需要进行变量设置,mixer在后端跟server是维护的一个连接池,所以对于client设置的变量,proxy维护起来特别麻烦,并且每次跟server使用新的连接的时候,还需要将所有的变量重设,这增大了复杂度。所以我不支持变量的设置,这点看cobar也是如此。既然不支持变量,所以COM_QUERY的prepare我也不会支持了。

COM_STMT_*这组命令,主要用在各个语言的client driver中,所以我觉得只支持这种的prepare就够了。

对于COM_STMT_EXECUTE的返回结果,因为prepare的语句可能是select,所以会返回binary resultset,binary resultset组成跟前面text resultset差不多,唯一需要注意的就是row packet采用的是binary row packet。

对于每一个binary row packet,第一个byte为0,后面紧跟着一个null bitmap,然后才是实际的数据。

在binary row packet中,使用null bitmap来表明该行某一列的数据为NULL。null bitmap长度通过 (column-count + 7 + 2) / 8计算得到,而对于每列数据,如果为NULL,那么它在null bitmap中的位置通过如下方式计算:

<code>NULL-bitmap-byte = ((field-pos + offset) / 8)NULL-bitmap-bit  = ((field-pos + offset) % 8)</code>

offset在binary resultset中为2,field-pos为该列的位置。

对于实际非NULL数据,则是根据每列定义的数据类型来获取,譬如如果type为MYSQL_TYPE_LONGLONG,那么该数据值的长度就是8字节,如果type为MYSQL_TYPE_STRING,那么该数据值就是一个length encoded string。

后记

我通过Wireshark分析了一些mysql protocol,主要在这里,这里不得不强烈推荐wireshark,它让我在学习mysql protocol过程中事半功倍。

mixer的代码在这里https://github.com/siddontang/mixer,欢迎反馈。

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
Composite Index와 여러 단일 열 인덱스를 언제 사용해야합니까?Composite Index와 여러 단일 열 인덱스를 언제 사용해야합니까?Apr 11, 2025 am 12:06 AM

데이터베이스 최적화에서 쿼리 요구 사항에 따라 인덱싱 전략을 선택해야합니다. 1. 쿼리에 여러 열이 포함되고 조건 순서가 수정되면 복합 인덱스를 사용하십시오. 2. 쿼리에 여러 열이 포함되어 있지만 조건 순서가 고정되지 않은 경우 여러 단일 열 인덱스를 사용하십시오. 복합 인덱스는 다중 열 쿼리를 최적화하는 데 적합한 반면 단일 열 인덱스는 단일 열 쿼리에 적합합니다.

MySQL에서 느린 쿼리를 식별하고 최적화하는 방법은 무엇입니까? (느린 쿼리 로그, Performance_schema)MySQL에서 느린 쿼리를 식별하고 최적화하는 방법은 무엇입니까? (느린 쿼리 로그, Performance_schema)Apr 10, 2025 am 09:36 AM

MySQL 느린 쿼리를 최적화하려면 SlowQueryLog 및 Performance_Schema를 사용해야합니다. 1. SlowQueryLog 및 Set Stresholds를 사용하여 느린 쿼리를 기록합니다. 2. Performance_schema를 사용하여 쿼리 실행 세부 정보를 분석하고 성능 병목 현상을 찾고 최적화하십시오.

MySQL 및 SQL : 개발자를위한 필수 기술MySQL 및 SQL : 개발자를위한 필수 기술Apr 10, 2025 am 09:30 AM

MySQL 및 SQL은 개발자에게 필수적인 기술입니다. 1.MySQL은 오픈 소스 관계형 데이터베이스 관리 시스템이며 SQL은 데이터베이스를 관리하고 작동하는 데 사용되는 표준 언어입니다. 2.MYSQL은 효율적인 데이터 저장 및 검색 기능을 통해 여러 스토리지 엔진을 지원하며 SQL은 간단한 문을 통해 복잡한 데이터 작업을 완료합니다. 3. 사용의 예에는 기본 쿼리 및 조건 별 필터링 및 정렬과 같은 고급 쿼리가 포함됩니다. 4. 일반적인 오류에는 구문 오류 및 성능 문제가 포함되며 SQL 문을 확인하고 설명 명령을 사용하여 최적화 할 수 있습니다. 5. 성능 최적화 기술에는 인덱스 사용, 전체 테이블 스캔 피하기, 조인 작업 최적화 및 코드 가독성 향상이 포함됩니다.

MySQL 비동기 마스터 슬레이브 복제 프로세스를 설명하십시오.MySQL 비동기 마스터 슬레이브 복제 프로세스를 설명하십시오.Apr 10, 2025 am 09:30 AM

MySQL 비동기 마스터 슬레이브 복제는 Binlog를 통한 데이터 동기화를 가능하게하여 읽기 성능 및 고 가용성을 향상시킵니다. 1) 마스터 서버 레코드는 Binlog로 변경됩니다. 2) 슬레이브 서버는 I/O 스레드를 통해 Binlog를 읽습니다. 3) 서버 SQL 스레드는 데이터를 동기화하기 위해 Binlog를 적용합니다.

MySQL : 쉽게 학습하기위한 간단한 개념MySQL : 쉽게 학습하기위한 간단한 개념Apr 10, 2025 am 09:29 AM

MySQL은 오픈 소스 관계형 데이터베이스 관리 시스템입니다. 1) 데이터베이스 및 테이블 작성 : CreateAbase 및 CreateTable 명령을 사용하십시오. 2) 기본 작업 : 삽입, 업데이트, 삭제 및 선택. 3) 고급 운영 : 가입, 하위 쿼리 및 거래 처리. 4) 디버깅 기술 : 확인, 데이터 유형 및 권한을 확인하십시오. 5) 최적화 제안 : 인덱스 사용, 선택을 피하고 거래를 사용하십시오.

MySQL : 데이터베이스에 대한 사용자 친화적 인 소개MySQL : 데이터베이스에 대한 사용자 친화적 인 소개Apr 10, 2025 am 09:27 AM

MySQL의 설치 및 기본 작업에는 다음이 포함됩니다. 1. MySQL 다운로드 및 설치, 루트 사용자 비밀번호를 설정하십시오. 2. SQL 명령을 사용하여 CreateAbase 및 CreateTable과 같은 데이터베이스 및 테이블을 만듭니다. 3. CRUD 작업을 실행하고 삽입, 선택, 업데이트, 명령을 삭제합니다. 4. 성능을 최적화하고 복잡한 논리를 구현하기 위해 인덱스 및 저장 절차를 생성합니다. 이 단계를 사용하면 MySQL 데이터베이스를 처음부터 구축하고 관리 할 수 ​​있습니다.

InnoDB 버퍼 풀은 어떻게 작동하며 성능에 중요한 이유는 무엇입니까?InnoDB 버퍼 풀은 어떻게 작동하며 성능에 중요한 이유는 무엇입니까?Apr 09, 2025 am 12:12 AM

innodbbufferpool은 데이터와 색인 페이지를 메모리에로드하여 MySQL 데이터베이스의 성능을 향상시킵니다. 1) 데이터 페이지가 버퍼 풀에로드되어 디스크 I/O를 줄입니다. 2) 더러운 페이지는 정기적으로 디스크로 표시되고 새로 고침됩니다. 3) LRU 알고리즘 관리 데이터 페이지 제거. 4) 읽기 메커니즘은 가능한 데이터 페이지를 미리로드합니다.

MySQL : 초보자를위한 데이터 관리의 용이성MySQL : 초보자를위한 데이터 관리의 용이성Apr 09, 2025 am 12:07 AM

MySQL은 설치가 간단하고 강력하며 데이터를 쉽게 관리하기 쉽기 때문에 초보자에게 적합합니다. 1. 다양한 운영 체제에 적합한 간단한 설치 및 구성. 2. 데이터베이스 및 테이블 작성, 삽입, 쿼리, 업데이트 및 삭제와 같은 기본 작업을 지원합니다. 3. 조인 작업 및 하위 쿼리와 같은 고급 기능을 제공합니다. 4. 인덱싱, 쿼리 최적화 및 테이블 파티셔닝을 통해 성능을 향상시킬 수 있습니다. 5. 데이터 보안 및 일관성을 보장하기위한 지원 백업, 복구 및 보안 조치.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

맨티스BT

맨티스BT

Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

PhpStorm 맥 버전

PhpStorm 맥 버전

최신(2018.2.1) 전문 PHP 통합 개발 도구

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.