+
+
+[悲观模式](/dm/feature-shard-merge-pessimistic.md) `unlock` 包括以下操作:
+
+* 请求 owner 执行 DDL 操作。
+* 请求其他非 owner 的 DM-worker 跳过 DDL 操作。
+* 移除 DM-master 上的 lock 信息。
{{< copyable "shell-regular" >}}
@@ -126,7 +175,7 @@ Global Flags:
-s, --source strings MySQL Source ID.
```
-`shard-ddl-lock unlock` 命令支持以下参数:
+悲观模式相关参数:
+ `-o, --owner`:
- flag 参数,string,可选
@@ -141,6 +190,66 @@ Global Flags:
- 非 flag 参数,string,必选
- 指定需要执行 unlock 操作的 DDL lock ID(即 `shard-ddl-lock` 返回结果中的 `ID`)
+
+
+
+
+[乐观模式](/dm/feature-shard-merge-optimistic.md) `unlock` 包括以下操作:
+
+* 请求指定的处于冲突状态的上游表执行或跳过冲突 DDL 操作。
+* 对其他非指定的表不会进行任何操作。
+* 若操作后 DM-master 可以为所有分表生成兼容表结构,则 DM-master 上的 lock 信息将被自动移除。
+
+{{< copyable "shell-regular" >}}
+
+```bash
+shard-ddl-lock unlock -h
+```
+
+```
+Unlock un-resolved DDL locks forcely
+
+Usage:
+ dmctl shard-ddl-lock unlock [flags]
+
+Flags:
+ -a, --action string accept skip/exec values which means whether to skip or execute ddls (default "skip")
+ -d, --database string database name of the table
+ -f, --force-remove force to remove DDL lock
+ -h, --help help for unlock
+ -o, --owner string source to replace the default owner
+ -t, --table string table name
+
+Global Flags:
+ -s, --source strings MySQL Source ID.
+```
+
+乐观模式相关参数:
+
++ `-a, --action`:
+ - flag 参数,string,可选
+ - 不指定时,请求指定的上游表跳过该冲突 DDL 操作;指定为 exec 时,请求该上游表执行引起冲突的 DDL 操作
+ - 除非执行前已对下游合表表结构进行了适配修改,否则不应该指定为 exec 执行冲突 DDL。
+
++ `-s, --source`:
+ - flag 参数,string,乐观模式必填且目前只支持写一个
+ - 指定需要执行 unlock 操作的上游的 source ID,可通过 `shard-ddl-lock` 命令获取
+
++ `-d, --database`:
+ - flag 参数,string,乐观模式必填且目前只支持写一个
+ - 指定需要执行 unlock 操作的上游的数据库名称,可通过 `shard-ddl-lock` 命令获取
+
++ `-t, --table`:
+ - flag 参数,string,乐观模式必填且目前只支持写一个
+ - 指定需要执行 unlock 操作的上游的表名称,可通过 `shard-ddl-lock` 命令获取
+
++ `lock-id`:
+ - 非 flag 参数,string,必选
+ - 指定需要执行 unlock 操作的 DDL lock ID(即 `shard-ddl-lock` 返回结果中的 `ID`)
+
+
+
+
以下是一个使用 `shard-ddl-lock unlock` 命令的示例:
{{< copyable "shell-regular" >}}
@@ -158,7 +267,7 @@ shard-ddl-lock unlock test-`shard_db`.`shard_table`
## 支持场景
-目前,使用 `shard-ddl-lock unlock` 命令仅支持处理以下两种 sharding DDL lock 异常情况。
+目前,使用 `shard-ddl-lock unlock` 命令仅支持处理以下三种 sharding DDL lock 异常情况。
### 场景一:部分 MySQL source 被移除
@@ -401,3 +510,244 @@ MySQL 及 DM 操作与处理流程如下:
#### 手动处理后的影响
手动 unlock sharding DDL lock 后,后续的 sharding DDL 将可以自动正常迁移。
+
+### 场景三:乐观模式协调过程中出现表结构冲突
+
+#### Lock 异常原因
+
+在 DM-master 尝试自动协调乐观 DDL,需要等待所有 MySQL source 的表结构达到一致状态,锁信息才会被清除(详见[乐观分表合并协调原理](/dm/feature-shard-merge-optimistic.md#原理))。在 sharding DDL 迁移过程中,如果分表的 DDL 生成了不一致的表结构,例如部分分表添加 default 0 的列、而另一部分分表添加 default 1 的列,将造成 DM-master 无法生成兼容表结构,从而使得锁无法自动 unlock。
+
+#### 手动处理示例
+
+假设上游有 MySQL-1 (`mysql-replica-01`) 和 MySQL-2 (`mysql-replica-02`) 两个实例,其中 MySQL-1 中有 `shardddl1`.`tb1` 一个表,MySQL-2 中有 `shardddl1`.`tb1` 和 `shardddl1`.`tb2` 两个表。现在需要将这三个表合并后迁移到下游 TiDB 的 `shardddl`.`tb` 表中。
+
+初始表结构如下:
+
+{{< copyable "sql" >}}
+
+```sql
+SHOW CREATE TABLE shardddl1.tb1;
+```
+
+```
++---------------+-------------------------------------------+
+| Table | Create Table |
++---------------+-------------------------------------------+
+| tb1 | CREATE TABLE `tb1` (
+ `a` int(11) NOT NULL,
+ `b` int(11) NOT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |
++---------------+-------------------------------------------+
+```
+
+上游 MySQL-1 实例下的分表将执行以下 DDL 语句变更表结构:
+
+{{< copyable "sql" >}}
+
+```sql
+ALTER TABLE shardddl*.tb* MODIFY b INT DEFAULT 0;
+```
+
+上游 MySQL-2 实例下的分表将执行以下 DDL 语句变更表结构:
+
+{{< copyable "sql" >}}
+
+```sql
+ALTER TABLE shardddl*.tb* MODIFY b INT DEFAULT -1;
+```
+
+MySQL 及 DM 操作与处理流程如下:
+
+1. `mysql-replica-01` 对应的分表执行了对应的 DDL 操作进行表结构变更。
+
+ {{< copyable "sql" >}}
+
+ ```sql
+ ALTER TABLE shardddl1.tb1 MODIFY b INT DEFAULT 0;
+ ```
+
+2. DM-worker 接收到 `mysql-replica-01` 分表的 DDL 之后,将对应的 DDL 信息发送给 DM-master,DM-master 创建相应的 DDL lock。
+3. 使用 `shard-ddl-lock` 查看当前的 DDL lock 信息。
+
+ {{< copyable "shell-regular" >}}
+
+ ```bash
+ shard-ddl-lock test
+ ```
+
+ ```
+ {
+ "result": true,
+ "msg": "",
+ "locks": [
+ {
+ "ID": "test-`shardddl`.`tb`",
+ "task": "test",
+ "mode": "optimistic",
+ "owner": "",
+ "DDLs": [
+ ],
+ "synced": [
+ "mysql-replica-01-`shardddl1`.`tb1`"
+ ],
+ "unsynced": [
+ "mysql-replica-02-`shardddl1`.`tb1`",
+ "mysql-replica-02-`shardddl1`.`tb2`"
+ ]
+ }
+ ]
+ }
+ ```
+
+4. 由于业务需要,`mysql-replica-02` 对应的分表添加的列默认值为 -1,但下游最终结构希望默认值为 0。
+5. DM-worker 接受到 `mysql-replica-02` 分表的 DDL 之后,将对应的 DDL 信息发送给 DM-master,DM-master 无法生成兼容表结构,MySQL-2 上的同步暂停。此时使用 `shard-ddl-lock` 和 `query-status test` 命令可以查到具体问题:
+
+ {{< copyable "shell-regular" >}}
+
+ ```bash
+ shard-ddl-lock test
+ ```
+
+