本文介紹了在AUTO模式數據庫中使用Locality關鍵字指定數據庫對象的存儲位置的方法。本語法僅適用于AUTO模式數據庫。

PolarDB-X支持在AUTO模式數據庫中,通過Locality關鍵字來指定數據庫、表或分區的存儲位置,以實現數據隔離或數據的均勻分布。

當前Locality關鍵字實現的能力如下:

  • 允許定義數據庫、表、分區級別的Locality屬性,其他操作(縮容除外)均會在保證Locality約束的前提下改變數據分布。
  • 允許變更表組、分區組級別的Locality屬性,修改后將自動觸發相應的異步數據遷移任務。

前提條件

  • 實例內核版本需為5.4.14及以上。
  • 邏輯庫的分區類型需為AUTO模式。

如何查看實例版本,請參見查看和升級實例版本

注意事項

  • 節點縮容后,包含被縮容節點的Locality定義將會自動失效。
  • 當前Locality屬性通過DN節點的ID定義,備份恢復后原有Locality屬性將會自動失效。

查看存儲節點信息

假設已有一個PolarDB-X實例,您可以通過如下命令查看實例中的存儲節點信息:

SHOW STORAGE;

返回結果如下:

+--------------------+----------------------------------+------------+-----------+----------+-------------+--------+-----------+-------+--------+
| STORAGE_INST_ID    | LEADER_NODE                      | IS_HEALTHY | INST_KIND | DB_COUNT | GROUP_COUNT | STATUS | DELETABLE | DELAY | ACTIVE |
+--------------------+----------------------------------+------------+-----------+----------+-------------+--------+-----------+-------+--------+
| polardbx-ng28-dn-0 | polardbx-ng28-dn-0-cands-0:14289 | true       | MASTER    | 1        | 2           | 0      | false     | null  | null   |
| polardbx-ng28-dn-1 | polardbx-ng28-dn-1-cands-0:14176 | true       | MASTER    | 1        | 1           | 0      | true      | null  | null   |
| polardbx-ng28-dn-2 | polardbx-ng28-dn-2-cands-0:14568 | true       | MASTER    | 1        | 1           | 0      | true      | null  | null   |
| polardbx-ng28-dn-3 | polardbx-ng28-dn-3-cands-0:16796 | true       | MASTER    | 1        | 1           | 0      | true      | null  | null   |
| polardbx-ng28-gms  | polardbx-ng28-dn-0-cands-0:14289 | true       | META_DB   | 2        | 2           | 0      | false     | null  | null   |
+--------------------+----------------------------------+------------+-----------+----------+-------------+--------+-----------+-------+--------+
說明
  • STORAGE_INST_ID列為存儲節點名,即當前在Locality中使用的名字。
  • INST_KIND列為存儲節點類型,值為META_DB的節點為元數據節點,不能用于存儲用戶數據。
  • STATUS列為存儲節點狀態,值為0的節點為可用節點。
  • DELTETABLE列表明該節點是否可被縮容,值為false的節點不可被縮容,其中包含元數據節點和一個指定存儲節點(下面簡稱為0號存儲節點)。

創建數據庫時指定存儲位置

在創建數據庫時指定存儲位置以實現數據隔離。

  1. 在實例中創建一個AUTO模式數據庫,并通過如下命令指定其存儲位置,詳細語法請參見CREATE DATABASE
    CREATE DATABASE db1 LOCALITY='dn=polardbx-ng28-dn-0,polardbx-ng28-dn-1,polardbx-ng28-dn-2' MODE = 'auto';
  2. 創建成功后,您可以通過如下語句查看數據庫的存儲位置信息。
    SHOW CREATE DATABASE `db1`;

    返回結果如下:

    +----------+--------------------------------------------------------------------------------------------------------------------+
    | DATABASE | CREATE DATABASE                                                                                                    |
    +----------+--------------------------------------------------------------------------------------------------------------------+
    | db1      | CREATE DATABASE `db1` /* MODE = 'auto' LOCALITY = "dn=polardbx-ng28-dn-0,polardbx-ng28-dn-1,polardbx-ng28-dn-2" */ |
    +----------+--------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.04 sec)
  3. 您還可以通過如下命令查看創建在該數據庫下的邏輯分庫和物理分庫信息。
    SHOW DS;

    返回結果如下:

    +----+--------------------+--------------------+---------------------------------+----------------------+---------+
    | ID | STORAGE_INST_ID    | DB                 | GROUP                           | PHY_DB               | MOVABLE |
    +----+--------------------+--------------------+---------------------------------+----------------------+---------+
    |  0 | polardbx-ng28-dn-0 | db1                | DB1_P00000_GROUP                | db1_p00000           |       1 |
    |  1 | polardbx-ng28-dn-1 | db1                | DB1_P00001_GROUP                | db1_p00001           |       1 |
    |  2 | polardbx-ng28-dn-2 | db1                | DB1_P00002_GROUP                | db1_p00002           |       1 |
    |  3 | polardbx-ng28-gms  | information_schema | INFORMATION_SCHEMA_SINGLE_GROUP | polardbx_info_schema |       0 |
    +----+--------------------+--------------------+---------------------------------+----------------------+---------+
    4 rows in set (0.04 sec)
    說明 數據庫的存儲位置必須包含0號節點,表和分區的存儲位置不受此限制。

