问题现象
使用分区表进行DQL/DML业务,出现业务报错。
原因分析
导致分区表DQL/DML业务报错的原因有很多,需要根据具体的报错内容和报错的业务模型,来判断属于哪些场景。
这里列出一些常见的报错场景:
- 开启行迁移开关后,并发UPDATE/DELETE报错
- 关闭行迁移开关后,跨分区更新导致的报错
- 插入数据无法路由到已有分区导致的报错
处理方法
判断是否为开启行迁移开关导致的并发UPDATE/DELETE报错
报错场景
如果业务报错为以下两种场景之一,则说明为开启行迁移开关导致的并发UPDATE/DELETE报错。
--UPDATE业务报错
ERROR: partition table update conflict
DETAIL: disable row movement of table can avoid this conflict
--DELETE业务报错
ERROR: partition table delete conflict
DETAIL: disable row movement of table can avoid this conflict
原因分析
开启行迁移开关后,允许通过更新分区键的方式,将数据从一个分区更新到另一个分区;关闭行迁移开关后,如果业务试图将数据从一个分区更新到另一个分区,则业务会抛出报错。
开启/关闭行迁移开关的方法是创建分区表时申明ENABLE/DISABLE ROW MOVEMENT子句。也可以通过ALTER TABLE命令来修改:
--开启分区表t1的行迁移开关
ALTER TABLE t1 ENABLE ROW MOVEMENT;
--关闭分区表t1的行迁移开关
ALTER TABLE t1 DISABLE ROW MOVEMENT;
开启行迁移开关后,并发UPDATE/DELETE业务可能会报错。原因如下:
UPDATE和DELETE操作对于旧数据都是标记为已删除。在打开行迁移开关情况下,如果更新分区键时,导致了跨分区更新,内核会把旧分区中旧数据标记为已删除,在新分区中新增加一条数据,无法通过旧数据找到新数据。
在UPDATE和UPDATE并发、DELETE和DELETE并发、UPDATE和DELETE并发三个并发场景下,如果并发操作同一行数据时,数据跨分区和非跨分区结果有不同的行为。
- 对于数据非跨分区结果,第一个操作执行完后,第二个操作不会报错。
- 如果第一个操作是UPDATE,第二个操作能成功找到最新的数据,之后对新数据操作。
- 如果第一个操作是DELETE,第二个操作看到当前数据已经被删除而且找不到最新数据,就终止操作。
- 对于数据跨分区结果,第一个操作执行完后,第二个操作会报错。
- 如果第一个操作是UPDATE,由于新数据在新分区中,第二个操作不能成功找到最新的数据,就无法操作,之后会报错。
- 如果第一个操作是DELETE,第二个操作看到当前数据已经被删除而且找不到最新数据,但无法判断删除旧数据的操作源于UPDATE还是DELETE。如果是UPDATE,报错处理。如果是DELETE,终止操作,为了保持数据的正确性,同样报错处理。
处理方法
如果业务明确不存在跨分区更新分区键的业务,可以关闭关闭行迁移开关。
如果业务确实存在跨分区更新分区键的业务,需要串行执行业务才能解决问题;或者考虑更换分区键。
判断是否为关闭行迁移开关导致的跨分区更新报错
报错场景
如果业务报错为以下场景,则说明为关闭行迁移开关导致的跨分区更新报错。
ERROR: fail to update partitioned table "t1"
DETAIL: disable row movement
原因分析
关闭行迁移开关后,如果业务试图将数据从一个分区更新到另一个分区,则业务会抛出报错。
处理方法
如果业务确实存在跨分区更新分区键的业务,可以考虑打开行迁移开关,但需考虑是否可能会存在并发报错场景;或者考虑更换分区键。
判断是否为插入数据无法路由到已有分区导致的报错
报错场景
如果业务报错为以下场景,则说明为插入数据无法路由到已有分区导致的报错。
ERROR: inserted partition key does not map to any table partitiont
原因分析
导致这种场景出现的原因一般有两种,一种是因为分区定义不合理导致的业务异常,另一种是分区键类型设计不合理导致的比较异常。
分区定义不合理是指业务定义的分区结构无法满足全量表数据的匹配,有部分数据不属于任一已有分区。比如下面的业务就会抛出这种报错:
CREATE TABLE t1 (
c1 integer,
c2 integer
)
PARTITION BY RANGE (c1)
(
PARTITION p1 VALUES LESS THAN (100),
PARTITION p2 VALUES LESS THAN (200)
)
DISABLE ROW MOVEMENT;
INSERT INTO t1 VALUES(1,1),(201,1);
分区键类型设计不合理是指使用了不合理的分区键类型,导致数据的比较规则并不符合用户预期场景。比如按照字典序规则,字符串’9’比’100’大。下面的业务就会抛出这种报错:
CREATE TABLE t1 (
c1 varchar,
c2 integer
)
PARTITION BY RANGE (c1)
(
PARTITION p1 VALUES LESS THAN ('100'),
PARTITION p2 VALUES LESS THAN ('200')
)
DISABLE ROW MOVEMENT;
INSERT INTO t1 VALUES('9',1);
处理方法
如果是分区定义不合理导致的业务异常,需要重新设计分区结构。可以使用分区DDL命令,比如ADD分区、SPLIT分区、MERGE分区等来调整分区结构。
如果是分区键类型设计不合理导致的比较异常,目前不支持修改分区键所在列的类型,需要重新创建分区表。