2009년 2월 4일 수요일

Close경우의 패킷

Close경우의 패킷
PreparedStatement의 close경우(C API에서는 mysql_stmt_close()에 해당)에는 다음과 같은 
Command Packet이 클라이언트에서 서버로 송신된다. 

PreparedStatement Close Command Packet
패킷헤더: 4바이트
명령어번호: 1바이트 , 0x19(COM_STMT_CLOSE)고정
 Statement ID: 4바이트

또  접속이 끊겼을 때에는 다음과 같은 Command Packet이 클라이언트에서 서버로 송신된다. 

Quit Command Packet
패킷헤더: 4바이트
명령어번호: 1바이트 , 0x01(COM_QUIT)고정

그 어느쪽도 서버에서 클라이언트로는 TCP응답이 되돌려질 뿐 MySQL전용의 패킷형식은 없다. 

-----------
MySQL 통신프로토콜에 관한 기술 자료로서 MySQL Internal Manual(영어)이 있다. 
다만 옛날 버전정보가 그대로 남아있거나 해서 일부 부정확한 부분도 있다. 

이 수준의 정보를 깊은 수준으로 이해하려고 한다면 소스코드를 분석할 필요가 있을 때가 온다. 
MySQL은 오픈소스이기 때문에 소스코드를 잘 보면  이런 내용들을 전부 이해할 수 있다. 







서버측커서 이용시의 패킷(packet)

서버측커서 이용시의 패킷
MySQL 5.0에서부터 서버측 커서의 기능이 지원된다.
이것을 사용하면 결과를 한번에 전부가 아니라 5레코드정도 부분단위로 단계적으로 취득하는 것이 가능하다.
배치처리등 대량의 레코드를 처리하는 경우등에 클라이언트측에서 Out of Memory가 나지 않도록 하고 싶은 경우 효과적이다.

MySQL 서버측 기능은 Prepared Statement하고 셋트로 이용한다.
당연하지만 검색용 SQL문만 이용가능하다.
패킷의 흐름은 다음과 같다.
client -> server 1. Prepare Command Packet(mysql_stmt_prepare())
server -> client 2. Prepare Packet
_Header Packet, _Placeholder Packets, _EOF Packet, _Field Packets, _EOF Packet
client -> server 3. Execute Command Packet(mysql_stmt_execute())
server -> client 4. Execute Packet
_ResultSet Header Packet, _Field Packets, _EOF Packet
client -> server 5. Fetch Command Packet(mysql_stmt_fetch())
server -> client 6. Fetch Packet
_PreparedStatement Row Data Packets, _EOF Packet
※5,6은 결과셋이 없어질 때까지 반복하는 것이 가능.

보통의 Prepared Statement하고 다른 것은 「Fetch Command Packet」이라고 하는 fetch명령용 패킷이 새로이 추가된 것과
서버에서 클라이언트에 패킷이 되돌려지는 타이밍이 바뀌었다는 것이다.

보통의 Prepared Statement에서는 Execute명령(MySQL C API에서는 mysql_stmt_execute())을 실행한 단계에서 서버에서
ResultSet Header Packet, Field Packet, EOF Packet, PreparedStatement Row Data Packet, EOF Packet 전부가 보내어진다.

한편 서버측 커서를 사용한 경우는 Execute 명령시점에서 ResultSet Header Packet, Field Packet, EOF Packet까지가 보내어진다.
나머지 PreparedStatement Row Data Packet하고 EOF Packet은 Fetch명령(C API에서 mysql_stmt_fetch())이 있을 때
보내어진다.

Fetch명령에 따라서 클라이언트에서 서버로 송출되는 Fetch Command Packet의 구성은 다음과 같다.
Fetch Command Packet
패킷헤더: 4바이트
명령어번호: 1바이트, 0x1c(COM_STMT_FETCH)고정
statement ID: 4바이트
fetch 크기: 4바이트, 16진수표현 (mysql_store_result()를 호출한 경우에는 0xff ff ff ff 가 셋팅되어 전부 반환됨)

fetch 크기를 설정하는 항목이 있어서 이 값의 레코드수 만큼 한번의 Fetch명령에 의해 서버에서 클라이언트로 반환된다.
1회의 Fetch명령에 대해서 fetch크기 만큼의 PreparedStatement Row Data Packet하고 그 뒤에 EOF Packet이 1패킷, 이 합계가 셋트로 반환된다.

EOF Packet에서는 서버의 상태정보로써 결과셋이 아직 있는지 끝났는지에 대한 정보가 설정된다.
클라이언트측에서는 이 값에 따라서 Fetch를 계속할 까 말까를 판단한다.
보통 모든 결과셋이 클라이언트에 보내어지기까지 클라이언트에서 반복해서 Fetch명령을 실행한다.





