全部產品
Search
文件中心

ApsaraDB RDS:非阻塞DDL

更新時間:May 13, 2026

RDS MySQL支援非阻塞DDL(Non blocking DDL)功能,規避了DDL執行過程中因MDL鎖長時間擷取不成功導致的會話阻塞和串連堆積,提升DDL過程中執行個體的穩定性和可用性。

功能說明

背景:在MySQL中,DDL操作需要擷取目標表的MDL-X鎖,以確保中繼資料一致性。然而,當表上存在未提交事務或長查詢時,DDL線程會因無法立即擷取鎖而進入等待狀態(pending)。由於MDL-X鎖具有最高優先順序,pending狀態下的MDL-X鎖會阻塞目標表後續的所有訪問,引發會話阻塞、串連堆積和響應延遲等問題,嚴重時可能導致整個業務系統不可用。

簡介:RDS MySQL的非阻塞DDL通過修改DDL線程擷取和等待MDL鎖的策略,將“一次性長等待”改為“間歇性短等待”。在等待間歇中,DDL線程會釋放對MDL-X的請求,新會話允許訪問目標表,避免了DDL線程長時間阻塞其他會話對目標表的訪問。

適用範圍

資料庫版本需滿足以下要求才能開啟非阻塞DDL功能,當版本不符合要求時,可以升級升級核心小版本資料庫大版本

  • MySQL 8.4

  • MySQL 8.0且核心小版本大於等於20250531

使用非阻塞DDL功能時,有以下限制:

  • 當前僅支援ALTER TABLECREATE INDEXDROP INDEX操作。OPTIMIZE TABLE操作可以使用ALTER TABLE ... ENGINE = InnoDB代替。

  • 主節點同步至備節點或唯讀執行個體時,備節點或唯讀執行個體上本功能不生效。

  • 開啟本功能會降低DDL的優先順序,因此無法擷取MDL鎖導致DDL失敗的機率會增大。

參數管理

參數說明

您可以通過loose_rds_nonblock_ddl_retry_intervalloose_rds_nonblock_ddl_lock_wait_timeout參數來控制和調整非阻塞DDL功能。開啟非阻塞DDL功能後,DDL線程會間歇性多次嘗試擷取MDL鎖,擷取失敗則釋放MDL請求並陷入等待。

參數名稱

說明

loose_rds_nonblock_ddl_retry_interval

  • 描述:DDL線程擷取MDL鎖逾時重試的時間間隔。

  • 參數範圍:會話層級。

  • 資料類型:Integer

  • 預設值:0(表示非阻塞DDL功能不生效)。

  • 取值範圍:0~31536000,單位:秒。

  • 是否需要重啟執行個體:否。

loose_rds_nonblock_ddl_lock_wait_timeout

  • 描述:DDL 線程間歇性擷取MDL鎖的逾時時間。

  • 參數範圍:會話層級。

  • 資料類型:Integer

  • 預設值:1

  • 取值範圍:1~31536000,單位:秒。

  • 是否需要重啟執行個體:否。

修改參數

  1. 訪問RDS執行個體列表,在上方選擇地區,然後單擊目標執行個體ID。

  2. 在左側導覽列中單擊參數設定

  3. 可修改參數頁簽內搜尋待修改參數,並配置參數值。

  4. 單擊確定,然後單擊提交參數,並在彈出的視窗中選擇生效的時間段。

功能效果

測試方法

本文採用sysbench工具類比資料庫執行個體上的資料訪問,對比開啟與關閉非阻塞DDL功能時,執行DDL對業務的影響。具體測試步驟如下:

  1. 使用sysbench構建表並插入資料。

    sysbench oltp_read_write --db-ps-mode=auto --percentile=95 --mysql-host=$HOST --mysql-port=$PORT --mysql-user=$USER --mysql-db=$DB --tables=1 --table-size=50 --threads=16 prepare
  2. 啟動sysbench壓力測試類比線上業務。

    sysbench oltp_read_write --db-ps-mode=auto --percentile=95 --mysql-host=$HOST --mysql-port=$PORT --mysql-user=$USER --mysql-db=$DB --tables=1 --table-size=50 --threads=16 --report-interval=1 --time=100 run
  3. 啟動一個會話,在待執行的目標表上開啟長事務,以阻塞後續的 DDL 操作。

    SELECT SLEEP(60) FROM sbtest1 LIMIT 1;
  4. 啟動另一個會話,在關閉非阻塞DDL功能的情況下執行如下DDL操作,觀察TPS變化。

    ALTER TABLE sbtest1 ENGINE = InnoDB;
    -- 預期:該DDL線程由於無法擷取MDL鎖被阻塞。
  5. 開啟非阻塞DDL功能:設定loose_rds_nonblock_ddl_retry_interval參數值為 6,loose_rds_nonblock_ddl_lock_wait_timeout 參數值為1。執行相同的DDL操作,觀察TPS變化。

    ALTER TABLE sbtest1 ENGINE = InnoDB;
    -- 預期:該DDL線程可以擷取MDL鎖,不會完全被阻塞

測試結果

  • 關閉非阻塞DDL功能時,DDL線程無法擷取MDL鎖,會話被完全阻塞。

  • 開啟非阻塞DDL功能後,DDL線程可以間歇性地擷取MDL鎖,會話不會被完全阻塞,系統穩定性得到保障。

image.png

image