MySQL 開發規範 35 條鐵律,涵蓋命名、類型、索引、SQL 寫法、架構設計、安全與流程,源自一線大廠 DBA 團隊實戰沉澱,違者代碼上線受阻、效能事故由開發負責。建議列入專案 CONTRIBUTING.md、Code Review 清單與 CI 檢查腳本。
一、命名與基礎規範 (1-5)
- 小寫+下劃線: 庫/表/欄位全小寫,單詞用
_ 分隔。lower_case_table_names=0 (Linux 預設) 區分大小寫,混用極易生成 abc/Abc/ABC 共存災難。
- 長度 ≤ 32 字符: 雖支援 64 字符,但統一限制 32 字符,利於辨識、傳輸、工具顯示。
- 強制 InnoDB: 5.5+ 預設引擎,支援事務、行鎖、MVCC、崩潰恢復、多核/大記憶體/SSD 優化、熱備份,全方位優於 MyISAM。
- 禁用保留字: 避免
order、group、key 等作識別符,否則 SQL 需反引號包裹,Shell 腳本轉義地獄。
- 禁用分區表: 分區鍵限制多、DDL/SHARDING/單表恢復極其困難,改用業務層手動 Sharding。
二、資料類型選型 (6-11)
- 非負數用 UNSIGNED: 同位寬下正數範圍翻倍,
TINYINT UNSIGNED 0-255 替代 TINYINT -128-127。
- IPv4 用 INT UNSIGNED: 4 Bytes vs CHAR(15) 15 Bytes,整數運算快 10 倍。轉換函數
INET_ATON()/INET_NTOA()。IPv6 用 DECIMAL(39,0) 或雙 BIGINT。
- TINYINT 代替 ENUM: ENUM 修改需 DDL 鎖表、數值型枚舉值易混淆預設值。
- 大小寫敏感字串用 VARBINARY: 無字符集開銷、比較快、預設區分大小寫。
- INT(4) 僅是顯示寬度: 儲存固定 4 Bytes,
INT(3) 顯示補空格,不影響範圍,客戶端多不支援。
- 時間類型精選: 年→
YEAR、日期→DATE、時間(秒)→TIMESTAMP (4 Bytes、自動初始化/更新)、DATETIME (8 Bytes) 仅用於 2038 年後或無時區需求。
三、欄位與表設計 (12-15)
- 全欄位 NOT NULL: NULL 需額外 bitmap、B+ 樹不存 NULL 降低索引效率、應用層判空麻煩。用 0、空串、特殊值替代。
- 冷熱分離拆大欄位:
TEXT/BLOB/JSON、低頻欄位拆獨立表 (1:1),熱表窄、全內存、緩存命中率高。
- 嚴禁明文存密碼: 必須鹽值+慢雜湊 (bcrypt/scrypt/Argon2),防字典攻擊/彩虹表/內部洩露。
- 必有主鍵,推薦 UNSIGNED AUTO_INCREMENT: 無主鍵 InnoDB 隱式產生 6 Bytes RowID,定位困難、基於行複制效率低。
四、索引規範 (16-19)
- 禁冗餘索引:
(a,b,c) 覆蓋 (a,b),後者冗餘,增加維護/IO/空間。
- 禁重複索引:
PRIMARY KEY(a) + UNIQUE KEY(a) 重複,無收益累贅。
- 低基數欄位不建索引: 「性別」、「狀態」等基數 < 100,全表掃描反而快,索引累贅。
- 善用覆蓋索引: 輔助索引含所有查詢欄位,避免回表。InnoDB 輔助索引存主鍵值,覆蓋索引單次 B+ 樹查找完成。例:
INDEX(uid,email) 覆蓋 SELECT email FROM user WHERE uid=?。
五、SQL 寫法規範 (20-26)
- IN 代替 OR: IN 列表值 < 1000,MySQL 內部排序後範圍查找,優於 OR。
- 字符集 UTF8MB4: 統一通用、無轉碼亂碼風險、支援 Emoji。漢字 3 Bytes、英文 1 Byte。
- UNION ALL 代替 UNION: 免排序去重,效能倍增。
- 禁
ORDER BY RAND(): 生成偽欄位、全表排序、產生磁盤臨時表,極慢。改用 WHERE id >= (SELECT FLOOR(RAND() * (SELECT MAX(id) FROM t))) 等方案。
- 分頁優化兩大模式:
- 模式一 (小結果集/複雜條件):
SELECT * FROM t WHERE ... ORDER BY gmt_create LIMIT 0,15 — 一次性取全欄位排序,隨翻頁深度線性劣化。
- 模式二 (大結果集/有覆蓋索引):
SELECT t.* FROM (SELECT id FROM t WHERE ... ORDER BY gmt_create LIMIT 0,15) a JOIN t ON a.id=t.id — 覆蓋索引取 ID 排序分頁,再回表取欄位,每頁耗時恆定。
- 禁止 SELECT *: 只取必要欄位,減少網傳、利用覆蓋索引、結構變更不影響應用。
- 禁不確定函數:
NOW()/RAND()/SYSDATE()/CURRENT_USER() 導致主從不一致 (Statement 複制)、Query Cache 失效。
六、架構與流程 (27-35)
- 分庫分表策略: 千庫十表、十庫百表等預案,利於後期水平拆分、利用 MySQL 多線程複制。
- 批量 SQL 減少交互:
INSERT ... ON DUPLICATE KEY UPDATE、REPLACE INTO、INSERT IGNORE、INSERT INTO VALUES(),(),()。
- 拆複雜 SQL、避免大事務: 簡單 SQL 易用 Query Cache、減少鎖時間 (特別是 MyISAM)、利用多核 CPU。
- 同表多 ALTER 合併:
ALTER TABLE t ADD COLUMN b VARCHAR(10), ADD INDEX idx_aa(aa); 單次鎖表重建。
- 禁存儲過程/觸發器/視圖/自定義函數: 效能問題、未知 Bug 多、DDL/SHARDING 極難、業務邏輯下沉限制演進。
- 禁 super 權限應用帳號: 導致
read_only 失效、詭異問題難追蹤,安全第一。
- 上線建表/改表需提供全量 SQL: 包含 INSERT/UPDATE/DELETE,DBA 需審核所有訪問路徑 (不只是 SELECT)。
- 業務邏輯不下沉 DB: DB 是有狀態服務,變更慢、擴展難。邏輯前置至應用層/中間層,DB 純存儲,實現邏輯存儲分離。
- 建表範本參考: 見附圖,含主鍵、索引、約束、註解、引擎、字符集完整規範。
落地執行建議
- 將 35 條規範轉為
SQLFluff/sql-lint 規則集,接入 CI 阻斷不合規 SQL。
2. 設計評審階段 DBA 必簽名,產出《索引設計文檔》、《分表路由規則》。
3. 定期 (月度) 抽查慢查詢、索引使用率、表碎片率,產出《資料庫健康報告》。
4. 新人入職必考規範,老員工季度重溫,建立「規範文化」而非「檢查文化」。
規範不是束縛,而是團隊協作的「通用語言」與系統穩定的「護欄」。內化於心,外化於碼,方能行穩致遠。