http://www.blogbus.com/skatings-logs/48527211.html
如果你用線程的編程,你應該用--with-thread-safe-client編譯MySQL C API,這將使C API線程對每個連接更安全。你可以讓2個線程共享相同的連接,只要如果你做下列事情:
兩個線程不能同時在同一個連接上發送查詢到MySQL。特別是你必須保證在一個mysql_query()和mysql_store_result()之間沒有其他線程正在使用同一個連接。
許多線程能存取用mysql_store_result()檢索出來的不同結果集合。
如果你使用mysql_use_result,你必須保證沒有其他線程在同一個連接上正在詢問任何東西,直到結果集合被關閉。
設計如下線程,驗證上述內容, Thread1和Thread2使用同一個mysql連接,執行select語句:
Thread1: Thread2:
mysql_query(); sleep(1);
| |
| |
sleep(2); mysql_query();
| |
| |
mysql_store_result(); mysql_store_result();
線程2中調用mysql_query()時出錯,通過mysql_error()返回的錯誤信息為:Commands out of sync; you can’t run this command now.
解決方法1:
一個線程分配一個mysql連接
解決方法2:
在mysql_query()之前加上線程鎖,在mysql_store_result()之后釋放線程鎖,
pthread_mutex_lock();
|
|
mysql_query();
|
|
mysql_store_result();
|
|
pthread_mutex_unlock();
不得以要用多線程,大概確定要注意這些:
(1)使mysql_real_connect()線程安全。(再次編譯:shell> ./configure --enable-thread-safe-client)
-------------------------------------
(2)一個連接上,要確保在mysql_query()和mysql_store_result()之間,只有一個線程。
(大多Mysql數據庫封裝類庫顧不到多線程,別用任何類庫)
------------------------------------
請指導,還有哪些要注意的,譬如,要改成INNODB的結構嗎?
@jsyang888: http://www.oschina.net/p/transfer (Mysql-transfer 多線程) 這有人用過嗎 ?(2年前)
http://blog.csdn.net/wenzi49312/article/details/8537727
mysql的多線程安全問題
1 開啟事務之前需要rollback 連接句柄。(清理垃圾)
2 mysql_ping 失敗,程序需要處理重連邏輯;
3 mysql_query()執行的SQL語句是一個以‘/0’結尾的字符串,而mysql_real_query()執行的字符串長度是參數指定的,因此,前者不能不能包含二進制數據(二進制數據中可能會包含‘/0’,導致被認為到達字符串末尾)
實際使用中,推薦使用mysql_real_query
4 mysql C API 中SQL不需要 ';' 結尾;
5 mysql 轉義;(老問題了)
6 所有update 語句,建議后邊調用函數判斷受影響的行數,是否是自己預期值;
7 mysql_real_connect 需要設置連接超時時間,特別是處理重連邏輯的時候,以免程序堵死;
8 程序rollback時候, 需要習慣性的校驗應用的錯誤碼,避免錯誤碼沒有賦值,調用者以為調用成功,造成漏洞;
9 多線程環境下使用libmysqlclient_r 庫,非libmysqlclient 庫
10 mysql_real_connect/mysql_init 多線程環境下調用需要加鎖;
11 使用mysql_real_escape_string, 需要注意目標緩沖區是 2*n+1 大小;
12 mysql_store_result 這個函數是分配的內存的。 使用完需要釋放,避免內存泄露;
13 mysql的事務盡量小,使用完,立即commit或rollback.不要起一個過大的事務。
14 mysql的隔離級別注意使用 Read Commited。不然會產生鎖間隙的問題。
15 避免嘗試去鎖一個不存在的記錄,for update語句where條件請使用主鍵(鎖定一個非主鍵,會默認同時鎖定一個主鍵,這是造成很多死鎖的原因)。避免過多的for update。
16 select語句必須使用索引,where條件避免使用 or 或者在條件中運用運算表達式,會造成索引失效。
17 聯合索引可以替代單獨的索引。如果已有聯合索引,不需要重復建立單獨的索引。索引過多會導致插入變慢。注意是聯合索引的第一個可以省略。 避過(f1,f2),可以省略f1的單獨索引,但是不能省略f2的單獨索引。
18 where條件,結果集不要太大,如果超過30%,索引會時效,會導致mysql掃描全表。不確定時,請用explain做檢測。
19 mysql單表記錄保持在1000W以下,以獲得較好的性能。
20 mysql數據庫鏈接數不能過多,請保持在200以下。
21 修改mysql 鎖等待時間,默認為50s,避免for update等待時間超長,造成系統阻塞 innodb_lock_wait_timeout(修改這個屬性需要重啟數據庫)
22 如果啟用事務,可以不必顯示的設置set autocommit=0,即使當時autocommit模式為1(直接提交模式),可以通過begin/commit來隱式的調用。
如果不使用事務,則必須顯示的調用 set autocommit=1.因為不能確定,是否某長鏈接中,有人設置了set autocommit=0.