全部產品
Search
文件中心

PolarDB:如何處理DDL異常

更新時間:Jul 06, 2024

本文介紹如何處理使用PolarDB-X 1.0時出現的DDL異常情況。

DDL原理簡介

PolarDB-X 1.0的DDL指令會在所有分表上執行對應的DDL操作。失敗的情況可以分為兩類:

  • DDL在分庫執行失敗。DDL在任意分庫執行出錯都可能導致各分表結構不一致。

    分庫執行報錯的原因多種多樣,如建表時表已存在、加列時列已存在等各類衝突或磁碟空間不足等。

  • 執行長時間無響應。在對大表執行DDL操作時,有可能由於分庫的執行時間過長導致DDL長時間無響應。

    長時間無響應一般是由分庫的執行時間過長導致的。以MySQL為例,DDL的耗時大部分取決於該操作是In-Place(直接在源表修改)還是Copy Table(拷貝表資料)。In-Place只需要修改中繼資料就可以了,而Copy Table需要重建整張表資料,此外還涉及日誌和buffer操作。各類操作與這兩項因素的關係詳見MySQL官方文檔Online DDL Operations

判斷DDL操作是In-place還是Copy Table操作,可以查看操作結束後rows affected這一項的傳回值。樣本如下:

  • 改變某列的預設值(非常快,完全不會影響表資料)。
    Query OK, 0 rows affected (0.07 sec)
  • 增加一個索引(需要一點時間 ,但是0 rows affected說明表資料沒有被複製)。
    Query OK, 0 rows affected (21.42 sec)
  • 改變某列的資料類型(耗費大量時間並且需要重建表中的所有資料行)。
    Query OK, 1671168 rows affected (1 min 35.54 sec)
因此,執行一個大表DDL操作前,可以通過以下步驟判定這是一個快速還是慢速的操作:
  1. 複製表結構產生一張複製表。
  2. 插入一些資料。
  3. 在複製表上執行目標DDL操作。
  4. 檢查操作完成後rows affected值是否為0。非0的值表示該操作需要重建整張表,這時可能需要考慮在業務低峰期執行該操作。

PolarDB-X 1.0 DDL操作會將所有SQL分發到所有分庫上並存執行。任一分庫上執行失敗不會影響其他分庫。另外,PolarDB-X 1.0還提供了CHECK TABLE指令來檢測分表結構的一致性。因此,失敗的DDL操作可以重新執行,已經執行成功的分庫上失敗報錯並不會影響其他分庫。只需保證最終所有分表結構一致即可。

DDL執行失敗處理步驟

  1. 使用CHECK TABLE指令檢查表結構。如果返回結果只有一行且為狀態正常則可認為表狀態一致。此時執行步驟2,否則執行步驟3。
  2. 使用SHOW CREATE TABLE指令檢查表結構。如果顯示的表結構符合DDL執行後的預期則可認為DDL執行成功,否則繼續執行步驟3。
  3. 使用SHOW PROCESSLIST指令查看所有當前執行的SQL狀態。如有仍在執行的DDL操作,請等候其執行完成後再執行步驟1、2,檢查表結構是否符合預期,否則執行步驟4。
  4. PolarDB-X 1.0上重新執行DDL操作。如果出現Lock conflict的報錯資訊請執行步驟5,否則執行步驟3。
  5. 使用RELEASE DBLOCK指令釋放DDL操作鎖,然後執行步驟4。

