PolarDB新增非阻塞DDL(Nonblock DDL)功能。Nonblock DDL規避了執行DDL過程中MDL鎖長時間獲取不成功導致的連接堆積和阻塞,有效地解決了DDL導致的鎖表問題。
背景信息
用戶在執行DDL操作的時候,若目標表存在未提交的長事務或大查詢,DDL將持續等待獲取MDL-X鎖。在PolarDB中由于MDL-X鎖具有最高優先級,DDL在等待MDL-X鎖的過程中,將阻塞目標表上所有的新事務,這將導致業務連接的堆積和阻塞,可能會造成整個業務系統崩潰的嚴重后果。PolarDB提供的Nonblock DDL功能,可以保證即使在無法獲得MDL-X鎖的情況下,依然允許新事務進入目標表,從而保證整個業務系統的穩定。
前提條件
PolarDB MySQL版集群需滿足如下條件之一:
PolarDB MySQL版8.0.1版本且Revision version為8.0.1.1.29及以上。
PolarDB MySQL版8.0.2版本且Revision version為8.0.2.2.12及以上。
您可以通過查詢版本號來確認集群版本。
注意事項
開啟Nonblock DDL功能會導致DDL的優先級降低,同時因MDL鎖獲取失敗從而導致執行DDL的失敗概率也會相應增大。
使用限制
PolarDB MySQL版8.0.1版本且Revision version為8.0.1.1.29及以上,以及8.0.2.2.12版本:
僅ALTER TABLE語句支持Nonblock DDL功能,應用于
ALTER TABLE table_name ADD INDEX index_name ( `column1`, `column2`, `column3` )
語句效果更佳。對于在InnoDB引擎上創建的表,需要使用
ALTER TABLE table_name engine=innodb
命令來代替OPTIMIZE TABLE table_name
命令進行碎片整理。
PolarDB MySQL版8.0.2版本且Revision version為8.0.2.2.13及以上:
ALTER TABLE、OPTIMIZE TABLE和TRUNCATE TABLE語句支持Nonblock DDL功能。
使用方法
您可以先通過loose_polar_nonblock_ddl_mode參數開啟Nonblock DDL功能,并通過loose_polar_nonblock_ddl_retry_times參數設置獲取MDL-X鎖超時重試的次數、loose_polar_nonblock_ddl_retry_interval參數設置獲取MDL-X鎖超時重試的時間間隔、loose_polar_nonblock_ddl_lock_wait_timeout參數設置獲取MDL-X鎖超時的時間。具體操作請參見設置集群參數和節點參數。參數說明如下:
參數 | 級別 | 說明 |
loose_polar_nonblock_ddl_mode | Session | Nonblock DDL功能開關。取值范圍如下:
|
loose_polar_nonblock_ddl_retry_times | Session | 設置獲取MDL-X鎖超時重試的次數。取值范圍:0~31536000。默認值為0(由參數 說明 該參數值建議設置為4194304。 |
loose_polar_nonblock_ddl_retry_interval | Session | 設置獲取MDL-X鎖超時重試的時間間隔。取值范圍:1~31536000。單位為秒。默認值為6。 |
loose_polar_nonblock_ddl_lock_wait_timeout | Session | 設置獲取MDL-X鎖超時的時間。取值范圍:1~31536000。單位為秒。默認值為1。 |
性能對比
本文檔對比了開啟和關閉Nonblock DDL功能對業務的影響情況,同時與使用外部工具gh-ost進行表結構變更也進行了性能對比。
測試工具
SysBench是一個跨平臺且支持多線程的模塊化基準測試工具,用于評估系統在運行高負載的數據庫時相關核心參數的性能表現。使用SysBench是為了繞過復雜的數據庫基準設置,甚至在沒有安裝數據庫的前提下,快速了解數據庫系統的性能。關于如何使用SysBench,請參見性能測試方法(OLTP)。
測試環境
一個規格為8核64 GB的標準版PolarDB MySQL版8.0版本的集群。
測試方法
使用SysBench創建1個測試表
sbtest1
,并插入1000000行數據。./oltp_read_write.lua --mysql-host="集群地址" --mysql-port=“端口號” --mysql-user=“用戶名” --mysql-password=“用戶密碼” --mysql-db="sbtest" --tables=1 --table-size=1000000 --report-interval=1 --percentile=99 --threads=8 --time=6000 prepare
通過SysBench中的
oltp_read_write.lua
模擬用戶業務。./oltp_read_write.lua --mysql-host="集群地址" --mysql-port=“端口號” --mysql-user=“用戶名” --mysql-password=“用戶密碼” --mysql-db="sbtest" --tables=1 --table-size=1000000 --report-interval=1 --percentile=99 --threads=8 --time=6000 run
在目標表
sbtest1
上開啟一個事務但不提交,該事務將持有目標表sbtest1
的MDL鎖。/* session 1 */ begin; select * from sbtest1;
在新會話中,開啟和關閉Nonblock DDL功能的條件下,分別對表
sbtest1
進行加列操作,觀察TPS的變化情況。/* session 2 */ alter table sbtest1 add column d int;
使用gh-ost工具進行加列操作,觀察TPS的變化情況(開啟Binlog)。
./gh-ost --assume-rbr --user="用戶名" --password="用戶密碼" --host="集群地址" --port="端口號" --database="sbtest" --table="sbtest1" --alter="ADD COLUMN d INT" --allow-on-master --aliyun-rds --initially-drop-old-table --initially-drop-ghost-table --execute;
測試結果
關閉Nonblock DDL,TPS持續跌零。默認超時時間為31536000,嚴重影響用戶業務。
開啟Nonblock DDL,TPS周期性下降,但未跌零。對用戶業務影響較小,能保證業務系統的穩定。
使用gh-ost進行表結構無鎖變更,TPS周期性跌零。對用戶業務影響很大,這是cut-over階段短暫鎖表造成的。
Nonblock DDL與gh-ost工具性能對比
開啟Nonblock DDL并使用傳統的加列方式(INSTANT、INPLACE、COPY)與使用gh-ost工具分別對100萬行數據的表進行加列操作的性能對比如下:
在無負載的情況下,通過下圖可以看出開啟Nonblock DDL并使用傳統的加列方式(INSTANT、INPLACE、COPY)比使用gh-ost工具耗時更少。
使用SysBench的oltp_read_write模擬業務負載,通過下圖可以看出開啟Nonblock DDL并使用傳統的加列方式(INSTANT、INPLACE、COPY)比使用gh-ost工具耗時更少。
測試結論
Nonblock DDL功能在DDL執行期間能更好的規避新事務阻塞、TPS跌零等問題,從而盡可能的保證業務系統的穩定性。同時,能夠提供更高效的DDL變更能力。
聯系我們
若您對DDL操作有任何疑問,可通過釘釘搜索群號入群咨詢。您可以直接@群內專家,并附上您要咨詢的問題;同時群內也有PolarDB MySQL版小助手24*7小時在線回答您的問題。釘釘群號:15375044501。