本文介紹了在PolarDB MySQL版中執行DDL操作時提示“獲取不到MDL鎖”的解決方法。
問題現象
在PolarDB MySQL版數據庫中執行DDL操作時提示獲取不到MDL鎖,報錯信息如下:
ERROR HY000: Fail to get MDL on replica during DDL synchronize
ERROR HY000: Fail to get table lock on replica; you can 'set polar_support_mdl_sync_preemption = ON' and try restarting transaction
問題原因
PolarDB MySQL版的只讀節點上存在未結束的查詢或未提交的事務。
解決方案
PolarDB MySQL版新增搶占式DDL來解決當前問題,您可以根據文檔中的內容,來了解并開啟當前功能。
提交事務(commit)或回滾事務(rollback)。
您也可以在只讀節點上開啟
polar_slave_work_on_nonblock_mdl_mode
參數,防止只讀節點上未提交的長事務阻塞DDL操作。具體操作請參見防止只讀節點上長事務阻塞DDL操作。執行DDL操作。
如果操作成功,任務結束。
如果操作失敗,繼續下一步。
如果您集群中的Polar Performance Schema功能是開啟狀態,您可以利用Performance Schema查詢目標表上MDL鎖狀態,然后來kill掉只讀節點上未提交事務的相關線程。具體操作如下:
說明您可以執行以下SQL查看集群中的Polar Performance Schema功能是否開啟。
SHOW VARIABLES LIKE 'polar_performance_schema';
如果當前只讀節點上未提交的事務非常重要,建議不要直接kill掉,請耐心等待此事務結束后,再進行DDL操作。
建議您開啟Polar Performance Schema功能。關于如何開啟Polar Performance Schema功能的開啟狀態,請參見操作步驟。
如果kill不掉線程、線程ID不存在或者出現如下報錯,請提交工單聯系阿里云技術支持進行處理。
ERROR 1094 (HY000): Unknown thread id: xxx
使用Hint語法指定只讀節點執行以下SQL查詢目標表上MDL鎖狀態。
/*force_node='pi-bp10k7631d6k3****'*/ SELECT t.PROCESSLIST_ID, m.OBJECT_TYPE, m.OBJECT_SCHEMA, m.OBJECT_NAME, m.LOCK_TYPE, m.LOCK_DURATION, m.LOCK_STATUS FROM performance_schema.metadata_locks m LEFT JOIN performance_schema.threads t ON m.owner_thread_id=t.thread_id;
顯示結果如下:
從上圖可以看到,當前
test/t
這個表上,有一個大查詢或者未提交的事務,持有了LOCK_TYPE
為SHARED_READ
的鎖。同時,當前test/t
表上有一個LOCK_TYPE
為EXCLUSIVE
的鎖處于PENGING
狀態。使用Hint語法指定只讀節點執行/*force_node='pi-bp10k7631d6k3****'*/ kill 14
結束掉連接對應的線程即可。如果您集群中的Polar Performance Schema功能是關閉狀態,您可以查詢
information_schema.innodb_trx
表上MDL鎖狀態,來確定是否有事務未提交,然后來kill掉對應的線程。具體操作如下:使用Hint語法指定只讀節點執行以下SQL查詢
information_schema.innodb_trx
表上MDL鎖狀態。/*force_node='pi-bp10k7631d6k3****'*/ SELECT * FROM information_schema.innodb_trx\G
大查詢導致的DDL執行失敗顯示結果如下:
從上圖可以看到,當前表
t1
上面存在一個大查詢,說明當前的連接持有了表t1
的MDL鎖。此時,使用Hint語法指定只讀節點執行/*force_node='pi-bp10k7631d6k3****'*/ kill 6
結束掉連接對應的trx_mysql_thread_id
線程即可。大事務導致的DDL執行失敗顯示結果如下:
從上圖可以看到,有一個未提交的事務14,由于
trx_query
字段為空,無法準確判斷當前事務持有了當前表的MDL鎖。此時您可以根據trx_started
字段進行處理,如果trx_started
字段的時間和當前時間的差距很大,大概率是當前事務14持有了MDL鎖。此時,使用Hint語法指定只讀節點執行/*force_node='pi-bp10k7631d6k3****'*/ kill 14
結束掉連接對應的trx_mysql_thread_id
線程即可。
聯系我們
若您對DDL操作有任何疑問,可通過釘釘搜索群號入群咨詢。您可以直接@群內專家,并附上您要咨詢的問題;同時群內也有PolarDB MySQL版小助手24*7小時在線回答您的問題。釘釘群號:15375044501。
更多信息
云原生數據庫PolarDB中DDL操作的過程如下:
在DDL操作的不同階段,如果需要變更表結構,則在變更前,主節點先獲取MDL鎖,然后寫入一條Redo日志。
只讀節點解析到此Redo日志時,會嘗試獲取同一個表中的MDL鎖。然后有下列兩種情況:
獲取成功,進入下一步。
獲取失敗,只讀節點反饋給主節點。
主節點等待所有只讀節點同步到最新的復制位點。在一定時間內,主節點會判斷所有只讀節點是否都解析到了此Redo日志以及是否加鎖成功。然后有下列兩種情況:
所有只讀節點同步到最新的復制位點,DDL成功。
某些只讀節點未同步到最新的復制位點,回滾DDL并報錯。此時報錯又分為兩種情況:一種是等待同步超時的報錯;一種是本文檔中加鎖失敗的報錯,而某些只讀節點加鎖失敗的主要原因是只讀節點存在未結束的查詢或者未提交的事務。