MySQL 有哪些優點與缺點,何時適合使用?
MySQL 是一種關聯式資料庫管理系統,可用於一般 Web 服務和線上交易處理(OLTP),尤其是在使用 InnoDB 儲存引擎及其交易、列級鎖定和一致性讀取等功能時。另一方面,讀取複寫預設為非同步,高可用性組態、複雜查詢與分割也都有設計和營運上的限制。只有當這些優勢符合工作負載和團隊的維運能力時,才會成為真正的優勢。dev.mysql.com dev.mysql.com
評估 MySQL 時,與其單純問它是否是「快速的資料庫」,更準確的作法是考量資料如何讀寫、發生故障時必須保證什麼,以及結構描述將變得多複雜。以下討論依循 MySQL 8.4 官方文件的範圍。實際行為可能因版本、儲存引擎、組態和複寫拓撲而異。dev.mysql.com
MySQL 是什麼類型的資料庫?
關聯式資料庫會將資料儲存在由資料列和資料欄組成的資料表中,並使用 SQL 查詢語言管理資料表之間的關係。例如,線上商店可使用 customers、orders 和 order_items 等資料表,管理客戶、訂單和訂購商品之間的關係。許多情況需要將多項變更組成單一操作,例如建立訂單、扣減庫存及記錄付款狀態。
儲存引擎在 MySQL 中很重要。儲存引擎是負責資料表如何儲存、鎖定及復原的元件。尤其是 InnoDB,作為 MySQL 的預設儲存引擎,提供 ACID 交易、提交與復原、當機復原、列級鎖定、多版本並行控制(MVCC)及外鍵。因此,通常與 MySQL 交易可靠性相關的說法,往往是指使用正確設定的 InnoDB 資料表的 MySQL。dev.mysql.com
ACID 是交易預期特性的統稱。原子性表示整個操作要麼成功,要麼取消。一致性表示已定義的資料規則會獲得維持。隔離性控制同時執行的操作彼此造成的影響;持久性則表示已提交的結果必須能在故障後保留。MySQL 的 ACID 特性也受到引擎、組態、硬體與營運程序影響,因此不應只因名稱就認為它會自動處理所有故障情境。dev.mysql.com
為什麼 InnoDB 交易與並行性是優勢?
OLTP 指的是請求頻繁且相對短暫的工作負載,例如接收訂單、更新會員資訊或變更付款狀態。在這種環境中,許多使用者可能會同時修改相同類型的資料,因此重要的是安全地將資料變更分組,並將衝突範圍維持在盡可能小的程度。
由於 InnoDB 提供交易提交、復原與當機復原,應用程式可設定為在例如建立訂單並扣減庫存的過程中,若某一個步驟失敗就復原整個交易。列級鎖定會視需要鎖定特定資料列,與廣泛鎖定整張資料表相比,可能更有利於允許並行作業。然而,當多個操作經常競爭相同資料列或相鄰資料範圍時,等待和衝突不會因此消失。dev.mysql.com
MVCC 透過使用多個資料版本提供一致性讀取。這並不單純表示讀取和寫入永遠不會互相干擾。可觀察到的結果與鎖定行為可能因交易的隔離等級、執行的 SQL 陳述式,以及是否使用鎖定讀取而有所不同。因此,在處理並行性問題時,不應只檢查引擎名稱。請先在業務規則中定義:哪些讀取必須看到最新值,以及哪些更新必須互斥。
外鍵是一種約束,可協助確保某個資料表中的值會參照另一個資料表中已存在的資料列。例如,它可強制訂單上的客戶 ID 指向實際存在的客戶。這有助於減少無效參照,但也表示必須預先仔細設計刪除與更新規則及資料表結構。若計畫日後導入分割,也必須檢查涉及外鍵的相容性限制。dev.mysql.com dev.mysql.com
開發環境與存取控制有哪些優勢?
MySQL 為 C/C++、Java、PHP、Python、Ruby 和其他語言提供多種用戶端協定與 API。因此,已使用這些語言和工具的應用程式可選擇建立連線層,並且可能相對容易建立 Web 應用程式與資料庫之間的基本路徑。不過,特定語言有 API 並不代表連線集區、錯誤重試、字元集與時區處理已正確設定。應用程式的資料存取方法必須另外驗證。dev.mysql.com
權限系統也是營運設計的一部分。MySQL 提供全域、資料庫和物件層級的權限,以及動態權限。可藉此分離角色:例如,僅授予應用程式帳戶特定資料表所需的讀寫權限,而將備份與管理工作使用不同帳戶。最小權限原則是有用的設計原則,可在帳戶遭入侵或程式發生錯誤時限制影響範圍。dev.mysql.com
然而,將權限劃分得更精細,並不會因此完成安全性工作。實務上,必須管理哪些帳戶擁有哪些權限、管理員帳戶和應用程式帳戶是否分離,以及由什麼程序管理權限變更。換言之,MySQL 的權限功能提供控制機制,但依據業務角色進行指派的責任仍由維運工作承擔。
索引和分割能解決什麼問題?
索引是一種資料結構,旨在減少為尋找目標資料列而掃描整張資料表的需求。例如,如果經常需要依訂單編號找出單筆訂單,該資料欄上的索引可能有所幫助。多欄索引對於以多個資料欄共同作為條件的查詢可能有用,但資料欄順序和實際查詢述詞都很重要。InnoDB 每張資料表最多支援 64 個次要索引,每個多欄索引最多支援 16 個資料欄。dev.mysql.com
不過,建立越多索引並不會自動變得更好。索引會占用儲存空間,在插入、更新或刪除資料列時也必須維護。支援的索引數量上限是技術限制,不是設計目標。能縮短搜尋路徑的索引是否真的必要,以及它會為寫入路徑增加多少負擔,應根據具代表性的查詢和資料分布來評估。
字串索引也有實體限制。InnoDB 索引索引鍵前置詞的限制通常是 3,072 位元組,但依資料列格式而定,可能降至 767 位元組。若嘗試使用每個字元儲存大小較大的字元集(例如 utf8mb4)為長字串建立索引,此限制可能影響結構描述設計。尤其重要的是,這是以位元組為基礎的限制,而不是字元數限制。dev.mysql.com
分割是一項依據定義規則將單一資料表儲存在多個分割區的功能。如果條件符合分割規則,分割區剪除可以排除 MySQL 不需要搜尋的分割區。例如,對於依日期範圍查詢的大型歷史資料表,若資料表依日期分割,便可考慮一種能縮小特定期間搜尋目標範圍的設計。dev.mysql.com
這不表示每個大型資料表都應該分割。如果常用條件不符合分割索引鍵,預期的目標資料縮減效果可能不會出現。分割也會為營運、索引鍵設計和約束引入額外規則,因此最好先比較問題能否透過較簡單的索引和查詢改進解決。
分割和全文搜尋有哪些限制?
在 MySQL 8.4 中,InnoDB 和 NDB 儲存引擎支援分割。已分割的 InnoDB 資料表不能具有外鍵,也不能成為其他資料表外鍵參照的目標。此外,分割索引鍵中使用的每個資料欄都必須是每個唯一索引鍵(包括主索引鍵)的一部分。當您嘗試分割訂單資料表等具有密集參照關係的核心資料表時,此條件可能大幅改變資料模型。dev.mysql.com
全文搜尋是依單字搜尋文字的功能。MySQL 在 InnoDB 和 MyISAM 中支援全文搜尋,但不支援已分割的資料表。因此,若預期同一張資料表同時需要長篇文件的搜尋功能,以及大規模歷史資料的分割功能,應儘早確認此組合是否可行。日後新增功能可能需要拆分資料表或變更搜尋架構。dev.mysql.com
這些限制不只是顯示 MySQL 缺少功能,而是表示各項功能未必能獨立組合使用。您可以逐一檢查外鍵、唯一索引鍵、分割索引鍵和全文搜尋的需求。避免只依據單一功能的好處決定結構描述會更安全。
如何利用複寫進行讀取擴充與備份?
複寫是一種將變更從一台伺服器傳送至另一台伺服器的架構。通常,來源伺服器會記錄變更,而複本伺服器會套用它們。將部分讀取請求分散到多個複本,可降低來源伺服器的讀取負載,也可考慮將備份或分析工作卸載至複本。dev.mysql.com
GTID 是一種透過為每筆交易指派識別碼來處理複寫位置的方法。以 GTID 為基礎的複寫可協助減少手動對齊二進位日誌檔案名稱和位置的負擔。不過,建立複寫拓撲與監控複寫延遲及操作復原程序是不同的事情。您必須決定哪台伺服器處理寫入、哪些伺服器可提供讀取,以及發生延遲時應如何處理。dev.mysql.com
預設複寫是非同步的。這表示在來源端提交完成的瞬間,無法保證每個複本都已套用相同變更。例如,使用者變更地址後立即被導向複本的查詢,可能顯示先前的地址。這可視為讀後寫一致性問題。必須取得最新資料的請求,需要一項將其導向來源端或考量複本套用狀態的政策。dev.mysql.com
半同步複寫採用一種做法:來源端收到複本已接收並記錄交易事件的確認。它是預設非同步複寫的替代方案,但不表示所有需求都會變成完全同步。討論強同步需求時,請明確定義所需的一致性層級、可接受的延遲範圍和故障行為,然後也考慮 NDB Cluster 等其他選項。dev.mysql.com
Group Replication 會自動解決高可用性問題嗎?
高可用性是透過組態讓服務在部分伺服器或網路發生故障時仍可持續運作的目標。Group Replication 可管理群組成員資格、在單一主要節點模式中自動選出主要節點,或支援多主要節點組態。它與 InnoDB Cluster 和 MySQL Router 結合後能形成高可用性拓撲的能力,是 MySQL 的重要選項。dev.mysql.com
然而,資料庫伺服器內的共識與應用程式連線容錯移轉並不是同一個問題。Group Replication 不包含將發生故障的用戶端切換至健康成員的功能。應用程式需要 MySQL Router、負載平衡器、連接器或自訂中介軟體來決定連線位置,而且該層也必須考量故障、重試和狀態更新來進行營運。dev.mysql.com
因此,當您聽到「自動容錯移轉」時,至少應分別詢問三個問題。第一,能否選出主要節點?第二,新的應用程式連線是否會前往健康的伺服器?第三,進行中的請求及使用者重試的請求會看到什麼結果?第一個問題有相應功能,並不會自動保證後兩者。
多主要節點組態也不能單純理解為提高寫入效能的開關。當允許從多個位置進行寫入時,還必須從業務層級設計如何避免或處理對相同資料的並行修改,以及應用程式寫入路徑必須遵循哪些規則。高可用性是營運上的考量,除了功能選擇外,也包括故障演練、可觀測性和復原程序。
為什麼複雜查詢會增加調校負擔?
最佳化器是一個從多種執行 SQL 陳述式的方法中,選擇預估成本最低之執行計畫的元件。例如,它會決定先使用哪個索引,以及資料表的連接順序。MySQL 的成本型最佳化器在統計資訊不足時可能依賴估算,因此可能選擇與人們預期不同的計畫。dev.mysql.com
隨著連接資料表數量增加,候選執行計畫的數量可能呈指數成長。在這種情況下,不僅資料擷取本身,探索合適計畫所需的最佳化時間也可能成為瓶頸。因此,對於經常執行複雜分析查詢或大量連接的系統,很難僅根據 SQL 能否在語法上執行來判定適用性。測試應使用實際資料分布和具代表性的條件。dev.mysql.com
EXPLAIN 是用於檢查查詢所選執行計畫的工具。當結果緩慢時,請先檢查述詞、連接條件、使用中的索引和預估資料列數。必要時,您可以重新整理統計資訊,或調整索引和查詢結構。索引提示和最佳化器控制功能也可使用,但強制使用特定計畫的方法必須持續驗證,以確保在資料變更後仍然有效。dev.mysql.com dev.mysql.com
這不表示無法在 MySQL 中進行複雜分析。不過,若大規模多資料表連接和分析查詢是核心工作負載,務實的作法是預先比較可投入多少時間進行調校、是否應將分析卸載至複本,以及是否應新增專用分析系統。相反地,對於主要由短暫且可預測交易組成的服務,此負擔可能相對較小。
何時應謹慎使用預存程序?
預存程序是儲存在資料庫伺服器上並於其中執行的程序或函式。它們可以讓部分資料處理規則更接近資料庫,但可在 SQL 陳述式中使用的預存函式具有一些限制。例如,預存函式不能使用會傳回結果集的陳述式。用於計算單一傳回值的函式,與傳回多筆資料列的查詢操作有不同目的和使用模式。dev.mysql.com dev.mysql.com
在複寫環境中,預存程序的確定性也很重要。確定性表示相同輸入會產生相同結果。會隨時間或環境狀態而變化的非確定性或時間相依程序,可能依複寫方法產生可重現性問題,使用以陳述式為基礎的複寫時尤其需要注意。將業務邏輯置於資料庫時,也應檢視該邏輯在複寫和當機復原期間能否產生相同結果。dev.mysql.com
是否使用預存程序,重點不在於功能是否存在,而在於變更、測試和部署的責任應放在哪裡。當規則分散在應用程式程式碼和資料庫程序之間時,追蹤和測試可能變得更加複雜。反過來說,它們可能適用於接近資料完整性的簡單規則。關鍵問題在於,團隊是否能理解並管理這些規則執行的位置及其對複寫的影響。
MySQL 何時適合使用,何時應審慎評估?
下表不是產品排名,而是用於檢查需求與功能是否相符的觀點。
| 情境 | 可考慮的 MySQL 方案 | 需要一併檢查的條件 |
|---|---|---|
| 一般 Web 服務以及訂單或會員處理 | 可使用 InnoDB 交易、列級鎖定、MVCC 和外鍵。 | 必須設計交易邊界與並行更新規則。 |
| 讀取密集型服務 | 來源端—複本複寫可分離讀取、備份和分析負載。 | 需要針對複本延遲和最新讀取制定政策。 |
| 需要具備容錯組態的服務 | 可考慮結合 Group Replication、Router 與相關元件的拓撲。 | 連線容錯移轉、重試和故障程序必須另外營運。 |
| 依日期範圍查詢的大型歷史資料 | 分割區剪除可依條件減少目標分割區。 | 請先檢查外鍵、唯一索引鍵和全文搜尋限制。 |
| 連接許多資料表、以分析為主的工作負載 | 可使用 SQL 執行及索引和最佳化器控制功能。 | 評估執行計畫驗證及持續調校的成本。 |
表格前 3 列以 InnoDB、複寫和 Group Replication 的官方功能為依據。最後 2 列也反映分割和最佳化器的行為與限制。dev.mysql.com dev.mysql.com dev.mysql.com dev.mysql.com dev.mysql.com
特別是,如果強大的多區域一致性或不中斷容錯移轉是核心需求,就不應只根據預設非同步複寫做出決定。請明確指定資料新鮮度需求、可接受的延遲、故障期間是否仍可寫入,以及應用程式容錯移轉路徑,再比較 Group Replication、NDB Cluster 或其他分散式選項。反之,若您希望在單一服務區域內可靠處理一般讀寫交易,並視需要將讀取分散至複本,MySQL 的功能組合可以是務實的起點。dev.mysql.com dev.mysql.com
導入前應檢查什麼?
首先,確認核心資料表使用 InnoDB,且交易邊界符合業務單位。必須一同成功或失敗的變更(例如建立訂單)應定義為一筆交易,同時避免不必要的長時間交易,以免增加鎖定持續時間。其次,列出最常見的讀寫查詢,並確認所需索引是否符合實際述詞和排序方式。dev.mysql.com dev.mysql.com
第三,若使用複寫,請決定「哪些讀取可由複本提供」。一種做法是區分需要新鮮資料的請求(例如付款後立即檢查狀態),以及可容忍某些延遲的清單和統計查詢。第四,若需要高可用性組態,請測試故障情境,不僅測試資料庫成員選舉,也測試應用程式連線實際會移至何處。dev.mysql.com dev.mysql.com
第五,假設資料將持續成長,檢查分割是否真的必要,以及能否接受外鍵與唯一索引鍵限制。若同時需要長字串搜尋、全文搜尋和分割,請先檢視功能之間的限制。最後,若複雜連接是核心,請在接近正式環境資料的條件下檢查 EXPLAIN,並評估是否具備持續管理統計資訊和索引變更的能力。dev.mysql.com dev.mysql.com dev.mysql.com
結論:應如何評估 MySQL 的優缺點?
MySQL 的優勢包括以 InnoDB 為基礎的交易與並行控制、與廣泛開發環境的整合、透過複寫分散讀取,以及建立高可用性組態的官方功能。這些功能可為一般 Web 服務和典型 OLTP 工作負載提供有意義的基礎。dev.mysql.com dev.mysql.com dev.mysql.com
同時,預設複寫可能產生的延遲、高可用性連線容錯移轉的額外設計、複雜查詢的執行計畫驗證,以及涉及索引、分割和全文搜尋的限制,都必須視為實際成本。歸根結底,MySQL 並不是具有普遍正面特質的選擇。只有當資料一致性需求、讀寫比例、結構描述限制、故障應對層級,以及調校與維運能力都明確具體時,才能評估它是否適合。dev.mysql.com dev.mysql.com dev.mysql.com