0 - Packet

クライアント-サーバー間のやり取りは下記の形式で行われます。

標準的なパケット

標準的なMySQL/MariaDBのパケットは4バイトのヘッダー+パケットbodyから成ります。

パケット長とは、パケットbodyの長さのことです。 パケット長は最大で3バイトです。実際のパケット長は3バイトからパケット長 = byte[0] + (byte[1]<<8) + (byte[2]<<16)で計算されます。パケット長の最大値(全て3バイト0xff)は16777215バイト、または 2^24 - 1、惜しくは16MB - 1バイトになります。

シーケンス番号は交換番号を意味します。クライエントがクエリを送信するたび、シーケンス番号はまず0にセットされます。そしてクライエントがパケットを分割する必要がある場合、シーケンス番号はインクリメントされます。 より複雑な状況として、クライアントとサーバーが複数パケットを交換するケース(例. 認証用ハンドシェイク)では、シーケンス番号(nr) = 受信したサーバーのパケットの最後のシーケンス番号(seq.nr) + 1にセットします。

例: COM_PING パケットを COM_PING 本体に1バイト (0x10)だけ送信する場合:

01 00 00 00 10

サーバーは OK_Packet を返します。その時のシーケンス番号は1です。

パケットの分割

前述の通り、パケット長は3バイトで、最大で2^24 - 1バイトもしくは16Mバイト - 1バイトです。 しかし、このプロトコルでは、より大きなデータの送受信が可能です。この場合、クライアントは同じデータに対して多数のパケットを送信します。その際、各パケットのシーケンス番号をインクリメントしていきます。

原則として、データを16Mバイトのチャンクで分割します。サーバーが長さ0xffffffのパケットを受信すると、次のパケットの読み取りを続けます。データがちょうど16MBになった時、空のパケットはシーケンスを強制終了する必要があります。


例 max_allowed_packet が40Mバイトに設定されており、40Mバイトのパケットbodyを送信する場合: standard_packet
最初のパケット:

ff ff ff 00 ...

2番目のパケット:

ff ff ff 01 ...

3番目のパケット:

02 00 80 02 ...


クライアント側はmax_allowed_packet の設定値を認識している必要があります。サーバー側には、mac_allowed_packetの設定値に対応したサイズで、パケットbodyを保持するためのバッファがあります。仮にクライアント側がmax_allowed_packetの設定値よりも大きなデータを送った場合は、ソケットがクローズされます。

2^24 - 1バイトのデータは2パケットで送信する必要があることに注意してください。最初のパケットは長さプレフィックス0xffffffで、2番目のパケットは長さ0(0x000000バイト, seqno インクリメント)です。一般的に、データ長は2^24 - 1の倍数であり、空のパケットが付属します。



パケットの圧縮

接続に時間がかかる場合、パケットは圧縮されます。 圧縮は ハンドシェイク・レスポンス・パケット の後、クライアント側がCOMPRESSを設定し、サーバー側が圧縮機能を備えている場合に有効になります。

圧縮が有効になると、パケットはヘッダー+データで7バイトになります。圧縮アルゴリズムにはZLIBが利用されます。ZLIBは幅広く利用されており、多くの言語やランタイムでサポートされています。

  • int<3> 圧縮パケット長
  • int<1> 圧縮シーケンス番号
  • int<3> 非圧縮パケット長
  • byte<n> 圧縮body
    • 圧縮bodyには少なくとも1つ以上の標準パケットが含まれますが、圧縮可能です。:
      • 1つ以上の標準パケット :

圧縮bodyには多くの標準パケットが含まれるため、圧縮シーケンス番号はシーケンス番号とは別にインクリメントされます。

小さなパケットに対しては圧縮は有効ではありません。そのためクライアント側は非圧縮データによる送信を選択することが可能です。
非圧縮データを送信するためには、圧縮されたパケット長を実際の長さに設定し、圧縮されていないパケット長を0に設定します。(データは圧縮されていない必要があります。)

例: COMPRESSが有効な状態で COM_PING パケットの COM_PING 本体を送信する場合。 1バイトのデータのため、圧縮する理由はありません。

01 00 00 00 00 00 00 01 00 00 00 10

サーバー側はOK_Packetを返します。レスポンスには圧縮シーケンス番号1とシーケンス番号1 が付いています。


圧縮パケットの分割

サーバー側はデータを解凍し、送信側と同じパケット(圧縮されていないパケット)を受け取る必要があります。データサイズを分割する必要がある場合、圧縮パケットを分割することが推奨されます。

compress_packet


Comments

Comments loading...
Content reproduced on this site is the property of its respective owners, and this content is not reviewed in advance by MariaDB. The views, information and opinions expressed by this content do not necessarily represent those of MariaDB or any other party.