클라이언트 라이브러리는 대부분 쓰레드-세이프이다. 가장 어려운 문제는 소켓에서 읽는 net.c의 서브루틴이 인터럽트-세이프가 아니라는 것이다. SIGPIPE 인터럽트용 인터럽트 핸들러를 설치한다면, 소켓 처리는 쓰레드-세이프가 된다.
연결이 종료될 때 프로그램이 중지되는 것을 피하기 위해서, MySQL은 mysql_library_init(), mysql_init(), 또는 mysql_connect()에 대한 첫번째 호출에서 SIGPIPE를 막는다. 사용자 자신의 SIGPIPE 핸들러를 사용하고자 한다면, 우선 mysql_library_init()를 실행한 후에 사용자 핸들러를 설치하도록 한다.
다른 쓰레드에서 클라이언트를 인터럽트할 수 있는 쓰레디드 클라이언트를 얻고 MySQL 서버와 통신을 할 때 타임 아웃을 설정하기 위해서는 서버가 사용하는 net_serv.o 코드와 -lmysys, -lmystrings, 그리고 -ldbug 라이브러리를 사용하도록 한다.
인터럽트 및 타임아웃이 필요없다면, 쓰레드-세이프 클라이언트 라이브러리 (mysqlclient_r)를 컴파일해서 사용하도록 한다.
쓰레디드 클라이언트를 사용할 때 타임아웃과 인터럽트를 사용한다면, 파일에 들어 있는 thr_alarm.c 파일을 많이 활용할 수 있을 것이다. mysys 라이브러리에서 루틴을 사용한다면, my_init()를 가장 먼저 호출해야 한다는 점만 기억하도록 한다!
어떠한 경우에서라도 다른 MySQL 함수를 호출하기 전에 반드시 mysql_library_init()를 실행해서 클라이언트 라이브러리를 초기화 시켜야 한다는 점을 명심하도록 한다. 라이브러리와 함께 업무를 종료한 후에는, mysql_library_end()를 실행하도록 한다.
mysql_real_connect()는 디폴트로 쓰레드-세이프가 아니다. 쓰레드-세이프 클라이언트 라이브러리를 컴파일하고 쓰레드-세이프 방식으로 그것을 사용하는 방법은 아래에 나와 있다.
mysql_real_connect()를 쓰레드-세이프로 만들기 위해서는, MySQL 배포판을 다음과 같은 명령문을 사용해서 구성해야 한다:
shell> ./configure --enable-thread-safe-client
그런 다음에, 배포판이 쓰레드-세이프 클라이언트 라이브러리 libmysqlclient_r를 생성하도록 다시 컴파일 한다. 이 라이브러리는 연결 별로 쓰레드-세이프가 된다. 다음에 나오는 캐빗 (caveat)을 사용하면 두 개의 쓰레드가 동일한 연결을 공유할 수 있도록 할 수 있다:
- 두 개의 쓰레드는 동일한 연결 상에서 두 대의 MySQL 서버에 동시에 하나의 쿼리를 보낼 수 없다. 특히, mysql_query()와 mysql_store_result()를 호출하는 동안에는 어떠한 다른 쓰레드도 동일한 연결을 사용하지 않음을 확인해야 한다.
- 많은 종류의 쓰레드가 mysql_store_result()로 추출되는 서로 다른 결과 셋에 접속할 수 있다.
- mysql_use_result를 사용한다면, 결과 셋이 닫히기 전에는 어떠한 다른 쓰레드도 동일한 연결을 사용하지 않음을 확인해야 한다. 하지만, 동일한 연결을 공유하는 쓰레디드 클라이언트는 mysql_store_result()를 사용하도록 하는 것이 가장 바람직하다.
- 동일한 연결 상에서 여러 개의 쓰레드를 사용하고자 한다면, mysql_query()와 mysql_store_result() 호출에 대해서는 뮤텍스 (mutex) 잠금을 반드시 해두도록 한다. 일단 mysql_store_result()가 준비되면, 잠금을 풀수 있고 다른 쓰레드가 동일한 연결을 쿼리할 수도 있다.
- POSIX 쓰레드를 사용한다면, 뮤텍스 잠금을 구축하고 풀 때 pthread_mutex_lock() 및 pthread_mutex_unlock()를 각각 사용할 수 있다.
MySQL 데이터베이스에 대한 연결을 생성하지 않은 MySQL 함수를 호출하는 쓰레드를 가지고 있다면 다음에 설명하는 사항을 알아야 한다:
mysql_init() 또는 mysql_connect()를 호출하면 MySQL은 디버그 라이브러리가 사용하는 쓰레드용으로 쓰레드-관련 변수를 생성한다.
쓰레드가 mysql_init() 또는 mysql_connect()를 호출하기 전에 MySQL 함수를 호출한다면, 쓰레드는 필요한 쓰레드-관련 변수를 가지고 있지 않기 때문에 조만간 코어 덤프를 사용해서 끝마쳐야 할 수도 있을 것이다.
다음 과정을 처리하도록 한다:
1. 다른 MySQL 함수를 호출하기 전에 mysql_library_init()를 실행하도록 한다. 이것은 쓰레드-세이프가 아니기 때문에, 쓰레드를 생성하기 전에 호출하거나, 또는 뮤텍스를 사용해서 호출을 하지 못하도록 한다.
2. 다른 MySQL 함수를 호출하기 전에 쓰레드 핸들러에서 초기에 mysql_thread_init()를 호출하도록 정렬한다. mysql_init() 또는 mysql_connect()를 호출한다면, 이것들은 mysql_thread_init()를 호출한다.
3. 쓰레드에서, pthread_exit()를 호출하기 전에 mysql_thread_end()를 실행한다. 이렇게 하면 MySQL 쓰레드-관련 변수가 사용한 메모리를 풀게 된다.