本節提供編寫使用 MySQL C API 中與執行緒相關的函數之用戶端程式的指南。如需這些函數的詳細資訊,請參閱第 8.2 節,「C API 執行緒函數說明」。如需使用它們的原始碼範例,請查看 MySQL 來源散發套件的 client
目錄
mysqlimport 的原始碼在與
--use-threads
選項相關聯的程式碼中使用執行緒。mysqlslap 的原始碼使用執行緒來設定同時工作負載,以測試高負載下的伺服器運作情況。
作為執行緒程式設計的替代方案,應用程式可能會發現非同步(非封鎖)C API 函數很有用。這些函數使應用程式能夠向伺服器提交多個未完成的請求,並使用輪詢來判斷每個請求何時完成。如需詳細資訊,請參閱第 7 章,C API 非同步介面。
如果將多執行緒程式連結至 MySQL 用戶端程式庫時發生未定義參考錯誤,最可能的原因是您未在連結/編譯命令中包含執行緒程式庫。
用戶端程式庫幾乎是執行緒安全的。最大的問題是 sql/net_serv.cc
中從通訊端讀取的子常式並非中斷安全的。這樣做的想法是,您可能希望擁有自己的警報,可以中斷對伺服器的長時間讀取。如果您為 SIGPIPE
中斷安裝中斷處理程式,則通訊端處理應該是執行緒安全的。
為避免在連線終止時中止程式,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 函數之前,安排在執行緒處理程式的早期呼叫
mysql_thread_init()
。(如果您呼叫mysql_init()
,它會為您呼叫mysql_thread_init()
。)在執行緒中,請在呼叫
pthread_exit()
之前呼叫mysql_thread_end()
。這會釋放 MySQL 執行緒特定變數使用的記憶體。
關於 mysql_init()
的先前注意事項也適用於 mysql_connect()
,它會呼叫 mysql_init()
。