故障現象
- PHP-FPM 進程數暴增報警
- 根因:SQL
SELECT id FROM feed_comment_info_id_0000 WHERE obj_id=101 AND type=1 未用索引
ANALYZE TABLE 後恢復正常
排查過程
1. 排除客戶端顯示問題
SET NAMES utf8; -- 客戶端同步 utf8
SELECT * FROM ... -- 仍顯示亂碼,排除顯示層問題
2. 定位存儲層亂碼來源
- 用戶確認:資料插入正常,UPDATE 後變亂碼
- Binlog 顯示 UPDATE 語句以
latin1 寫入中文內容
- 全查詢日誌揭露:應用連線未執行
SET NAMES,直接 SELECT 導出資料
- 預設
character_set_results=latin1 導致中文變問號,再 UPDATE 回寫造成永久損壞
Cardinality 異常根因分析
| 指標 | 異常值 | 正常值 | 說明 |
| Cardinality | 6216(實際行數 2 倍) | ≈ 實際不重複值數 | 統計資訊偏離導致優化器誤判索引選擇性 |
| 引擎 | InnoDB | - | InnoDB Cardinality 為估算值,每次 SHOW INDEX 可能不同 |
Cardinality 核心知識點
- 定義:索引中不重複值的估算數量
- MyISAM:精確值;InnoDB:隨機採樣估算(預設 8 頁)
- 影響:
Cardinality / Rows 越接近 1,優化器越傾向使用該索引
- 更新時機:
ANALYZE TABLE、mysqlcheck -Aa、大量 DML 後自動觸發(InnoDB 修改 10% 行數)
- 查看:
SHOW INDEX 或 information_schema.STATISTICS
解決方案與預防
- 即時修復:
ANALYZE TABLE feed_comment_info_id_0000
- 長期預防:
- 應用層強制
SET NAMES utf8mb4(連接池初始化)
- 監控
Cardinality 偏離度,定期維護
- InnoDB 5.6+ 可調
innodb_stats_persistent=ON 持久化統計資訊
- 上一篇文章: MySQL straight_join 優化實戰:強制驅動表順序解決檔案排序瓶頸
- 下一篇文章: MySQL 磁碟空間優化:表結構、存儲與維護四大維度建議
Copyright ©
程式碼之家 All Rights Reserved