CREATE CLONE

CLONE 操作允许在 MatrixOne 数据库中复制表或数据库的结构和数据。克隆可以在同一租户内进行,也可以跨租户进行(仅限 sys 租户操作)。跨租户克隆必须使用预先创建的 snapshot。

语法说明

CLONE 操作允许在 MatrixOne 数据库中复制表或数据库的结构和数据。克隆可以在同一租户内进行,也可以跨租户进行(仅限 sys 租户操作)。跨租户克隆必须使用预先创建的 snapshot。

前提条件

在执行 CLONE 操作前,需要确保:

  • 源数据库和表必须已经存在

  • 目标数据库(对于表克隆)必须已经存在,或者使用 CREATE DATABASE 预先创建

  • 对于跨租户克隆,必须预先创建 snapshot

  • 执行用户需要具有相应的权限

连接其他租户

要连接其他租户进行操作,需要使用特定格式的连接字符串:

# 连接普通租户 acc1
mysql -h 127.0.0.1 -P 6001 -u root:acc1 -p

# 连接普通租户 acc2  
mysql -h 127.0.0.1 -P 6001 -u root:acc2 -p

# 连接 sys 租户
mysql -h 127.0.0.1 -P 6001 -u root:sys -p

语法结构

克隆表

CREATE TABLE [IF NOT EXISTS] target_db.target_table 
CLONE source_db.source_table 
[COPY GRANTS]
[{SNAPSHOT = "snapshot_name"}] 
[TO ACCOUNT account_name]

克隆数据库

CREATE DATABASE [IF NOT EXISTS] target_db 
CLONE source_db 
[{SNAPSHOT = "snapshot_name"}] 
[TO ACCOUNT account_name]

源解析

使用 CREATE DATABASE ... CLONE 克隆数据库时,MatrixOne 会检查源数据库名称、租户上下文和快照配置来解析源。解析过程决定了从哪里读取数据以及使用哪个租户身份。

跨租户克隆

当克隆操作跨不同租户进行时(源和目标位于不同租户),必须使用快照。验证逻辑包含两个检查:

  1. 快照要求:如果操作租户与目标租户不同且未指定快照,操作将失败并报错:

    clone database between different accounts need a snapshot
    
  2. sys 租户限制:如果操作者不是 sys 租户且正在向其他租户克隆,操作将失败并报错:

    only sys can clone table to another account
    

也就是说,跨租户克隆必须由 sys 租户执行,且必须使用快照。非 sys 租户可以在自己的租户内直接克隆,无需快照。

订阅源

当源数据库来自订阅(subscription)时,克隆操作会自动解析底层数据库身份:

  • 源数据库名称解析为订阅的底层数据库名称(subMeta.DbName),绕过订阅包装层。

  • 快照的租户信息设置为订阅所属的源租户(subMeta.AccountId),确保克隆从正确的源租户读取数据。

  • 如果克隆语句中未显式指定快照,系统会自动根据订阅的租户信息构造一个快照。

通过这种解析机制,从订阅来源的数据库克隆时无需手动指定底层源信息。

COPY GRANTS

使用 CREATE TABLE ... CLONE 克隆表时,可以可选地包含 COPY GRANTS 子句,将源表的显式表级权限授予复制到克隆的目标表中。此选项仅适用于表级克隆(CREATE TABLE ... CLONE),不适用于数据库级克隆(CREATE DATABASE ... CLONE)。

复制内容:

  • 仅复制源表的显式表对象授权obj_type = 'table'),包括 SELECTINSERTDELETEUPDATEALL 及其组合等权限。

  • WITH GRANT OPTION 属性会被保留 —— 如果某个角色在源表上被授予了 WITH GRANT OPTION 的权限,则目标表上的复制授权同样保留该选项。

  • 同时复制 privilege_level = 'd.t'(数据库限定的表授权)和 privilege_level = 't'(非限定的表授权),各自保留其原始权限级别。

