2008년 12월 23일 화요일

MySQL통신프로토콜 - 인증시의 패킷2

Handshake Initialization Packet
클라이언트로가 서버에 접속요구를 했을 시점에 서버에서 클라이언트에 「Handshake Initialization Packet」이라는 패킷이 송신된다.
패킷 헤더, 서버가 처리가능한 프로토콜의 버전, 버전용의 문자열, 세션 식별ID, 암호화를 위한 문자열, 서버 캐릭터셋이 포함된다. 
프로토콜버전은 MySQL 4.1/5.0/5.1에서는 전부 0x0a이 된다. 
서버의 버전은 서버버전및 빌드옵션등의 문자열이 포함되어 있다. 
이것은 프로그램이 해석하기 위한 정보가 아니라 사람이 눈으로 보고 알 수 있는 정보를 제공하기 위해 준비되어있다.  명령어 라인툴 mysql에서 로그인하면 버전등의 정보가 표시되지만 이 같은 형태로 서버에서 보내어진 것을 표시하고 있는 것이다. 

Handshake Initialization Packet
*패킷헤더  :4바이트    ex>43 00 00 00
*프로토콜버전:  1바이트 4.1이후버전은 0x0a(10) ex>0a
*서버버전 : n+1바이트   바이트수는 바이너리에 의존, 종단은 0x00,
*스레드ID: 4바이트  MySQL에 접속원을 식별하기위한 ID ex>03 00 00 00 
*암호화  seed: 8바이트 패스워드 암호화를 위한 문자열 ex>33 7e 45 79 55 7a 28 54 
*filler: 1바이트  예약바이트 현재는 항상 0x00
*server capabilities: 2바이트 이용가능한옵션       
*캐릭터셋 번호: 1바이트  서버의 캐릭터셋ID(16진수) 
*server status: 2바이트  서버의 상태 ex>02 00    
*filler: 13바이트  예약바이트 현재는 전부 0x00
*난수문자열: 13바이트 난수문자열, 종단은 0x00

스레드ID는 세션번호를 말한다.  SHOW PROCESSLIST명령어등을 실행하면 그 mysqld에 접속해 있는 세션 일람을 번호로 보는게 가능한데 그걸 말한다. 
스레드ID는 클라이언트당 할당되고 그 이후에는 송수신 되지 않는다. 

예를 들어 TCP/IP접속이면 서버측은 스레드ID를 송수신 하지 않아도 클라이언트의 IP어드레스하고 포트번호로 클라이언트 식별이 가능하기 때문이다. 

암호화를 위한 문자열은 패스워드를 암호화하기 위해서 사용된다. 클라이언트에서 서버로 패스워드를 송신할 때 평문으로 주고 받는 것을 방지하기 위함이다. 
MySQL에서는 인증시에 패스워드만 암호화되어 주고 받게 되지만 그것은 사전에 암호화를 위한 문자열(공통키)를 서버에서 클라이언트에 보냈기 때문이라는 것을 알 수 있다. 

Server Capabilities라는 것은 서버가 처리가능한 옵션을 지정하고 있다.  예를 들어 4.0이전과 4.1이후 버전에서는 패스워드 송수신방법이 바뀌었기 때문에 4.1이후 환경에서는 old-password를 지정해서 mysqld를 기동하지 않는 한 4.0이전의 클라이언트에서의 접속은 되지 않는다. 

캐릭터셋번호는 mysqld의 default-character-set파라미터에서 설정한 캐릭터셋에 상당하는 번호이다.  utf8이면 0x53이다.  

Server Status는 자동커밋의 유무효라든지 풀스캔이 실행되었는지 아닌지에 대한 정보가 포함되어있다. 

   **SERVER_STATUS_IN_TRANS   트랜잭션제어중
       **SERVER_STATUS_AUTOCOMMIT   자동커밋모드가 유효
       **SERVER_MORE_RESULTS_EXISTS 결과셋이 계속되고 있음(SQL문을 한번에 여러번 실행하는 경우)
       **SERVER_QUERY_NO_GOOD_INDEX_USED 효과적인 인덱스가 사용되지 못했음.
       **SERVER_QUERY_NO_INDEX_USED 인덱스가 사용되지 못했음.
       **SERVER_STATUS_CURSOR_EXISTS 커서의 최종행에 도달해있지 않음(서버측 커서이용할 때만)
       **SERVER_STATUS_LAST_ROW_SENT 커서의 최종행에 도달했음(서버측 커서 이용할 때만)
      **SERVER_STATUS_DB_DROPPED 데이터베이스가 DROP되었음.
      **SERVER_STATUS_NO_BACKSLASH_ESCAPES escape기호로 0x5c(\)를 사용하지 않음.