早期 MySQL 為性能犧牲了部分 SQL:1999 標準功能。本文梳理缺失項、原因、官方規劃及應用層繞過方案。注意:MySQL 5.1+ 已陸續支持大部分功能,文中標註現狀。
| 功能 | 缺失版本 | 支持版本 | 替代方案 |
|---|---|---|---|
| 子查詢 | ≤ 4.1 | 4.1+ | 改寫為 JOIN / 臨時表 |
| 事務/Commit/Rollback | MyISAM 永不 | InnoDB (3.23+) | 用 InnoDB;MyISAM 用 LOCK TABLES + 相對更新 |
| 外鍵/引用完整性 | MyISAM 永不 | InnoDB (3.23+) | 應用層檢查;觸發器 (5.0+) 實現級聯 |
| 存儲過程/觸發器 | ≤ 5.0 | 5.0+ | 應用層封裝;事件調度器 (5.1+) |
| 視圖 | ≤ 5.0 | 5.0+ | 應用層封裝查詢 |
| 行級鎖/權限 | 所有版本 | InnoDB 行鎖;GET_LOCK() 協作鎖 | GET_LOCK/RELEASE_LOCK 實現邏輯鎖 |
-- 註釋 | ≤ 3.22 | 3.23+ (需空格 -- ) | 用 # 或 /* */ |
經典庫存扣減並發問題:
-- 方案 A:表鎖串行化(MyISAM 唯一選擇) LOCK TABLES inventory WRITE; SELECT quantity FROM inventory WHERE item='shirt'; UPDATE inventory SET quantity=quantity-3 WHERE item='shirt'; UNLOCK TABLES; -- 方案 B:相對更新(無需鎖,單語句原子) UPDATE inventory SET quantity=quantity-3 WHERE item='shirt';
轉賬等強一致性場景**必須用 InnoDB 事務**,MyISAM 無法通過日志手工恢復保證原子性。
MyISAM 僅解析 FOREIGN KEY 子句不報錯,**不創建約束、不級聯**。
DELETE FROM child WHERE parent_id=?。ON DELETE CASCADE/SET NULL/RESTRICT。邏輯下沉到服務器可減少網絡往返、統一業務規則。早期替代:
「缺失功能非缺陷,乃權衡取捨。」
MySQL 選擇**簡單、快速、穩定**的核心,將複雜功能推遲至成熟時實現,或留給應用層解決。這造就了其在 Web 2.0 時代的統治地位。
MySQL 5.7/8.0 已完整支持上述所有標準功能。**新項目無理由避開**,僅維護極舊版本時參考本文替代方案。