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 body に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を送信する場合:
最初のパケット:
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は幅広く利用されており、多くの言語やランタイムでサポートされています。
Since compress body can contain many "standard packets", compress sequence number is incremented separately from sequence number.
For small packets, using compression won't be efficient, so the client can choose to send uncompressed data.
That is done by setting the compressed packet length to the real length and the uncompressed packet length to 0. (Data must then be uncompressed).
Example: Sending a COM_PING packet COM_PING body when COMPRESS is enabled. This is 1 byte of data that has then no reason to be compressed, so:
01 00 00 00 00 00 00 01 00 00 00 10
The server will then return an OK_Packet response with a compress sequence number of 1, and a sequence number of 1.
Compression packet splitting
The server will uncompress data and then must have the same packet than if there was no compression. If data size needs splitting, it's better to separate compress packet.