如何正確處理DDL異常

更新時間:
Copy as MD

本文介紹處理DDL異常的常用方法。

概述

作為一款分散式資料庫,PolarDB-X中的一條DDL語句背後隱藏著複雜的資料處理流程。例如建立一張拆分表時,實際上會在多個資料節點上建立很多張物理MySQL表。PolarDB-XDDL處理架構擁有一定的容錯能力,會保證DDL的正確性和一致性。但在特殊情況下,需要手動處理DDL異常。

處理步驟

下面以建立全域唯一二級索引為例,介紹處理DDL異常的步驟。建立全域唯一二級索引時,會校正列中資料的全域唯一性,如果發現列中資料不唯一,則會導致DDL的執行失敗。此時DDL的狀態可能變為“PAUSED”或“ROLLBACK_PAUSED”。

  1. 查看DDL的執行狀態

    執行SHOW DDL語句,查看DDL的執行狀態。只有當DDL狀態為“PAUSED”或“ROLLBACK_PAUSED”時,才需要手動處理。

    SHOW DDL\G;
    *************************** 1. row ***************************
               JOB_ID: 1359992239576580096
        OBJECT_SCHEMA: d1
          OBJECT_NAME: t1
               ENGINE: DAG
             DDL_TYPE: ALTER_TABLE
                STATE: PAUSED
    BACKFILL_PROGRESS: 0%
     PHY_DDL_PROGRESS: 100%
             PROGRESS: 80%
           START_TIME: 2021-08-05 13:57:57.852
             END_TIME: 2021-08-05 13:58:30.804
     ELAPSED_TIME(MS): 32952
          PHY_PROCESS: 
           CANCELABLE: true
    1 row in set (0.03 sec)
  2. 判斷錯誤原因

    通常DDL異常發生時,會直接返回錯誤資訊。有時DDL的錯誤資訊可能難以擷取(例如DDL是非同步執行的),可以通過SHOW DDL RESULT語句查看近期執行過的DDL。在本樣本中,從返回的錯誤資訊中看到出現了UNIQUE KEY的衝突。

    ALTER TABLE t1 ADD unique global INDEX `idx_c2`(`c2`) DBPARTITION BY HASH(`c2`) tbpartition by hash(c2) tbpartitions 3;
    ERROR 3009 (HY000): [12dfa9bc5c800000][30.39.226.95:8527][d1]Failed to execute the DDL task. Caused by: ERR-CODE: [TDDL-5321][ERR_GLOBAL_SECONDARY_INDEX_BACKFILL_DUPLICATE_ENTRY] Duplicated entry '100018' for key 'PRIMARY'
    
    
    SHOW ddl result\G;
    *************************** 1. row ***************************
            JOB_ID: 1359992239576580096
       SCHEMA_NAME: d1
       OBJECT_NAME: t1
          DDL_TYPE: ALTER_TABLE
       RESULT_TYPE: ERROR
    RESULT_CONTENT: Failed to execute the DDL task. Caused by: ERR-CODE: [TDDL-5321][ERR_GLOBAL_SECONDARY_INDEX_BACKFILL_DUPLICATE_ENTRY] Duplicated entry '100018' for key 'PRIMARY' 
  3. 恢複或取消DDL

    大多數情況下,DDL出錯時都能夠自動回復或取消。特殊情況需要手動處理DDL異常。各個DDL的容錯策略可能不同,例如CREATE TABLE語句的容錯策略是:自動嘗試恢複,多次失敗則自動取消。

    可以手動恢複或取消DDL任務。
    • 手動恢複:使用CONTINUE DDL語句可以恢複DDL任務。
    • 手動取消:使用CANCEL DDL語句可以取消DDL任務。有些DDL任務可能是無法取消的,可以通過SHOW DDL語句返回的“CANCELABLE”欄位查看是否可以取消。
    -- 處理完UNIQUE KEY的資料衝突後,可以使用continue ddl語句繼續執行
    CONTINUE ddl 1359992239576580096;
    Query OK, 1 row affected (1.63 sec)
    
    -- 如果不想再繼續添加這個全域唯一二級索引,則可以直接取消任務
    CANCEL ddl 1359992239576580096;
    Query OK, 1 row affected (0.03 sec)
  4. 檢查表一致性和正確性
    DDL執行成功後,建議使用以下語句檢查表的一致性和表結構的正確性:
    • 使用CHECK TABLE語句檢查表的一致性:如果返回結果為OK,說明表已經處於一致性狀態,可以正常使用;如果返回報錯資訊,提示表處於不一致狀態,請聯絡阿里雲支援人員。
    • 使用SHOW CHECK TABLE語句查看錶結構的正確性。
    CHECK TABLE t1;
    +-------+-------+----------+----------+
    | TABLE | OP    | MSG_TYPE | MSG_TEXT |
    +-------+-------+----------+----------+
    | d1.t1 | check | status   | OK       |
    +-------+-------+----------+----------+
    1 row in set (0.05 sec)
    
    SHOW CHECK TABLE t1\G;
    *************************** 1. row ***************************
           Table: t1
    Create Table: CREATE TABLE `t1` (
        `c1` bigint(20) NOT NULL AUTO_INCREMENT BY GROUP,
        `c2` bigint(20) DEFAULT NULL,
        `c3` bigint(20) DEFAULT NULL,
        PRIMARY KEY USING BTREE (`c1`),
        UNIQUE GLOBAL KEY `idx_c2` (`c2`) COVERING (`c1`) DBPARTITION BY HASH(`c2`) TBPARTITION BY HASH(`c2`) TBPARTITIONS 3
    ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4  dbpartition by hash(`c1`) tbpartition by hash(`c1`) tbpartitions 3
    1 row in set (0.02 sec)