C/JがMySQLサーバへ送ったPacketのダンプ
アプリケーションコードがDriverManager.getConnection()を呼び出し.ユーザ名/パスワード無し.
normal size=59, HEADER:[39][0][0][1] = 27 00 00 01 / BODY: 27 00 00 01 8f a2 02 00 ' . . . . . . . ff ff ff 00 08 00 00 00 . . . . . . . . 00 00 00 00 00 00 00 00 . . . . . . . . 00 00 00 00 00 00 00 00 . . . . . . . . 00 00 00 00 00 00 74 65 . . . . . . t e 73 74 00 00 00 00 00 00 s t . . . . . . 00 00 00 00 00 00 00 00 . . . . . . . . 00 00 00
C/Jが"SET NAMES latin1"を自動的に発行
normal size=39, HEADER:[17][0][0][0] = 11 00 00 00 / BODY: 11 00 00 00 03 53 45 54 . . . . . S E T 20 4e 41 4d 45 53 20 6c . N A M E S . l 61 74 69 6e 31 00 00 00 a t i n 1 . . . 00 00 00 00 00 00 00 00 . . . . . . . . 00 00 00 00 00 00 00 . . . . . . .
C/Jが"SET character_set_results = NULL"を自動的に発行
normal size=39, HEADER:[33][0][0][0] = 21 00 00 00 / BODY: 21 00 00 00 03 53 45 54 ! . . . . S E T 20 63 68 61 72 61 63 74 . c h a r a c t 65 72 5f 73 65 74 5f 72 e r _ s e t _ r 65 73 75 6c 74 73 20 3d e s u l t s . = 20 4e 55 4c 4c 00 00 . N U L L . .
C/Jが"SHOW VARIABLES"を自動的に発行.Packetの再利用により前回の内容が残ってる.
normal size=39, HEADER:[15][0][0][0] = 0f 00 00 00 / BODY: 0f 00 00 00 03 53 48 4f . . . . . S H O 57 20 56 41 52 49 41 42 W . V A R I A B 4c 45 53 73 65 74 5f 72 L E S s e t _ r 65 73 75 6c 74 73 20 3d e s u l t s . = 20 4e 55 4c 4c 00 00 . N U L L . .
C/Jが"SHOW COLLATION"を自動的に発行.同じく以前の内容が残ってる.
normal size=39, HEADER:[15][0][0][0] = 0f 00 00 00 / BODY: 0f 00 00 00 03 53 48 4f . . . . . S H O 57 20 43 4f 4c 4c 41 54 W . C O L L A T 49 4f 4e 73 65 74 5f 72 I O N s e t _ r 65 73 75 6c 74 73 20 3d e s u l t s . = 20 4e 55 4c 4c 00 00 . N U L L . .
C/Jが"SET autocommit=1"を自動的に発行.同じく以前の内容が残ってる.
normal size=39, HEADER:[17][0][0][0] = 11 00 00 00 / BODY: 11 00 00 00 03 53 45 54 . . . . . S E T 20 61 75 74 6f 63 6f 6d . a u t o c o m 6d 69 74 3d 31 74 5f 72 m i t = 1 t _ r 65 73 75 6c 74 73 20 3d e s u l t s . = 20 4e 55 4c 4c 00 00 . N U L L . .
アプリケーションコードがPreparedStatement.execute()を呼び出し.1つ目のカラムはINT型で値=1を設定済み,2つ目のカラムはLONGBLOB型で値は50個の'A'を設定済みでexecute()を呼んだ.ただしClient-SideのPreparedStatementであるため,プロトコル/パケット的には通常のQUERY実行と同じ.
normal size=16384, HEADER:[96][0][0][0] = 60 00 00 00 / BODY: 60 00 00 00 03 49 4e 53 ` . . . . I N S 45 52 54 20 49 4e 54 4f E R T . I N T O 20 74 31 20 28 63 31 2c . t 1 . ( c 1 , 20 63 32 29 20 56 41 4c . c 2 ) . V A L 55 45 53 20 28 31 2c 20 U E S . ( 1 , . 5f 62 69 6e 61 72 79 27 _ b i n a r y ' 41 41 41 41 41 41 41 41 A A A A A A A A 41 41 41 41 41 41 41 41 A A A A A A A A 41 41 41 41 41 41 41 41 A A A A A A A A 41 41 41 41 41 41 41 41 A A A A A A A A 41 41 41 41 41 41 41 41 A A A A A A A A 41 41 41 41 41 41 41 41 A A A A A A A A 41 41 27 29 00 00 00 00 A A ' ) . . . . 00 00 00 00 00 00 00 00 . . . . . . . . 00 00 00 00 00 00 00 00 . . . . . . . . (中略) 00 00 00 00 00 00 00 00 . . . . . . . .
アプリケーションコードがConnection.close()を呼び出し.
normal size=6, HEADER:[1][0][0][0] = 01 00 00 00 / BODY: 01 00 00 00 01 00 . . . . . .
ふむ.Packet Headerの先頭3bytesを使って書いた"Bodyのサイズ"はサーバ側でちゃんと読まれていたし,Headerに書かれているサイズと実際のBodyのサイズも一致するし,やっと多少納得する所までこれた.
しかし謎はまだある.大量のデータを送った場合(16MB超)にPacket Headerが"00 00 00 00"になるわけだが,これだとサーバ側のmy_real_read関数の戻り値が0となり,my_net_read関数内でのループ処理が想定通りに動く気がしない.
また実験してみればわかるが,50MBのデータを送った際にC/J側で確認したPacket数は2つ.100MBのデータを送った際には5つであった点だ.単純に割り算で考えると納得行かない.C/J側でのPacketのダンプはflushの直前でやっているので取りこぼしは無いはず,だがまだ自分のミスがあるのかも.早い話が,サーバ側でもいろんな変数にprintf突っ込んで動かしてみればいい.コンパイルに時間がかかるのが痛いけど.
がしかし今日は遅いのでもう寝る.では.AM4:00.