全部產品
Search
文件中心

:DDL原子性

更新時間:Jul 06, 2024

PolarDB-X支援多階段DDL功能。該功能避免了使用者DDL在物理執行時,出現部分分區執行成功,部分分區執行失敗的情況,有效解決了物理DDL原子性的問題(由於邏輯執行的DDL不存在原子性問題,因此本文主要討論物理執行的DDL)。

背景資訊

PolarDB-X中,一張邏輯表往往對應了多個物理表(分區),且這些分區會分布在多個儲存節點中。在對一張邏輯表執行DDL操作時,如果是物理執行,那麼這張表的所有物理表都需要執行相關物理DDL操作,由於各個分區物理DDL執行是獨立的,因此往往不能保證物理執行的原子性;如果是邏輯執行,計算節點通過新增暫存資料表,匯入存量資料,雙寫同步增量資料,切換表中繼資料的方式實現,並且切換表中繼資料的過程是原子的,因此不存在原子性問題。

不支援原子性物理DDL的時候,物理DDL在多個分區上獨立執行,並無一致提交的時間點,且計算節點和儲存節點各自儲存中繼資料資訊,同一時間點內,可能出現計算層與儲存層多個分配之間的中繼資料視圖存在差異的情況,導致使用者查詢報錯。

另外,對於ALTER TABLE MODIFY COLUMN此類修改列的schema約束的語句,容易因為分區內已經存在的資料違反約束而導致物理DDL執行失敗。當部分分區執行物理DDL失敗,而部分分區執行物理DDL成功時,計算層無法通過下發物理DDL實現一致的復原語義,必須人工介入,使用者的業務將有較長時間出現中繼資料視圖不一致狀態,存在影響使用者業務的隱患。

PolarDB-X支援的多階段DDL功能,通過在DN上構造多個分區提交物理DDL的barrier,控制物理DDL在commit point之前的復原和提交行為,保證多分區DDL原子性提交,從而提供一致的DN多分區元資訊視圖。

注意事項

  • 僅核心版本在5.4.18-17108394及以上的PolarDB-X執行個體支援多階段DDL功能。

  • 由於所有參與的物理分區都必須保持串連和線程,不支援單個DN存在500個物理分區以上的較大規模邏輯表。

  • 對於COPY類型的物理DDL,分布式DDL的影響由原有的鎖分區變為鎖全邏輯表。

  • 物理DDL在commit階段修改資料字典,此操作為全域互斥操作,在多階段DDL中將表現為集中到鎖表時間點。

  • 對於鎖表敏感的使用者,推薦使用無鎖變更列類型,該功能為邏輯執行,同樣可以保證原子性。

適用範圍

  • 目前僅適用於ADD/DROP COLUMN、ADD/DROP INDEX以及MODIFY COLUMN操作的物理DDL。

  • 不適用包含物理分區、外鍵、全文索引的表。

使用方法

  • 檢查執行個體是否支援多階段DDL,以及多階段DDL的開啟狀態:

    show variables like "enable_two_phase_ddl";

    如果查詢不到結果,那麼說明不支援多階段DDL;如果返回為true則說明已經開啟了多階段DDL功能;如果返回為false則說明未開啟多階段DDL功能。

    -- 預設開啟多階段 DDL 功能
    
    show variables like "enable_two_phase_ddl";
    +----------------------+-------+
    | Variable_name        | Value |
    +----------------------+-------+
    | enable_two_phase_ddl | ON    |
    +----------------------+-------+
  • 開啟多階段DDL功能:

    set global enable_two_phase_ddl = true;
  • 關閉多階段DDL功能:

    set global enable_two_phase_ddl = false;

樣本

  1. PolarDB-X執行個體中,建立一張邏輯表t1,其結構如下:

    +-------+--------------------------------------------------------------------------+
    | Table | Create Table                                                             |
    +-------+--------------------------------------------------------------------------+
    | t1    | CREATE TABLE `t1` (
            `a` int(11) DEFAULT NULL,
            `b` int(11) DEFAULT NULL
    ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
    PARTITION BY KEY(`a`)
    PARTITIONS 16                                                                      |
    +-------+--------------------------------------------------------------------------+
  2. 寫入資料到邏輯表t1中。

    insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,999999);
    Query OK, 1 row affected (0.01 sec)
  3. 在strict 模式下,執行ALTER TABLE t1 MODIFY COLUMN b tinyint,由於t1表存在一條b列為999999,strict 模式下該資料所在的分區預期物理DDL執行失敗,預設開啟多階段DDL功能,因此預期所有分區都應該變更失敗。

    ALTER TABLE t1 MODIFY COLUMN b tinyint;
    ERROR 4700 (HY000): ERR-CODE: [TDDL-4700][ERR_SERVER] server error by Failed to execute the DDL task. Caused by: ERR-CODE: [TDDL-4636][ERR_DDL_JOB_ERROR] ERR-CODE: [TDDL-4636][ERR_DDL_JOB_ERROR] failed to execute on group(WUMU_P00000_GROUP): /* drds_two_phase_ddl(1717761420461916160)*/ALTER TABLE `t1_KdRs_00004`\n\tMODIFY COLUMN b tinyint , Caused by: Data truncation: Out of range value for column 'b' at row 1. .
  4. 執行SHOW DDL和SHOW DDL RESULT命令,查看當前執行個體庫中的DDL任務和歷史執行結果。

    show ddl;
    Empty set (0.01 sec)
    
    show ddl result;
    +---------------------+-------------+-------------+--------------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | JOB_ID              | SCHEMA_NAME | OBJECT_NAME | DDL_TYPE     | RESULT_TYPE | RESULT_CONTENT                                                      |
    +---------------------+-------------+-------------+--------------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | 1717761420575162368 | wumu        | t1          | ALTER_TABLE  | ERROR       | Failed to execute the DDL task. Caused by: ERR-CODE: [TDDL-4636][ERR_DDL_JOB_ERROR] ERR-CODE: [TDDL-4636][ERR_DDL_JOB_ERROR] failed to execute on group(WUMU_P00000_GROUP): /* drds_two_phase_ddl(1717761420461916160)*/ALTER TABLE `t1_KdRs_00004`\n\tMODIFY COLUMN b tinyint , Caused by: Data truncation: Out of range value for column 'b' at row 1. .  |
    +---------------------+-------------+-------------+--------------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 rows in set (0.03 sec)
  5. 執行CHECK TABLE命令,檢查邏輯表各個分區的結構是否一致,並且與計算層的中繼資料相同。

    check table t1;
    +---------------------------------+-------+----------+----------+
    | TABLE                           | OP    | MSG_TYPE | MSG_TEXT |
    +---------------------------------+-------+----------+----------+
    | wumu.t1:Topology                | check | status   | OK       |
    | wumu.t1:Columns                 | check | status   | OK       |
    | t1.auto_shard_key_a:Local Index | check | status   | OK       |
    +---------------------------------+-------+----------+----------+
    3 rows in set (0.01 sec)
    
    show create table t1;
    +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table                                                                                 |
    +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | t1    | CREATE TABLE `t1` (
            `a` int(11) DEFAULT NULL,
            `b` int(11) DEFAULT NULL,
            KEY `auto_shard_key_a` USING BTREE (`a`)
    ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
    PARTITION BY KEY(`a`)
    PARTITIONS 16 |
    +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.01 sec)