本節提供編寫使用 MySQL C API 中執行緒相關函式的客戶端程式的指南。有關這些函式的詳細資訊,請參閱第 8.2 節「C API 執行緒函式描述」。有關使用它們的原始碼範例,請查看 MySQL 原始碼發行版的 client
目錄。
mysqlimport 的原始碼在與
--use-threads
選項相關聯的程式碼中使用執行緒。mysqlslap 的原始碼使用執行緒來建立同時工作負載,以測試在高負載下的伺服器運作情況。
作為執行緒程式設計的替代方案,應用程式可能會發現非同步(非阻塞)C API 函式很有用。這些函式使應用程式能夠向伺服器提交多個未完成的請求,並使用輪詢確定每個請求何時完成。如需更多資訊,請參閱第 7 章,《C API 非同步介面》。
如果在將多執行緒程式連結到 MySQL 客戶端函式庫時發生未定義的參考錯誤,最可能的原因是您未在連結/編譯命令中包含執行緒函式庫。
客戶端函式庫幾乎是執行緒安全的。最大的問題是 sql/net_serv.cc
中從 Socket 讀取的子程式不是中斷安全的。這樣做是考慮到您可能希望擁有自己的警報,可以中斷對伺服器的長時間讀取。如果您為 SIGPIPE
中斷安裝中斷處理常式,則 Socket 處理應為執行緒安全的。
為避免在連線終止時中止程式,MySQL 會在首次呼叫 mysql_library_init()
、mysql_init()
或 mysql_connect()
時封鎖 SIGPIPE
。若要使用您自己的 SIGPIPE
處理常式,請先呼叫 mysql_library_init()
,然後安裝您的處理常式。
客戶端函式庫是針對每個連線的執行緒安全。兩個執行緒可以共享同一個連線,但有以下注意事項:
-
除非您使用先前提及的非同步 C API 函式,否則多個執行緒無法同時在同一個連線上向 MySQL 伺服器傳送查詢。特別是,您必須確保在一個執行緒中呼叫
mysql_real_query()
(或mysql_query()
)和mysql_store_result()
之間,沒有其他執行緒使用相同的連線。若要執行此操作,請在您的mysql_real_query()
(或mysql_query()
)和mysql_store_result()
呼叫對周圍使用互斥鎖。在mysql_store_result()
傳回後,可以釋放鎖定,而其他執行緒可以查詢相同的連線。如果您使用 POSIX 執行緒,可以使用
pthread_mutex_lock()
和pthread_mutex_unlock()
來建立和釋放互斥鎖。注意如果您檢查 MySQL 原始碼發行版中的程式,您會看到呼叫
native_mutex_lock()
和native_mutex_unlock()
,而不是呼叫pthread_mutex_lock()
和pthread_mutex_unlock()
。後者函式定義在thr_mutex.h
標頭檔中,並對應到特定於平台的互斥函式。 多個執行緒可以存取使用
mysql_store_result()
擷取的不同結果集。若要使用
mysql_use_result()
,您必須確保在結果集關閉之前,沒有其他執行緒使用相同的連線。但是,對於共享相同連線的多執行緒客戶端而言,最好使用mysql_store_result()
。
如果執行緒未建立與 MySQL 資料庫的連線,但呼叫了 MySQL 函式,請考慮以下事項:
當您呼叫 mysql_init()
時,MySQL 會為執行緒建立執行緒特定的變數,該變數由除錯函式庫(以及其他)使用。如果您在執行緒呼叫 mysql_init()
之前呼叫 MySQL 函式,則執行緒沒有必要的執行緒特定變數,您很可能會遲早遇到核心傾印。為了避免問題,您必須執行以下操作:
在任何其他 MySQL 函式之前呼叫
mysql_library_init()
。它不是執行緒安全的,因此請在建立執行緒之前呼叫它,或使用互斥鎖保護呼叫。安排在執行緒處理常式中的早期呼叫
mysql_thread_init()
,然後再呼叫任何 MySQL 函式。(如果您呼叫mysql_init()
,它會為您呼叫mysql_thread_init()
。)在執行緒中,在呼叫
pthread_exit()
之前呼叫mysql_thread_end()
。這會釋放 MySQL 執行緒特定變數使用的記憶體。
關於 mysql_init()
的上述注意事項也適用於 mysql_connect()
,後者會呼叫 mysql_init()
。