詳細操作如下:

  1. 檢查表結構一致性。

    使用CHECK TABLE指令檢查表結構,樣本如下:

    check table `xxxx`;
    說明 如果在DMS上執行CHECK TABLE沒有返回結果,請在命令列下重試。

    若返回結果只有一行且顯示狀態OK時,表明表結構一致。樣本如下:

    +----------------------------+-------+----------+----------+
    | TABLE                      | OP    | MSG_TYPE | MSG_TEXT |
    +----------------------------+-------+----------+----------+
    | TDDL5_APP.xxxx             | check | status   | OK       |
    +----------------------------+-------+----------+----------+
    1 row in set (0.05 sec)       
  2. 檢查表結構。

    使用SHOW CREATE TABLE指令檢查表結構,樣本如下:

    mysql> show create table `xxxx`;

    若表結構一致且表結構無誤時,可認為DDL已執行成功,返回結果樣本如下:

    +---------+------------------------------------------------------------------------------------------------------------------+
    | Table   | Create Table                                                                                                     |
    +---------+------------------------------------------------------------------------------------------------------------------+
    |  xxxx   | CREATE TABLE `xxxx` (
    `id` int(11) NOT NULL DEFAULT '0',
    `NAME` varchar(1024) NOT NULL DEFAULT '',
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash(`id`) tbpartition by hash(`id`) tbpartitions 3                      |
    +---------+------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.05 sec)    
  3. 查看當前正在執行的SQL語句。

    有些DDL執行速度過慢,發現DDL長時間無響應後,可執行SHOW PROCESSLIST指令查看所有當前執行的SQL狀態,樣本如下:

    mysql> SHOW PROCESSLIST WHERE COMMAND != 'Sleep';

    返回結果樣本如下:

    +---------------+-----------+--------------------+-------------+---------+-----------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+-----------+---------------+-----------+
    | ID            | USER      | DB                 | COMMAND     | TIME    | STATE                                                                 | INFO                                                                                                 | ROWS_SENT | ROWS_EXAMINED | ROWS_READ |
    +---------------+-----------+--------------------+-------------+---------+-----------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+-----------+---------------+-----------+
    | 0-0-352724126 | ifisibhk0 | test_123_wvvp_0000 | Query       |      15 | Sending data                                                          | /*DRDS /42.120.74.88/ac47e5a72801000/ */select `t_item`.`detail_url`,SUM(`t_item`.`price`) from `t_i |      NULL |          NULL |      NULL |
    | 0-0-352864311 | cowxhthg0 | NULL               | Binlog Dump |      13 | Master has sent all binlog to slave; waiting for binlog to be updated | NULL                                                                                                 |      NULL |          NULL |      NULL |
    | 0-0-402714566 | ifisibhk0 | test_123_wvvp_0005 | Query       |      14 | Sending data                                                          | /*DRDS /42.120.74.88/ac47e5a72801000/ */select `t_item`.`detail_url`,`t_item`.`price` from `t_i      |      NULL |          NULL |      NULL |
    | 0-0-402714795 | ifisibhk0 | test_123_wvvp_0005 | Alter       |     114 | Sending data                                                          | /*DRDS /42.120.74.88/ac47e5a72801000/ */ALTER TABLE `Persons` ADD `Birthday` date                    |      NULL |          NULL |      NULL |
    ......
    +---------------+-----------+--------------------+-------------+---------+-----------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+-----------+---------------+-----------+
    12 rows in set (0.03 sec)       

    TIME列代表該指令已經執行的秒數。發現耗時較長的指令(如樣本中ID為0-0-402714795的指令)後,您可使用KILL '0-0-402714795'命令來取消該指令。

    說明 PolarDB-X 1.0中一個邏輯SQL對應多條分庫指令,因此為了停止一個邏輯DDL可能需要Kill多條指令。您可以從SHOW PROCESSLIST結果集的INFO列判斷該指令歸屬的邏輯SQL。
  4. Lock conflict報錯處理。

    PolarDB-X 1.0執行DDL操作會加庫級鎖,操作完後再釋放掉。KILL DDL操作很可能會導致該鎖沒有釋放,此時再執行DDL會出現以下報錯:

    Lock conflict , maybe last DDL is still running

    此時執行RELEASE DBLOCK命令釋放該鎖即可。指令取消及鎖釋放後,您可以選擇在業務低穀或者停止期間,重新執行該DDL。

常見問題

  • Q:為什麼在DMS或其它用戶端上無法顯示修改後的表結構?

    A:為了相容某些用戶端從系統資料表(如COLUMNS或TABLES)中擷取表結構的功能,PolarDB-X 1.0在您的0分庫RDS裡建立了一個影子庫,影子庫名與PolarDB-X 1.0邏輯庫名一致,儲存了邏輯庫裡所有的表結構等資訊。

    DMS會從影子庫系統資料表中擷取PolarDB-X 1.0的表結構。在處理異常DDL過程中,由於種種原因可能會出現庫表結構已經修改,但是影子庫中的表結構卻未修改的現象。此時您需串連到影子庫,在該庫中重新對錶進行一次DDL操作即可。

    說明 CHECK TABLE不會檢測影子庫表結構與PolarDB-X 1.0邏輯庫表結構是否一致。
  • Q:執行DDL語句時出現錯誤碼,該如何解決?

    A:關於PolarDB-X 1.0返回的常見錯誤碼及解決方案,請參見錯誤碼