創建邏輯表時指定存儲位置

在創建邏輯表時指定存儲位置以實現數據隔離,目前支持在單表和Range、Hash、List三種分區方式的分區表中使用Locality關鍵字。

  1. 在實例中創建一個邏輯表,并指定其存儲位置。詳細語法參見CREATE TABLE(AUTO模式)
    CREATE TABLE t_order (
      `id` bigint(11) NOT NULL AUTO_INCREMENT BY GROUP,
      `order_id` varchar(20) DEFAULT NULL,
      `buyer_id` varchar(20) DEFAULT NULL,
      `seller_id` varchar(20) DEFAULT NULL,
      `order_snapshot` longtext DEFAULT NULL,
      `order_detail` longtext DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `l_i_order` (`order_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 locality = 'dn=polardbx-ng28-dn-1,polardbx-ng28-dn-2';
  2. 執行以下語句,查看表的定義。
    SHOW CREATE TABLE `t_order`;

    返回信息如下:

    +---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | TABLE   | CREATE TABLE                                                                                                                                                                                                                                                                                                                                                                                        |
    +---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | t_order | CREATE TABLE `t_order` (
        `id` bigint(11) NOT NULL AUTO_INCREMENT,
        `order_id` varchar(20) DEFAULT NULL,
        `buyer_id` varchar(20) DEFAULT NULL,
        `seller_id` varchar(20) DEFAULT NULL,
        `order_snapshot` longtext,
        `order_detail` longtext,
        PRIMARY KEY (`id`),
        INDEX `l_i_order` (`order_id`)
    ) ENGINE = InnoDB DEFAULT CHARSET = utf8
    /* LOCALITY='dn=polardbx-ng28-dn-1,polardbx-ng28-dn-2' */ |
    +---------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.05 sec)
  3. 執行以下語句,查看邏輯表的各個分區的數據分布情況。
    SHOW TOPOLOGY `t_order`;

    返回信息如下:

    +----+------------------+--------------------+----------------+-------------+--------------------+
    | ID | GROUP_NAME       | TABLE_NAME         | PARTITION_NAME | PHY_DB_NAME | DN_ID              |
    +----+------------------+--------------------+----------------+-------------+--------------------+
    |  0 | DB1_P00002_GROUP | t_order_18dV_00001 | p2             | db1_p00002  | polardbx-ng28-dn-2 |
    |  1 | DB1_P00001_GROUP | t_order_18dV_00000 | p1             | db1_p00001  | polardbx-ng28-dn-1 |
    |  2 | DB1_P00001_GROUP | t_order_18dV_00002 | p3             | db1_p00001  | polardbx-ng28-dn-1 |
    +----+------------------+--------------------+----------------+-------------+--------------------+
    3 rows in set (0.15 sec)
    說明
    • 創建表時Locality關鍵字指定的存儲節點集合,必須是數據庫對應存儲節點集合的子集。
    • 如果所創建的表為單表,則只允許Locality關鍵字聲明單個DN節點作為存儲節點。
    • 當邏輯表與表組匹配時,表與表組、分區和分區組的Locality屬性必須完全相同才能匹配成功。
    • 邏輯表、邏輯表的表組、邏輯表的GSI、邏輯表GSI的表組默認具備相同的Locality屬性。

創建邏輯表的分區時指定存儲位置

在創建邏輯表時,通過指定分區級別的存儲節點,可以將同一張邏輯表的不同分區分布在不同DN上。

  1. 在實例中創建一個邏輯表,并指定其分區的Locality。
    CREATE TABLE orders_region(
     order_id int AUTO_INCREMENT primary key,
     customer_id int,
     country varchar(64),
     city varchar(64),
     order_time datetime not null)
    PARTITION BY LIST COLUMNS(country,city)
    (
      PARTITION p1 VALUES IN (('China','Shanghai')) LOCALITY = 'dn=polardbx-ng28-dn-2',
      PARTITION p2 VALUES IN (('China','Beijing')) LOCALITY = 'dn=polardbx-ng28-dn-2',
      PARTITION p3 VALUES IN (('China','Hangzhou')) ,
      PARTITION p4 VALUES IN (('China','Nanjing')) ,
      PARTITION p5 VALUES IN (('China','Guangzhou')) ,
      PARTITION p6 VALUES IN (('China','Shenzhen')) ,
      PARTITION p7 VALUES IN (('China','Wuhan')) ,
      PARTITION p8 VALUES IN (('America','New York'))
    ) LOCALITY = 'dn=polardbx-ng28-dn-0,polardbx-ng28-dn-1';
                
  2. 執行以下語句,查看表的定義。
    SHOW CREATE TABLE `orders_region`;

    返回信息如下:

    +---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | TABLE         | CREATE TABLE                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
    +---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | orders_region | CREATE TABLE `orders_region` (
        `order_id` int(11) NOT NULL AUTO_INCREMENT,
        `customer_id` int(11) DEFAULT NULL,
        `country` varchar(64) DEFAULT NULL,
        `city` varchar(64) DEFAULT NULL,
        `order_time` datetime NOT NULL,
        PRIMARY KEY (`order_id`),
        KEY `auto_shard_key_country_city` USING BTREE (`country`, `city`)
    ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
    /* LOCALITY='dn=polardbx-ng28-dn-0,polardbx-ng28-dn-1' */
    PARTITION BY LIST COLUMNS(`country`,`city`)
    (PARTITION `p1` VALUES IN (('China','Shanghai')) ENGINE = InnoDB LOCALITY='dn=polardbx-ng28-dn-2',
     PARTITION `p2` VALUES IN (('China','Beijing')) ENGINE = InnoDB LOCALITY='dn=polardbx-ng28-dn-2',
     PARTITION `p3` VALUES IN (('China','Hangzhou')) ENGINE = InnoDB,
     PARTITION `p4` VALUES IN (('China','Nanjing')) ENGINE = InnoDB,
     PARTITION `p5` VALUES IN (('China','Guangzhou')) ENGINE = InnoDB,
     PARTITION `p6` VALUES IN (('China','Shenzhen')) ENGINE = InnoDB,
     PARTITION `p7` VALUES IN (('China','Wuhan')) ENGINE = InnoDB,
     PARTITION `p8` VALUES IN (('America','New York')) ENGINE = InnoDB) |
    +---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.05 sec)
  3. 執行以下語句,查看邏輯表的各個分區的數據分布情況。
    SHOW TOPOLOGY `orders_region`;

    返回信息如下:

    +----+------------------+--------------------------+----------------+-------------+--------------------+
    | ID | GROUP_NAME       | TABLE_NAME               | PARTITION_NAME | PHY_DB_NAME | DN_ID              |
    +----+------------------+--------------------------+----------------+-------------+--------------------+
    |  0 | DB1_P00002_GROUP | orders_region_RlsY_00000 | p1             | db1_p00002  | polardbx-ng28-dn-2 |
    |  1 | DB1_P00002_GROUP | orders_region_RlsY_00001 | p2             | db1_p00002  | polardbx-ng28-dn-2 |
    |  2 | DB1_P00001_GROUP | orders_region_RlsY_00003 | p4             | db1_p00001  | polardbx-ng28-dn-1 |
    |  3 | DB1_P00001_GROUP | orders_region_RlsY_00004 | p5             | db1_p00001  | polardbx-ng28-dn-1 |
    |  4 | DB1_P00001_GROUP | orders_region_RlsY_00006 | p7             | db1_p00001  | polardbx-ng28-dn-1 |
    |  5 | DB1_P00000_GROUP | orders_region_RlsY_00002 | p3             | db1_p00000  | polardbx-ng28-dn-0 |
    |  6 | DB1_P00000_GROUP | orders_region_RlsY_00005 | p6             | db1_p00000  | polardbx-ng28-dn-0 |
    |  7 | DB1_P00000_GROUP | orders_region_RlsY_00007 | p8             | db1_p00000  | polardbx-ng28-dn-0 |
    +----+------------------+--------------------------+----------------+-------------+--------------------+
    8 rows in set (0.25 sec)
    說明 分區的存儲節點必須是數據庫存儲節點的子集,但可以不是邏輯表的存儲節點的子集。

修改表組的存儲節點

動態變更表組的存儲節點。

語法
ALTER TABLEGROUP identifier SET LOCALITY = locality_option
locality_option:
    'dn=storage_inst_id_list'
 |  ''
示例

以前文中的orders_region表為例,該表位于表組`tg3`中,現對其存儲節點進行變更:

ALTER TABLEGROUP `tg3` SET LOCALITY = `dn=polardbx-ng28-dn-0`;

變更操作后,表的拓撲如下:

SHOW TOPOLOGY `orders_region`;
+----+------------------+--------------------------+----------------+-------------+--------------------+
| ID | GROUP_NAME       | TABLE_NAME               | PARTITION_NAME | PHY_DB_NAME | DN_ID              |
+----+------------------+--------------------------+----------------+-------------+--------------------+
|  0 | DB1_P00002_GROUP | orders_region_RlsY_00000 | p1             | db1_p00002  | polardbx-ng28-dn-2 |
|  1 | DB1_P00002_GROUP | orders_region_RlsY_00001 | p2             | db1_p00002  | polardbx-ng28-dn-2 |
|  2 | DB1_P00000_GROUP | orders_region_RlsY_00002 | p3             | db1_p00000  | polardbx-ng28-dn-0 |
|  3 | DB1_P00000_GROUP | orders_region_RlsY_00003 | p4             | db1_p00000  | polardbx-ng28-dn-0 |
|  4 | DB1_P00000_GROUP | orders_region_RlsY_00004 | p5             | db1_p00000  | polardbx-ng28-dn-0 |
|  5 | DB1_P00000_GROUP | orders_region_RlsY_00005 | p6             | db1_p00000  | polardbx-ng28-dn-0 |
|  6 | DB1_P00000_GROUP | orders_region_RlsY_00006 | p7             | db1_p00000  | polardbx-ng28-dn-0 |
|  7 | DB1_P00000_GROUP | orders_region_RlsY_00007 | p8             | db1_p00000  | polardbx-ng28-dn-0 |
+----+------------------+--------------------------+----------------+-------------+--------------------+
8 rows in set (0.17 sec)
            

在同一表組內,定義過Locality的分區的數據存儲位置,將遵從其Locality約束,其他分區將根據表組的Locality約束進行數據遷移。修改表組或分區組的存儲位置將會在元信息變更后快速返回,后臺生成相應表組的分區遷移任務異步執行

可通過information_schema.ddl_plan查詢對應的分區遷移任務REBALANCE TABLEGROUP tg3的執行進度。

SELECT * FROM information_schema.ddl_plan WHERE table_schema = "db1";
+----+---------------------+---------------------+--------------+------------------------------------------------------------------+---------+-----------+----------+-------------+--------+--------+---------------------+---------------------+----------------+
| ID | plan_id             | job_id              | table_schema | ddl_stmt                                                         | state   | ddl_type  | progress | retry_count | result | extras | gmt_created         | gmt_modified        | resource       |
+----+---------------------+---------------------+--------------+------------------------------------------------------------------+---------+-----------+----------+-------------+--------+--------+---------------------+---------------------+----------------+
|  1 | 1465819565798723584 | 1465819579241467904 | db1          | REBALANCE TABLEGROUP `tg3`  EXPLAIN=false ASYNC=true DEBUG=false | SUCCESS | REBALANCE |      100 |           0 |        |        | 2022-05-24 14:37:58 | 2022-05-24 14:38:11 | tablegroup:tg3 |
+----+---------------------+---------------------+--------------+------------------------------------------------------------------+---------+-----------+----------+-------------+--------+--------+---------------------+---------------------+----------------+

修改分區組的存儲節點

動態變更分區組的存儲節點。

語法
ALTER TABLEGROUP identifier SET PARTITIONS part_name LOCALITY = locality_option
locality_option:
    'dn=storage_inst_id_list'
 |  ''
示例

以前文中的orders_region表為例,該表位于表組`tg3`中,現對其分區p3的Locality進行變更:

ALTER TABLEGROUP `tg3` SET PARTITIONS p3 LOCALITY = `dn=polardbx-ng28-dn-1`;

變更后表的拓撲如下:

SHOW TOPOLOGY orders_region;
+----+------------------+--------------------------+----------------+-------------+--------------------+
| ID | GROUP_NAME       | TABLE_NAME               | PARTITION_NAME | PHY_DB_NAME | DN_ID              |
+----+------------------+--------------------------+----------------+-------------+--------------------+
|  0 | DB1_P00002_GROUP | orders_region_RlsY_00000 | p1             | db1_p00002  | polardbx-ng28-dn-2 |
|  1 | DB1_P00002_GROUP | orders_region_RlsY_00001 | p2             | db1_p00002  | polardbx-ng28-dn-2 |
|  2 | DB1_P00001_GROUP | orders_region_RlsY_00002 | p3             | db1_p00001  | polardbx-ng28-dn-1 |
|  3 | DB1_P00000_GROUP | orders_region_RlsY_00003 | p4             | db1_p00000  | polardbx-ng28-dn-0 |
|  4 | DB1_P00000_GROUP | orders_region_RlsY_00004 | p5             | db1_p00000  | polardbx-ng28-dn-0 |
|  5 | DB1_P00000_GROUP | orders_region_RlsY_00005 | p6             | db1_p00000  | polardbx-ng28-dn-0 |
|  6 | DB1_P00000_GROUP | orders_region_RlsY_00006 | p7             | db1_p00000  | polardbx-ng28-dn-0 |
|  7 | DB1_P00000_GROUP | orders_region_RlsY_00007 | p8             | db1_p00000  | polardbx-ng28-dn-0 |
+----+------------------+--------------------------+----------------+-------------+--------------------+
8 rows in set (0.11 sec)

分區變更操作中的Locality屬性傳播

當前AUTO模式下的分區變更操作包括表組級分區變更語法(AUTO模式)變更表類型及分區策略(AUTO模式)

在分區變更操作中,新的分區組和表組一般自動繼承原有的Locality屬性,并且變更后的表組和分區組也將自動滿足數據分布約束,但是以下三種情形例外:

  • 對于表的類型變更操作,當目標類型為單表或者廣播表時,表的Locality屬性默認為空。
  • 對于明確涉及數據熱點的分區變更操作,新分區Locality默認為空。
  • 對于merge partition操作,當原分區集合成員的Locality不同時,新分區Locality默認為空。

分區變更操作涉及的Locality變更說明:

類型(簡稱) 變更對象 變更對象的Locality屬性是否不變 備注
分區表拆分變更 -
表的類型變更 僅在單表變更為分區表時不變。 分區表變更為單表和廣播表時Locality屬性會自動失效。
分區遷移(move partition) 分區組 -
分區合并(merge partition) 分區組 新分區僅在所有舊分區的locality屬性相同時繼承舊分區的locality。 無法繼承時,新分區Locality默認為空值。
分區分裂(split partition) 分區組 -
分區按熱點分裂(split by hot value) 分區組 新分區Locality默認為空值。
分區熱點值提取(extract) 分區組 新分區Locality默認為空值。
分區刪除(drop partition) 分區組 - -
分區新增(add partition) 分區組 -
LIST分區值修改(modify partition) 分區組 -
分區重命名(rename partition) 分區組 -

典型使用場景

  • 創建數據庫時,可通過Localiy對邏輯庫級別的數據進行隔離,數據庫中的表和分區會自動分布在指定的DN上。
  • 創建單表時,可通過Locality指定單表的存儲節點,從而避免單表數量過多對0號節點的存儲壓力。
  • 創建分區表時,可通過指定分區級別的Locality,將同一張邏輯表的不同分區控制在不同的DN上,例如結合LIST分區可對同一張邏輯表中不同地域數據進行隔離。
  • 當數據分區產生熱點數據時,可通過分區變更和Locality為熱點分區指定單獨的DN,從而隔離其物理存儲資源。