前言
這 22 條經驗來自長期 MySQL 開發與維護的一線總結,涵蓋連線管理、事務控制、SQL 寫法、索引設計、參數調優等核心領域。每一條都是踩坑後的血淚結晶,建議收藏備查。
連線與 API 使用(第 1-12 條)
- 事務開啟前先 Rollback:清理連線上的髒數據,避免上一個事務殘留影響當前邏輯。
- 處理 mysql_ping 失敗重連邏輯:長連線必須有心跳檢測與自動重連機制,防止連線中斷導致業務異常。
- 優先使用 mysql_real_query():支援二進制數據(含
\0),mysql_query() 遇 \0 會誤判字串結束。
- C API 執行 SQL 無需分號結尾:不同於客戶端工具,API 傳入的 SQL 字串不包含終止符。
- 嚴格做轉義防注入:使用
mysql_real_escape_string(),目標緩衝區大小至少 2*n+1。
- UPDATE 必須檢查影響行數:確認
mysql_affected_rows() 符合預期,防止靜默失敗。
- 設置連線超時:
mysql_real_connect 需設定超時,特別是重連邏輯中,避免進程卡死。
- Rollback 時校驗錯誤碼:防止錯誤碼未賦值導致調用方誤以為成功,造成數據不一致漏洞。
- 多線程用 libmysqlclient_r:非線程安全的
libmysqlclient 會導致崩潰或數據競爭。
- mysql_real_connect/init 多線程需加鎖:這兩個函數非線程安全,並發調用必須互斥。
- 結果集必須釋放:
mysql_store_result() 分配記憶體,用完需 mysql_free_result(),否則洩漏。
- 大量寫入分批 Commit:避免單一巨大事務鎖定過多資源,導致阻塞與回滾成本過高。
事務與隔離級別(第 13-15 條)
- 事務盡量小,用完即 Commit/Rollback:長事務是並發殺手。
- 推薦 Read Committed 隔離級別:避免 Repeatable Read 的間隙鎖導致死鎖與鎖擴大。
- FOR UPDATE 必須走主鍵:非主鍵條件會隱式鎖定主鍵,極易產生死鎖;盡量減少
FOR UPDATE 使用。
索引與查詢優化(第 16-18 條)
- WHERE 條件必須用到索引:避免
OR、函數運算、隱式轉換導致索引失效。
- 聯合索引替代單列索引:
(a,b) 可覆蓋 a 的單列查詢,但無法覆蓋 b;避免重複建立索引,索引過多拖慢寫入。
- 結果集超 30% 時優化器可能放棄索引:不確定時用
EXPLAIN 驗證,必要時用 FORCE INDEX。
架構與參數規劃(第 19-22 條)
- 單表行數控制在 1000 萬以內:超過則考慮分表或分區,保持查詢性能線性。
- 連線數建議 ≤ 200:過多連線導致線程切換開銷激增,必要時用連線池。
- 調整 innodb_lock_wait_timeout:預設 50s 過長,業務層面建議縮短至 5-10s,需重啟生效。
- 顯式管理自動提交模式:用事務時用
BEGIN/COMMIT 隱式關閉 autocommit;不用事務時顯式 SET autocommit=1,防止長連線殘留事務狀態。
總結
這 22 條規範若能貫徹落地,能解決 90% 以上的 MySQL 線上故障與性能問題。建議團隊將其內化為 Code Review 清單與上線檢查項,讓最佳實踐成為肌肉記憶。