2009년 2월 3일 화요일

Prepared Statement의 패킷5

PreparedStatement Row Data Packet
결과셋 1행에 대해 PreparedStatement Row Data Packet이 1패킷 반환되어진다. 
이 구성은 보통 검색용 SQL문 실행시의 Row Data Packet하고 같다. 
다만  내용구성이 약간 다르다. 

우선 반환되는 컬럼값의 표기가  보통의 검색용 SQL문에서는 모두 문자열표현이었지만 Prepared Statement의 경우에는 다르다. 

예를 들어 INTEGER형인 경우에는 4바이트, DATETIME형이면 8바이트의 고정크기이다. 
또 null 필드라는 영역도 새롭게 추가된다. 

PreparedStatement Row Data Packet
패킷헤더: 4바이트
OK: 1바이트, 0x00고정
null필드: (field count+9)/8 바이트, 나머지수는 절사.  값은 0x00고정
컬럼값(추출하는 컬럼수만큼 반복):  문자열형은 LCS표기, 정수형은 16진수표기 
ex> 01 00 00 00  03 61 62 63 07 d6 07 0c 1e 10 12 11
     ==> 첫번째 컬럼 : 01 00 00 00 , 1 , Integer
              두번째 컬럼: 03 61 62 63,  abc, 문자열
               세번째 컬럼: 07 d6 07 0c 1e 10 12 11,  2006년  12월 30일  16시 18분 17초

       

2009년 2월 1일 일요일

Prepared Statement의 패킷4

Placeholder(「?」)에 값을 넣어, 실제로 SQL문을 실행시키는 단계(C에서는 mysql_stmt_execute()에 해당)에서는 Execute명령용 패킷이 송수신된다. 

Execute Command Packet
클라이언트에서 서버로 보내지는 패킷이다. 
placeholder의 데이터형과 설정값등의 정보가 보내지게 된다. 

 Execute Command Packet
패킷헤더: 4바이트
명령번호 : 1바이트 , execute이면 0x17(COM_STMT_EXECUTE)
 Statement ID: 4바이트
 flag(커서타입): 1바이트, 서버측 커서(STMT_ATTR_CURSOR_TYPE)기능을 사용하는 경우는 0x01, 그 이외에는 0x00
 카운터: 4바이트, 현재는 0x01 00 00 00 의 4바이트 고정
 null bit map: (7+파라미터  갯수)/8 바이트,  바인드 변수가 null을 허용할까 말까의 플래그
 send_types_to_server: 1바이트, 현재는 0x01고정
 placeholder의 데이터형: 2*n바이트,  placeholder의 갯수만큼 반복  ex> 03 00 fd 00
 placeholder의  값:  수치는 바이너리표기, 문자열, 날짜/시간형은 LCS표기
   ex>03 00 00 00 03 61 62 63  
     ==>  첫번째 placeholder : 4바이트 integer형, 값은 3   
               두번째 placeholder: 문자열 abc


명령번호는 0x17(COM_STMT_EXECUTE)이다. 

커서타입이라는 것은 MySQL5.0이후의 기능인 서버측 커서를 사용할까 아닐까하는 것을 표시하는 플래그로 사용하지 않는 경우에는 0x00 사용하는 경우에는 0x01이 된다. 

현시점의 MySQL의 서버측 커서는 읽기 전용이기 때문에 서버측 커서기능을 사용할지 않을까(0x00),  읽기 전용 서버사이트 커서기능을 사용할까(0x01) 의 두가지 선택이 가능하게 된다. 

디폴트로는 서버측 커서기능은 off이다. 
또 Prepared Statement기능을 병용사용할 필요가 있어서  보통의 SQL문하고 세트로 사용하는 것은 되지는 않는다. 

null bit map이라는 것은 각 Placeholder가 null값을 허용할까 말까를 식별하기위한 플래그이다. 
최후에 각 Placeholder의 데이터형하고 Placeholder의 설정값이 각각 반복되어 저장된다. 
데이터형은 일률 2바이트로 관리된다.  
Placeholder의 설정값은,  문자열형은 Length Coded String표기이지만 수치형은 16진수표기가 되는 등 데이터형에 따라서 다르다. 

갱신할 때에는 보통 갱신용 SQL문장의 경우와 같이 서버에서 클라이언트에 OK/Error Packet이 반환된다.  또  검색할때도 보통 검색용 SQL문과 같이 서버에서 클라이언트로 다음과 같은 구성으로 패킷이 반환된다. 

ResultSet Header Packet 1패킷
Field Packets 컬럼수만큼의 패킷
EOF Packet  1패킷
PreparedStatement Row Data Packets  레코드수만큼의 패킷
EOF Packet 1패킷

이 중에 Rows Data Packets만 레이아웃이 보통의 검색용 SQL문의 경우와 다르다.