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.