2009년 2월 4일 수요일

서버측커서 이용시의 패킷(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명령을 실행한다.