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 TABLE、CREATE INDEX和DROP INDEX操作。OPTIMIZE TABLE操作可以使用ALTER TABLE ... ENGINE = InnoDB代替。主節點同步至備節點或唯讀執行個體時,備節點或唯讀執行個體上本功能不生效。
開啟本功能會降低DDL的優先順序,因此無法擷取MDL鎖導致DDL失敗的機率會增大。
參數管理
參數說明
您可以通過loose_rds_nonblock_ddl_retry_interval和loose_rds_nonblock_ddl_lock_wait_timeout參數來控制和調整非阻塞DDL功能。開啟非阻塞DDL功能後,DDL線程會間歇性多次嘗試擷取MDL鎖,擷取失敗則釋放MDL請求並陷入等待。
參數名稱 | 說明 |
|
|
|
|
修改參數
訪問RDS執行個體列表,在上方選擇地區,然後單擊目標執行個體ID。
在左側導覽列中單擊參數設定。
在可修改參數頁簽內搜尋待修改參數,並配置參數值。
單擊確定,然後單擊提交參數,並在彈出的視窗中選擇生效的時間段。
功能效果
測試方法
本文採用sysbench工具類比資料庫執行個體上的資料訪問,對比開啟與關閉非阻塞DDL功能時,執行DDL對業務的影響。具體測試步驟如下:
使用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啟動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啟動一個會話,在待執行的目標表上開啟長事務,以阻塞後續的 DDL 操作。
SELECT SLEEP(60) FROM sbtest1 LIMIT 1;啟動另一個會話,在關閉非阻塞DDL功能的情況下執行如下DDL操作,觀察TPS變化。
ALTER TABLE sbtest1 ENGINE = InnoDB; -- 預期:該DDL線程由於無法擷取MDL鎖被阻塞。開啟非阻塞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鎖,會話不會被完全阻塞,系統穩定性得到保障。

