华为云云数据库GaussDBDQL/DML-DDL并发_云淘科技

表级DDL会给分区表施加8级锁,阻塞全部的DQL/DML操作。

分区级DDL会给分区表施加4级锁,并给目标分区施加8级锁。当DQL/DML与DDL作用不同分区时,支持二者执行层面的并发;当DQL/DML与DDL作用相同分区时,后触发业务会被阻塞。

如果并发的DDL与DQL/DML作用目标分区有重叠,由于串行阻塞,DQL/DML既可能先于DDL发生,也可能后于DDL发生,用户应该明确知晓其可能的预期结果。比如当Truncate与Insert作用同一分区时,如果Truncate先于Insert触发,则业务完成后目标分区存在数据,如果Truncate后于Insert触发,则业务完成后目标分区不存在数据。

业务在进行分区DDL维护操作时,应尽可能避免期间同时对目标分区进行DQL/DML操作。

DQL/DML-DDL跨分区并发

GaussDB Kernel支持跨分区的DQL/DML-DDL并发。

例如,定义如下分区表range_sales,下面给出了一些支持并发的例子。

CREATE TABLE range_sales
(
    product_id     INT4 NOT NULL,
    customer_id    INT4 NOT NULL,
    time_id        DATE,
    channel_id     CHAR(1),
    type_id        INT4,
    quantity_sold  NUMERIC(3),
    amount_sold    NUMERIC(10,2)
)
PARTITION BY RANGE (time_id)
(
    PARTITION time_2008 VALUES LESS THAN ('2009-01-01'),
    PARTITION time_2009 VALUES LESS THAN ('2010-01-01'),
    PARTITION time_2010 VALUES LESS THAN ('2011-01-01'),
    PARTITION time_2011 VALUES LESS THAN ('2012-01-01')
);

分区表支持的并发业务可以为如下场景。

--并发case1,插入分区time_2011与清空分区time_2008互不阻塞
\parallel on
INSERT INTO range_sales VALUES (455124, 92121433, '2011-09-17', 'X', 4513, 7, 17);
ALTER TABLE range_sales TRUNCATE PARTITION time_2008 UPDATE GLOBAL INDEX;
\parallel off

--并发case2,指定分区time_2010查询与交换分区time_2009互不阻塞
\parallel on
SELECT COUNT(*) FROM range_sales PARTITION (time_2010);
ALTER TABLE range_sales EXCHANGE PARTITION (time_2009) WITH TABLE temp UPDATE GLOBAL INDEX;
\parallel off

--并发case3,对分区表range_ sales做更新与删除分区time_2008互不阻塞,这是因为更新SQL带条件剪枝到分区time_2010和time_2011上
\parallel on
UPDATE range_sales SET channel_id = 'T' WHERE channel_id = 'X' AND time_id > '2010-06-01';
ALTER TABLE range_sales DROP PARTITION time_2008 UPDATE GLOBAL INDEX;
\parallel off

--并发case4,对分区表range_ sales的任何DQL/DML操作与新增分区time_2012互不阻塞,这是因为新增分区对其他进行的业务不可见
\parallel on
DELETE FROM range_sales WHERE channel_id = 'T';
ALTER TABLE range_sales ADD PARTITION time_2012 VALUES LESS THAN ('2013-01-01');
\parallel off

DQL/DML-DDL同分区并发

GaussDB Kernel不支持同分区的DQL/DML-DDL并发,后触发业务会被先触发业务阻塞。

原则上,不建议用户在进行分区DDL时,同时对该分区进行DQL/DML操作,因为目标分区存在一个状态的突变过程,可能会导致业务的查询结果不符合预期。

如果由于业务模型不合理、无法剪枝等场景导致的DQL/DML和DDL作用分区有重叠时,考虑两种场景:

场景一:先触发DQL/DML,再触发DDL。DDL会被阻塞,等DQL/DML提交后再进行。

场景二:先触发DDL,再触发DQL/DML。DQL/DML会被阻塞,等DDL提交后再进行,由于分区元信息发生了变更,可能导致预期不合理。为了保证数据一致性,预期结果按照如下规则制定。

ADD分区

ADD分区会产生一个新的分区,这个新分区对期间触发的DQL/DML操作均是不可见的,无阻塞期。

DROP分区

DROP分区会将已有分区进行删除,期间触发的目标分区DQL/DML操作会被阻塞,阻塞完成后跳过对该分区的处理。

TRUNCATE分区

TRUNCATE分区会将已有分区清空数据,期间触发的目标分区DQL/DML操作会被阻塞,阻塞完成后继续对该分区进行处理。

注意期间触发的目标分区查询是查不到数据的,因为TRUNCATE操作提交后目标分区中不存有任何数据。

EXCHANGE分区

EXCHANGE分区会将一个已有分区与普通表进行交换,期间触发的目标分区DQL/DML操作会被阻塞,阻塞完成后继续对该分区进行处理,该分区的实际数据对应原普通表。

例外:如果分区表上存在GLOBAL索引,EXCHANGE命令带来UPDATE GLOBAL INDEX子句,且期间触发的分区表查询使用了GLOBAL索引,由于无法查询到交换后分区上的数据,在阻塞完成后查询业务会报错。

ERROR: partition xxxxxx does not exist on relation “xxxxxx”

DETAIL: this partition may have already been dropped by cocurrent DDL operations EXCHANGE PARTITION

SPLIT分区

SPLIT分区会将一个分区分割为多个分区,即使其中一个新分区与旧分区名字相同,也视为不同的分区。期间触发的目标分区DQL/DML操作会被阻塞,阻塞完成后业务报错。

ERROR: partition xxxxxx does not exist on relation “xxxxxx”

DETAIL: this partition may have already been dropped by cocurrent DDL operations SPLIT PARTITION

MERGE分区

MERGE分区会将多个分区合并为一个分区,如果合并后的分区与其中一个旧分区A名字相同,逻辑上视为相同分区。期间触发的目标分区DQL/DML操作会被阻塞,阻塞完成后,根据目标分区类型判断,如果目标分区是旧分区A,则作用于新分区;如果目标分区为其他旧分区,则业务报错。

ERROR: partition xxxxxx does not exist on relation “xxxxxx”

DETAIL: this partition may have already been dropped by cocurrent DDL operations MERGE PARTITION

RENAME分区

RENAME分区不会变更分区结构信息,期间触发的DQL/DML操作不会出现任何异常,但会被阻塞,直到RENAME操作提交。

MOVE分区

MOVE分区不会变更分区结构信息,期间触发的DQL/DML操作不会出现任何异常,但会被阻塞,直到MOVE操作提交。

父主题: 分区并发控制

同意关联代理商云淘科技,购买华为云产品更优惠(QQ 78315851)

内容没看懂? 不太想学习?想快速解决? 有偿解决: 联系专家