不复制的内容:

  • 更宽泛的授权(如 db.**.*不会展开为目标表上的直接表授权。它们保持为宽泛授权,不会作为独立的条目物化。

  • 继承的授权(通过角色层级)不会被单独物化。仅复制父角色上的直接授权;子角色通过角色层级继承的方式与正常情况相同。

限制:

  • COPY GRANTS 不能与 TO ACCOUNT 一起使用。否则将报错:COPY GRANTS cannot be used with TO ACCOUNT

  • 即使未显式指定 TO ACCOUNT,跨不同租户克隆时也不能使用 COPY GRANTS。如果源表属于其他租户(例如通过快照),则操作将失败并报错:COPY GRANTS cannot be used when cloning across accounts

  • 当指定 IF NOT EXISTS 且目标表已存在时,COPY GRANTS 不会修改已有目标表的授权。已有授权保持不变。

快照行为:

通过快照克隆时,COPY GRANTS 读取的是快照时间戳时的源表授权状态,而不是当前实时授权。这意味着:

  • 快照创建后添加到源表的授权不会被复制。

  • 快照创建后从源表撤销的授权仍然会出现在克隆的目标表上。

独立性:

复制后的授权与源表的授权相互独立。克隆操作后撤销或修改源表上的授权不会影响已克隆目标表上的授权。

使用说明

  • 同一租户内的克隆操作可以直接执行,无需 snapshot

  • 跨租户克隆只能由 sys 租户执行,且必须预先创建 snapshot。跨租户克隆时若未指定 snapshot,将报错。

  • 只有 sys 租户可以将表或数据库克隆到其他租户。非 sys 租户尝试跨租户克隆将报错。

  • CLONE DATABASE 语句现在可正确解析源数据库,包括来自订阅(subscription)的数据库。当源数据库来自订阅时,克隆操作会自动解析其底层数据库名和所属租户。

  • snapshot 提供了数据的时间点视图,确保克隆操作的一致性

  • 克隆操作会复制表的结构、数据和相关元数据

  • COPY GRANTS 将源表的显式表级权限授予复制到克隆的目标表。宽泛授权(db.**.*)不会被展开。详细行为和限制请参见 COPY GRANTS 部分。

  • COPY GRANTS 不能与 TO ACCOUNT 一起使用,也不能跨不同租户克隆时使用。

  • 当指定 IF NOT EXISTS 且目标表已存在时,COPY GRANTS 不会修改已有表的授权。

  • 复制的授权与源表相互独立 —— 克隆后修改源表授权不会影响已克隆的表。

权限限制

  1. 系统数据库限制

    • 普通租户不能克隆系统数据库(mo_task, mo_catalog, system, mysql, system_metric, information_schema, mo_debug)

    • 所有租户(包括 sys)都不能将数据克隆到系统数据库下

  2. 集群表限制

    • 普通租户不能克隆集群表(cluster table)

    • 只有 sys 租户可以克隆系统表

  3. 订阅数据克隆

    • 普通租户只能克隆已订阅的数据库或表

    • 跨租户克隆必须由 sys 租户执行

示例

准备工作:创建测试租户、数据库和表

-- 在 sys 租户下创建测试租户
CREATE ACCOUNT acc1 ADMIN_NAME = 'admin' IDENTIFIED BY '111';
CREATE ACCOUNT acc2 ADMIN_NAME = 'admin' IDENTIFIED BY '111';

-- 连接到 acc1 租户创建测试数据
-- mysql -h 127.0.0.1 -P 6001 -u acc1:admin -p111
CREATE DATABASE acc1_db;
USE acc1_db;
CREATE TABLE acc1_tbl (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO acc1_tbl (id, name) VALUES (1, 'Alice'), (2, 'Bob');

-- 连接到 acc2 租户创建测试数据  
-- mysql -h 127.0.0.1 -P 6001 -u acc2:admin -p111
CREATE DATABASE acc2_db;
USE acc2_db;
CREATE TABLE acc2_tbl (
    id INT PRIMARY KEY,
    email VARCHAR(100)
);
INSERT INTO acc2_tbl (id, email) VALUES (1, 'alice@example.com'), (2, 'bob@example.com');

Case 1: 同一个租户中 clone

克隆表:

-- 在同一个租户内克隆表
CREATE TABLE acc1_db.t2 CLONE acc1_db.acc1_tbl;

mysql> SELECT * FROM acc1_db.acc1_tbl;
+------+-------+---------------------+
| id   | name  | created_at          |
+------+-------+---------------------+
|    1 | Alice | 2025-09-08 16:43:30 |
|    2 | Bob   | 2025-09-08 16:43:30 |
+------+-------+---------------------+
2 rows in set (0.01 sec)

-- 使用指定 snapshot 克隆
CREATE SNAPSHOT sp FOR ACCOUNT acc1;

CREATE TABLE acc1_db.t3 CLONE acc1_db.acc1_tbl {SNAPSHOT = "sp"};

mysql>  SELECT * FROM acc1_db.t3;
+------+-------+---------------------+
| id   | name  | created_at          |
+------+-------+---------------------+
|    1 | Alice | 2025-09-08 16:43:30 |
|    2 | Bob   | 2025-09-08 16:43:30 |
+------+-------+---------------------+
2 rows in set (0.01 sec)

克隆数据库:

-- 在同一个租户内克隆数据库
CREATE DATABASE acc1_db_clone CLONE acc1_db;

mysql> USE acc1_db_clone;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW TABLES;
+-------------------------+
| Tables_in_acc1_db_clone |
+-------------------------+
| acc1_tbl                |
| t2                      |
| t3                      |
+-------------------------+
3 rows in set (0.01 sec)

-- 使用指定 snapshot 克隆数据库
mysql> CREATE DATABASE acc1_db_clone_snapshot CLONE acc1_db {SNAPSHOT = "sp"};
Query OK, 0 rows affected (0.02 sec)

mysql> use acc1_db_clone_snapshot;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SHOW TABLES;
+----------------------------------+
| Tables_in_acc1_db_clone_snapshot |
+----------------------------------+
| acc1_tbl                         |
| t2                               |
+----------------------------------+
2 rows in set (0.01 sec)

**注意:**跨租户的 clone 只能由 sys 操作,且必须要先创建 snapshot

Case 2: clone 其他普通租户数据到 sys

-- 切换到 sys 租户
-- mysql -h 127.0.0.1 -P 6001 -u sys:root -p111

-- sys 为 acc1 租户创建 account 级别 snapshot
CREATE SNAPSHOT sp_acc1 FOR ACCOUNT acc1;

-- 克隆数据库到 sys
CREATE DATABASE sys_db_from_acc1 CLONE acc1_db {SNAPSHOT = "sp_acc1"};
mysql> use sys_db_from_acc1;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------------------+
| Tables_in_sys_db_from_acc1 |
+----------------------------+
| acc1_tbl                   |
| t2                         |
| t3                         |
+----------------------------+
3 rows in set (0.00 sec)

-- 克隆表到 sys
CREATE TABLE sys_db_from_acc1.acc1_tbl_clone CLONE acc1_db.acc1_tbl {SNAPSHOT = "sp_acc1"};

mysql> select * from sys_db_from_acc1.acc1_tbl_clone;
+------+-------+---------------------+
| id   | name  | created_at          |
+------+-------+---------------------+
|    1 | Alice | 2025-09-08 16:43:30 |
|    2 | Bob   | 2025-09-08 16:43:30 |
+------+-------+---------------------+
2 rows in set (0.01 sec)

Case 3: clone sys 租户的数据到其他普通租户

-- 在 sys 租户下创建测试数据
CREATE DATABASE sys_db;
USE sys_db;
CREATE TABLE sys_tbl (
    id INT PRIMARY KEY,
    data VARCHAR(100)
);
INSERT INTO sys_tbl (id, data) VALUES (1, 'Sys Data 1'), (2, 'Sys Data 2');

-- sys 为自己创建 snapshot
CREATE SNAPSHOT sp_sys FOR ACCOUNT sys;

-- 克隆数据库到普通租户 acc1
CREATE DATABASE acc1_from_sys CLONE sys_db {SNAPSHOT = "sp_sys"} TO ACCOUNT acc1;

-- 克隆表到普通租户 acc1
CREATE TABLE acc1_db.sys_tbl_clone CLONE sys_db.sys_tbl {SNAPSHOT = "sp_sys"} TO ACCOUNT acc1;

--连接 acc1
mysql> use acc1_from_sys;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-------------------------+
| Tables_in_acc1_from_sys |
+-------------------------+
| sys_tbl                 |
+-------------------------+
1 row in set (0.00 sec)

mysql> select * from acc1_db.sys_tbl_clone;
+------+------------+
| id   | data       |
+------+------------+
|    1 | Sys Data 1 |
|    2 | Sys Data 2 |
+------+------------+
2 rows in set (0.01 sec)

Case 4: clone 普通租户数据到另一个普通租户

-- sys 为源租户 acc1 创建 snapshot
CREATE SNAPSHOT sp_acc1_for_clone FOR ACCOUNT acc1;

-- 克隆表从 acc1 到 acc2
CREATE TABLE acc2_db.acc1_tbl_clone CLONE acc1_db.acc1_tbl {SNAPSHOT = "sp_acc1_for_clone"} TO ACCOUNT acc2;

-- 克隆数据库从 acc1 到 acc2
CREATE DATABASE acc2_from_acc1 CLONE acc1_db {SNAPSHOT = "sp_acc1_for_clone"} TO ACCOUNT acc2;

--连接租户 acc2

mysql> select * from acc2_db.acc1_tbl_clone;
+------+-------+---------------------+
| id   | name  | created_at          |
+------+-------+---------------------+
|    1 | Alice | 2025-09-08 16:43:30 |
|    2 | Bob   | 2025-09-08 16:43:30 |
+------+-------+---------------------+
2 rows in set (0.00 sec)

mysql> use acc2_from_acc1;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+--------------------------+
| Tables_in_acc2_from_acc1 |
+--------------------------+
| acc1_tbl                 |
| sys_tbl_clone            |
| t2                       |
| t3                       |
+--------------------------+
4 rows in set (0.01 sec)

注意事项

  • 权限要求

    • 同一租户内克隆需要源对象的 SELECT 权限和目标数据库的 CREATE 权限

    • 跨租户克隆只能由 sys 租户执行

    • 普通租户只能克隆已订阅的非系统数据库和表

  • 系统对象限制

    • 禁止克隆到系统数据库

    • 普通租户禁止克隆系统表和集群表

  • Snapshot 有效期

    • Snapshot 有有效期限制,过期后无法用于克隆操作

    • 建议在创建 snapshot 后尽快完成克隆操作

  • 资源消耗

    • 克隆操作会消耗存储空间和计算资源

    • 大型数据库或表的克隆可能需要较长时间

  • 数据一致性

    • 使用 snapshot 可以确保克隆数据的时间点一致性

    • 无 snapshot 的克隆反映的是当前时刻的数据状态