文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  NDB 叢集中與交易處理相關的限制

25.2.7.3 NDB 叢集中與交易處理相關的限制

NDB 叢集在處理交易方面存在一些限制。這些限制包括以下內容:

  • 交易隔離等級。 NDBCLUSTER 儲存引擎僅支援 READ COMMITTED 交易隔離等級。(例如,InnoDB 支援 READ COMMITTEDREAD UNCOMMITTEDREPEATABLE READSERIALIZABLE。)您應該記住,NDB 以逐列為基礎實作 READ COMMITTED;當讀取請求到達儲存該列的資料節點時,傳回的是當時該列最後提交的版本。

    永遠不會傳回未提交的資料,但是當修改多列的交易與讀取相同列的交易同時提交時,執行讀取的交易可能會觀察到這些列的不同列的之前值、之後值或兩者,原因是給定列的讀取請求可能在另一個交易提交之前或之後處理。

    為了確保給定的交易僅讀取之前或之後的值,您可以使用 SELECT ... LOCK IN SHARE MODE 來強制執行列鎖定。在這種情況下,鎖定會一直保留到擁有該鎖定的交易提交為止。使用列鎖定也可能導致以下問題:

    • 鎖定等待逾時錯誤的頻率增加,並降低並行性

    • 由於讀取需要提交階段,因此交易處理負擔增加

    • 可能會耗盡可用的並行鎖定數量,該數量受 MaxNoOfConcurrentOperations 限制

    NDB 對所有讀取使用 READ COMMITTED,除非使用諸如 LOCK IN SHARE MODEFOR UPDATE 之類的修飾詞。LOCK IN SHARE MODE 會導致使用共用列鎖定;FOR UPDATE 會導致使用獨佔列鎖定。唯一索引鍵讀取的鎖定會由 NDB 自動升級,以確保自我一致的讀取;BLOB 讀取也會為了保持一致性而採用額外的鎖定。

    請參閱 第 25.6.8.4 節,「NDB 叢集備份疑難排解」,以瞭解 NDB 叢集實作交易隔離等級如何影響 NDB 資料庫的備份和還原。

  • 交易與 BLOB 或 TEXT 資料行。 NDBCLUSTER 僅將使用任何 MySQL 的 BLOBTEXT 資料類型的資料行值的其中一部分儲存在 MySQL 可見的資料表中;其餘的 BLOBTEXT 則儲存在單獨的內部資料表中,MySQL 無法存取該資料表。這會產生兩個相關問題,當您在包含這些類型的資料行的資料表上執行 SELECT 陳述式時,您應注意這些問題:

    1. 對於任何來自 NDB 叢集資料表的 SELECT:如果 SELECT 包含 BLOBTEXT 資料行,則 READ COMMITTED 交易隔離等級會轉換為具有讀取鎖定的讀取。這樣做是為了保證一致性。

    2. 對於任何使用唯一索引鍵查詢來擷取使用任何 BLOBTEXT 資料類型的任何資料行,並在交易中執行的 SELECT,在交易期間(即直到交易提交或中止為止)會對該資料表保留共用的讀取鎖定。

      使用索引或資料表掃描的查詢不會發生此問題,即使是針對具有 BLOBTEXT 資料行的 NDB 資料表。

      例如,考慮由下列 CREATE TABLE 陳述式定義的資料表 t

      CREATE TABLE t (
          a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
          b INT NOT NULL,
          c INT NOT NULL,
          d TEXT,
          INDEX i(b),
          UNIQUE KEY u(c)
      ) ENGINE = NDB,

      以下對 t 的查詢會導致共用的讀取鎖定,因為它使用了唯一索引鍵查詢:

      SELECT * FROM t WHERE c = 1;

      但是,此處顯示的四個查詢都不會導致共用的讀取鎖定:

      SELECT * FROM t WHERE b = 1;
      
      SELECT * FROM t WHERE d = '1';
      
      SELECT * FROM t;
      
      SELECT b,c WHERE a = 1;

      這是因為在這四個查詢中,第一個使用索引掃描,第二個和第三個使用資料表掃描,而第四個雖然使用主索引鍵查詢,但不會擷取任何 BLOBTEXT 資料行的值。

      您可以透過避免使用唯一索引鍵查詢來擷取 BLOBTEXT 資料行,或在無法避免此類查詢的情況下,盡快提交交易,以協助將共用讀取鎖定的問題降到最低。

  • 唯一索引鍵查詢與交易隔離。唯一索引是在 NDB 中使用內部維護的隱藏索引資料表實作的。當使用唯一索引存取使用者建立的 NDB 資料表時,首先會讀取隱藏的索引資料表,以尋找隨後用於讀取使用者建立的資料表的主索引鍵。為了避免在這種雙重讀取操作期間修改索引,會鎖定在隱藏索引資料表中找到的列。當更新使用者建立的 NDB 資料表中由唯一索引參照的列時,更新所執行的交易會對隱藏的索引資料表進行獨佔鎖定。這表示對相同(使用者建立的)NDB 資料表的任何讀取操作都必須等待更新完成。即使讀取操作的交易等級是 READ COMMITTED,也是如此。

    一種可以用來繞過可能封鎖讀取的方法是強制 SQL 節點在執行讀取時忽略唯一索引。這可以透過將 IGNORE INDEX 索引提示用作讀取資料表的 SELECT 陳述式的一部分來完成(請參閱 第 10.9.4 節,「索引提示」)。由於 MySQL 伺服器會為 NDB 中建立的每個唯一索引建立陰影排序索引,因此可以讀取排序索引,並避免唯一索引存取鎖定。產生的讀取與按主索引鍵提交的讀取一樣一致,傳回讀取該列時最後提交的值。

    透過排序索引讀取會降低叢集中資源的利用效率,並可能具有更高的延遲。

    也可以透過查詢範圍而非唯一值來避免使用唯一索引進行存取。

  • 回滾。沒有部分交易,也沒有交易的部分回滾。重複索引鍵或類似的錯誤會導致整個交易回滾。

    此行為與其他交易儲存引擎(例如可能會回滾個別陳述式的 InnoDB)的行為不同。

  • 交易和記憶體使用量。 如本章其他部分所述,NDB 叢集無法很好地處理大型交易;最好執行許多小型交易,每個交易包含少量操作,而不是嘗試執行包含大量操作的單一大型交易。在其他考量因素中,大型交易需要非常大量的記憶體。因此,許多 MySQL 陳述式的交易行為會受到影響,如下列清單所述:

    • TRUNCATE TABLENDB 資料表上使用時不具備交易性。如果 TRUNCATE TABLE 無法清空資料表,則必須重新執行直到成功。

    • DELETE FROM (即使沒有 WHERE 子句) 具備 交易性。對於包含大量列的資料表,您可能會發現使用多個 DELETE FROM ... LIMIT ... 語句來「分塊」刪除操作可以提高效能。如果您的目標是清空資料表,則您可能希望改用 TRUNCATE TABLE

    • LOAD DATA 語句。NDB 資料表上使用時,LOAD DATA 不具備交易性。

      重要事項

      當執行 LOAD DATA 語句時,NDB 引擎會以不規則的間隔執行提交,以更好地利用通訊網路。無法事先得知何時會進行此類提交。

    • ALTER TABLE 和交易。當複製 NDB 資料表作為 ALTER TABLE 的一部分時,複製的建立是不具交易性的。(無論如何,當複製被刪除時,此操作會被回滾。)

  • 交易和 COUNT() 函式。 當使用 NDB Cluster 複寫時,無法保證複本上 COUNT() 函式的交易一致性。換句話說,當在來源上執行一系列語句(INSERTDELETE 或兩者)以在單一交易中變更資料表中的列數時,在複本上執行 SELECT COUNT(*) FROM 資料表 查詢可能會產生中間結果。這是因為 SELECT COUNT(...) 可能會執行髒讀,而不是 NDB 儲存引擎中的錯誤。(有關更多資訊,請參閱錯誤 #31321。)