全部產品
Search
文件中心

PolarDB:MDL最佳化(中繼資料鎖)

更新時間:Jul 06, 2024

MDL鎖(MetaData Lock,中繼資料鎖)是資料庫的內部鎖,用於確保執行DDL時事務使用的表中繼資料的一致性。普通讀寫事務需要擷取對應表的MDL讀鎖,DDL操作需要擷取對應表的MDL寫鎖。執行DDL時需要關注的MDL鎖相關問題如下:

  • 阻塞性

    長事務長期持有的MDL讀鎖會阻塞DDL的執行,這會使DDL因長時間申請MDL寫鎖不成功而失敗。此外,由於MySQL中MDL鎖是公平鎖,當DDL因為長事務持有MDL讀鎖而阻塞等待MDL寫鎖時,新事務也會因排隊申請MDL讀鎖而將被全部阻塞。

  • 死結風險

    多個DDL和事務一起執行時,由於申請MDL鎖的順序不同,可能引發MDL死結。

  • 排它性

    MDL寫鎖具有排它性,當DDL擷取到MDL寫鎖後,所有新來的事務都將因為無法申請MDL讀鎖而等待,這會造成流量跌零。雖然MySQL支援了Online DDL,但這類DDL只是儘力避免全程鎖表,在一些關鍵的環節仍需要短暫擷取MDL寫鎖。

執行DDL時一旦出現上述問題,可能導致Business Connectivity的堆積和阻塞,嚴重時可造成業務流量的暫時跌零,後果較為嚴重。PolarDB-X對上述MDL鎖的問題進行了針對性最佳化,使得執行DDL時不再需要擔心上述風險。

搶佔式MDL鎖最佳化

PolarDB-X支援搶佔式MDL鎖最佳化,該最佳化消除了執行DDL時由於MDL鎖的阻塞性導致的潛在風險。

支援版本

PolarDB-X的5.4.17-16952556及以上版本支援該功能。

詳細說明

執行需要申請MDL寫鎖的DDL時,如果申請MDL寫鎖的等鎖時間過長,PolarDB-X將自動停止阻塞該DDL的長事務所屬的串連。

下表展示了沒有搶佔式MDL鎖最佳化時,DDL和新事務被舊長事務阻塞的情形。

表1

步驟

Session1

Session2

Session3

1

begin;

-

begin;

2

insert into tb0 values(1);

-- 擷取tb0的MDL讀鎖

-

-

3

-- 長期不提交,類比長事務

-

-

4

-

alter table tb0 add column col int;

-- 嘗試擷取tb0的MDL寫鎖,被長事務阻塞

-

5

-

-

select id from tb0;

-- 嘗試擷取tb0的MDL讀鎖,被阻塞。

搶佔式MDL鎖最佳化後的執行過程如下(步驟與表1完全一致,關鍵步驟已在圖中標出):

image.png

可以看到,由於搶佔式MDL鎖最佳化機制,session1上的長事務所屬串連被斷開,保證了session2上的DDL順利執行,也確保了Session3上的新事務的正常執行。

分布式MDL死結檢測

PolarDB-X支援分布式MDL死結檢測,該功能可以檢測並打破在執行DDL時由MDL鎖參與形成的死結,維護DDL和事務的正常執行。

支援版本

PolarDB-X的5.4.17-16952556及以上版本支援該功能。

詳細說明

PolarDB-X將定時掃描事務和DDL之間的鎖等待情況,如果檢測到死結,PolarDB-X將自動停止一個普通事務,以確保DDL和其它事務的正常執行。

下表展示了一個典型的由MDL鎖參與的死結情境。

表2

步驟

session1

session2

session3

session4

1

begin;

-- 開啟事務1

begin;

-- 開啟事務2

-

-

2

insert into t1 values(1);

-- 擷取t1的MDL讀鎖

insert into t2 values(1);

-- 擷取t2的MDL讀鎖

-

-

3

-

-

alter table t1 add column col int;

-- 發起DDL1,嘗試擷取t1的MDL寫鎖,被阻塞

alter table t2 add column col int;

-- 發起DDL2,嘗試擷取t2的MDL寫鎖,被阻塞

4

insert into t2 values(2);

-- 嘗試獲得t2的MDL讀鎖。但因為MDL是公平鎖,所以被DDL2阻塞

insert into t1 values(2);

-- 嘗試獲得t1的MDL讀鎖。但因為MDL是公平鎖,所以被DDL1阻塞

-

-

如下示範了在具有分布式MDL死結檢測功能的PolarDB-X上,表2中的死結問題如何得到解決(執行步驟與上表完全一致,關鍵步驟已在圖中標出):

image.png

在按照表2裡的順序產生死結情境後,PolarDB-X檢測到了死結,並選擇斷開事務2所在的串連,事務2被復原,事務1和DDL1、DDL2順利執行。

雙版本MDL鎖最佳化

對於邏輯執行的DDL,PolarDB-X支援了雙版本中繼資料和對應的雙版本MDL鎖,這使得在執行這類DDL時,真正可以做到全程不鎖表、流量不跌零。

限制條件

該最佳化支援PolarDB-X中所有邏輯執行的DDL,判斷DDL是否為邏輯執行。詳情請參見Online DDL

詳細說明

PolarDB-X的邏輯DDL基於Online Schema Change原理實現,將一個邏輯DDL的中繼資料版本細分為多個小版本,使得DDL的中繼資料版本演化可以在PolarDB-X執行個體中安全進行。例如PolarDB-X中的CREATE GLOBAL INDEX DDL全程會涉及ABSENT(Vn),DELETE_ONLY(Vn+1),WRITE_ONLY(Vn+2),PUBLISH(Vn+3)多次版本切換。此外,PolarDB-X將MDL鎖與中繼資料的小版本綁定,每個版本的中繼資料都擁有各自對應版本的中繼資料鎖。

得益於Online Schema Change機制,在同一時刻,不僅叢集中的不同CN節點之間允許存在兩個版本,一個CN節點內部也允許存在兩個版本。因此當邏輯DDL開始中繼資料版本演化時,每一次演化,PolarDB-X只會擷取舊版本中繼資料對應的MDL寫鎖,因此新事務可以訪問新版本中繼資料,並申請新版本中繼資料對應的MDL讀鎖。

在雙版本中繼資料鎖的最佳化下,PolarDB-X的邏輯DDL可以做到全程不鎖表、流量不跌零。