2009년 1월 8일 목요일

갱신용 SQL문 실행시의 패킷1

계속해서 SQL문을 실행했을 때 송수신되는 패킷에 대해서 이야기해보자. 
갱신용하고 검색용 패킷은 꽤 다르지만 갱신용이 간단하니까 이것부터 설명한다. 

갱신용 SQL문에서는 클라이언트에서 Command Packet을 서버에 송신하고, 서버는 OK Packet또는 Error Packet을 리턴하는 흐름을 가진다. 

Command Packet
클라이언트에서 서버에 대해서 SQL문을 송출하는 것이다. 이때 패킷에는 SQL문이외에도 서버에 대한 명령(커맨드)을 나타내는 바이트열도 포함된다. 
그런 의미도 있어서 이 패킷을 「Command Packet」이라고 부른다. 
다음과 같은 insert문을 실행한 경우를 알아보자. 

INSERT문의 실행예
 mysql> INSERT INTO tbl1 VALUES(5, 'xyz', NOW() );
Query OK, 1 row affected ( 0.16 sec)

Command Packet(INSERT문)
패킷헤더:  4바이트
커맨드번호: 1바이트 ,  보통의 SQL문장이면 0x03(COM_QUERY)
SQL문본체: n바이트, SQL문본체로써 NULL(0x00)으로 끝나지는 않는다. 
             위의 예제의 경우 49  4e 53 45 52 54 20 49 4e 54 4f 20.... (INSERT INTO )

패킷헤더의 바로 뒤 1바이트는 「커맨드번호」이다.  그 뒤에 실제로 발행되는 SQL문이 그대로 전송된다. 커맨드번호라는 것은 명령의 종류를 나타내는 것으로 보통 SQL문은 전부 COM_QUERY(0x03) 커맨드이다. 
(CREATE TABLE등의 DDL문, SELECT/INSERT/UPDATE/DELETE문, SET문등)

현재 데이터베이스를 변경하는 경우라든지 prepared statement를 실행하는 경우등은 다른 커맨드번호가 할당된다. 
서버측에서는 커맨드번호에 대해서 적절한 처리를 실행한다.  커맨드종류에는 다음과 같은게 있다. 
COM_SLEEP     
COM_QUIT          mysql_close
COM_INIT_DB    mysql_select_db
COM_QUERY       mysql_query
COM_FIELD_LIST     mysql_list_fields
COM_CREATE_DB      mysql_create_db
COM_DROP_DB     mysql_drop_db
COM_REFRESH     mysql_reload, mysql_refresh
COM_SHUTDOWN      mysql_shutdown
COM_STATISTICS      mysql_stat
COM_PROCESS_INFO  mysql_list_processes
COM_CONNECT
COM_PROCESS_KILL     mysql_kill
COM_DEBUG    mysql_dump_debug_info
COM_PING     mysql_ping
COM_TIME
COM_DELAYED_INSERT    
COM_CHANGE_USER     mysql_change_user
COM_BINLOG_DUMP   (replication용)
COM_TABLE_DUMP      (replication용)
COM_CONNECT_OUT   (replication용)
COM_REGISTER_SLAVE (replication용)
COM_STMT_PREPARE  mysql_stmt_prepare
COM_STMT_EXECUTE  mysql_stmt_execute
COM_STMT_SEND_LONG_DATA   mysql_stmt_send_long_data
COM_STMT_CLOSE   mysql_stmt_close
COM_STMT_RESET   mysql_stmt_prepare(reset_stmt_handle)
COM_SET_OPTION  mysql_set_server_option
COM_STMT_FETCH  mysql_stmt_fetch
COM_DAEMON
COM_END


SQL문본체에는 구분자인 세미콜론(;)은 포함되지 않는다. 또 다음과 같은 복수의 SQL문을 합쳐서 실행하는 경우는 복수의 SQL문발행패킷로 분할되어 송신된다. 

복수의 SQL문을 실행
mysql> SELECT 1; SELECT 2;

이런 경우는 SELECT 1을 실행하는 패킷하고 SELECT 2를 실행하는 패킷이 각각 생성되어 그 순서로 송신되게 된다.