使用PLACEMENT POLICY后,exchange partition执行失败后,影响了非分区表的插入

背景: 希望通过exchange partition的操作,将一个非分区表改造成分区表,但是在操作时候,发现exchange partition操作会报失败,同时会影响非分区表的写入。报错内容是ERROR 1736 (HY000): Tables have different definitions,之后往非分区表插入超过对应分区定义的数据时候,就会报错ERROR 1748 (HY000): Found a row not matching the given partition set
操作日志如下,可稳定复现:

mysql>
mysql> CREATE TABLE `t1` (
    ->   `date` date NOT NULL ,
    ->   `name` varchar(10)  NOT NULL,
    ->   UNIQUE KEY `uk_1` (`date`,`name`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
Query OK, 0 rows affected (0.51 sec)

mysql> CREATE TABLE `t1_partition` (
    ->   `date` date NOT NULL ,
    ->   `name` varchar(10)  NOT NULL,
    ->   UNIQUE KEY `uk_1` (`date`,`name`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
    -> PARTITION BY RANGE COLUMNS(`date`)
    -> (PARTITION `p202307` VALUES LESS THAN ('2023-08-01'),
    ->  PARTITION `p202308` VALUES LESS THAN ('2023-09-01'),
    ->  PARTITION `p202309` VALUES LESS THAN ('2023-10-01'),
    ->  PARTITION `p202310` VALUES LESS THAN ('2023-11-01'),
    ->  PARTITION `p202311` VALUES LESS THAN ('2023-12-01'),
    ->  PARTITION `p202312` VALUES LESS THAN ('2024-01-01'),
    ->  PARTITION `pfuture` VALUES LESS THAN (MAXVALUE));
Query OK, 0 rows affected (0.52 sec)

mysql> insert into t1(date, name) values ("2023-07-02","0000"), ("2023-07-03","0000"), ("2023-07-04","0000"), ("2023-07-05","0000");
Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> alter table t1_partition exchange partition p202307 with table t1;
ERROR 1736 (HY000): Tables have different definitions
mysql> insert into t1(date, name) values ("2023-07-06","0000");
Query OK, 1 row affected (0.01 sec)

mysql> insert into t1(date, name) values ("2023-08-06","0000");
ERROR 1748 (HY000): Found a row not matching the given partition set
mysql> insert into t1(date, name) values ("2023-07-07","0000");
Query OK, 1 row affected (0.00 sec)

复现执行SQL如下:

CREATE TABLE `t1` (
  `date` date NOT NULL ,
  `name` varchar(10)  NOT NULL,
  UNIQUE KEY `uk_1` (`date`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;


CREATE TABLE `t1_partition` (
  `date` date NOT NULL ,
  `name` varchar(10)  NOT NULL,
  UNIQUE KEY `uk_1` (`date`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY RANGE COLUMNS(`date`)
(PARTITION `p202307` VALUES LESS THAN ('2023-08-01'),
 PARTITION `p202308` VALUES LESS THAN ('2023-09-01'),
 PARTITION `p202309` VALUES LESS THAN ('2023-10-01'),
 PARTITION `p202310` VALUES LESS THAN ('2023-11-01'),
 PARTITION `p202311` VALUES LESS THAN ('2023-12-01'),
 PARTITION `p202312` VALUES LESS THAN ('2024-01-01'),
 PARTITION `pfuture` VALUES LESS THAN (MAXVALUE));

insert into t1(date, name) values ("2023-07-02","0000"), ("2023-07-03","0000"), ("2023-07-04","0000"), ("2023-07-05","0000");

-- 此处报错了
alter table t1_partition exchange partition p202307 with table t1;

insert into t1(date, name) values ("2023-07-06","0000");
insert into t1(date, name) values ("2023-08-06","0000");

-- 以下没有执行
rename table t1 to t1_bak;
rename table t1_partition to t1;

6.6.0版本没有复现。。。
5.4.3版本也没复现。。。

出现问题后,即便使用另外一个LESS THAN (MAXVALUE)的分区表来进行exchange,也会继续报错

mysql> CREATE TABLE `t1_partition_all` (
    ->   `date` date NOT NULL ,
    ->   `name` varchar(10)  NOT NULL,
    ->   UNIQUE KEY `uk_1` (`date`,`name`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
    -> PARTITION BY RANGE COLUMNS(`date`)
    -> (PARTITION `pfuture` VALUES LESS THAN (MAXVALUE));
Query OK, 0 rows affected (0.54 sec)

mysql> alter table t1_partition_all exchange partition pfuture with table t1;
ERROR 1736 (HY000): Tables have different definitions
mysql> insert into t1(date, name) values ("2023-07-08","0000");
Query OK, 1 row affected (0.01 sec)

mysql> insert into t1(date, name) values ("2023-08-08","0000");
ERROR 1748 (HY000): Found a row not matching the given partition set
mysql>


额,7.1也没有复现

1 个赞

7.1.1没有复现

诡异,新建了一个6.5.3集群也没有报错,但是在出问题的集群里,可以稳定复现。即便是新创建其他表名,也会报错

知道了,是PLACEMENT POLICY引起的,加了PLACEMENT POLICY后,6.5.3和7.1都是可以稳定复现的

CREATE PLACEMENT POLICY rule1 FOLLOWERS=4;
CREATE TABLE `t1` (
  `date` date NOT NULL ,
  `name` varchar(10)  NOT NULL,
  UNIQUE KEY `uk_1` (`date`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin PLACEMENT POLICY=`rule1`;


CREATE TABLE `t1_partition` (
  `date` date NOT NULL ,
  `name` varchar(10)  NOT NULL,
  UNIQUE KEY `uk_1` (`date`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin  PLACEMENT POLICY=`rule1`
PARTITION BY RANGE COLUMNS(`date`)
(PARTITION `p202307` VALUES LESS THAN ('2023-08-01'),
 PARTITION `p202308` VALUES LESS THAN ('2023-09-01'),
 PARTITION `p202309` VALUES LESS THAN ('2023-10-01'),
 PARTITION `p202310` VALUES LESS THAN ('2023-11-01'),
 PARTITION `p202311` VALUES LESS THAN ('2023-12-01'),
 PARTITION `p202312` VALUES LESS THAN ('2024-01-01'),
 PARTITION `pfuture` VALUES LESS THAN (MAXVALUE));

insert into t1(date, name) values ("2023-07-02","0000"), ("2023-07-03","0000"), ("2023-07-04","0000"), ("2023-07-05","0000");

-- 此处报错了
alter table t1_partition exchange partition p202307 with table t1;

insert into t1(date, name) values ("2023-07-06","0000");
insert into t1(date, name) values ("2023-08-06","0000");
1 个赞

7.1.1这次复现了。

ERROR 1736 (HY000): Tables have different definitions

执行这条SQL,也会报ERROR 1748 (HY000): Found a row not matching the given partition set吧?

难道配置了placement rule的表就不能进行exchange partition操作了?

没exchange成功影响不大,但是非分区表直接不能写入超过partition定义的限制了,很坑、很坑。。。

1 个赞

我记得之前在6.5.2时候执行过,是成功的,不知道是不是后边引进的一个BUG


6.5.2,exchange partition报错了,但是插入不受影响

试下插入第二条2023-08-06记录

额,2020308的插入不了。。。
image

看这报错的意思,他把t1当成分区表了?但是t1上面有没有大于20230801的分区

是的,虽然没有exchange成功,但是元数据已经改了一半了,已经被认为是某个表的分区了,所以会进行检查

看起来是 ddl 的 bug,我开了个 issue:https://github.com/pingcap/tidb/issues/45791

看起来有两个问题:一个是 placement 规则的检查没有做好。第二个是因为1的原因ddl失败后中间状态的meta没有回滚。