399 Star 1.3K Fork 1.5K

GVPopenGauss / openGauss-server

 / 详情

list分区在线重建btree索引,DML执行过程中并发重建索引,报错partition xxx does not exist on relation xxx

修复中
缺陷
创建于  
2022-12-02 15:54

【标题描述】:
【测试类型:SQL功能/存储功能/接口功能/工具功能/性能/并发/压力长稳/故障注入/安全/资料/编码规范】【测试版本:2.0.0】 问题描述

【操作系统和硬件信息】(查询命令: cat /etc/system-release, uname -a):
输入图片说明

【测试环境】(单机/1主x备x级联备):
单机
【被测功能】:
在线重建索引
【测试类型】:
功能测试
【数据库版本】(查询命令: gaussdb –V):
输入图片说明
【预置条件】:
关闭ustore

DROP INDEX idx_local_list_btree ;
DROP TABLE t_rebuild_p_list cascade;
CREATE TABLE t_rebuild_p_list (
id int,
name varchar(20)
)partition by list(id)
(partition p1 values (1,3,5),
partition p2 values (2,4,6),
partition p3 values (7,8,9,10));
INSERT INTO t_rebuild_p_list values(1,'liuyi');
INSERT INTO t_rebuild_p_list values(2,'chener');
INSERT INTO t_rebuild_p_list values(3,'zhangsan');
INSERT INTO t_rebuild_p_list values(4,'lisi');
INSERT INTO t_rebuild_p_list values(5,'wangwu');
INSERT INTO t_rebuild_p_list values(6,'zhaoliu');
INSERT INTO t_rebuild_p_list values(7,'sunqi');
INSERT INTO t_rebuild_p_list values(8,'zhouba');
INSERT INTO t_rebuild_p_list values(9,'wujiu');
CREATE INDEX idx_local_list_btree ON t_rebuild_p_list using btree(id) local;

【操作步骤】(请填写详细的操作步骤):

--打开两个会话
--会话1不断执行DML和DQL操作:
do language plpgsql $$    
declare    
begin    
  for i in 5..100000 loop    
    INSERT INTO t_rebuild_p_list values(10,'zhengshi');
     DELETE FROM t_rebuild_p_list WHERE id=10;
     PERFORM name FROM t_rebuild_p_list WHERE id<6 order by name;
    commit;    
  end loop;    
end;    
$$;    
--会话2重建索引
REINDEX INDEX concurrently  idx_local_list_btree ;
REINDEX INDEX concurrently  idx_local_list_btree partition p1_id_idx ;
REINDEX INDEX concurrently idx_local_list_btree partition p2_id_idx ;
REINDEX INDEX concurrently  idx_local_list_btree partition p3_id_idx ; 

【预期输出】:
执行DML及重建索引均成功

【实际输出】:
DML报错partition xxx does not exist on relation xxx
输入图片说明

【原因分析】:

  1. 这个问题的根因
  2. 问题推断过程
  3. 还有哪些原因可能造成类似现象
  4. 该问题是否有临时规避措施
  5. 问题解决方案
  6. 预计修复问题时间

【日志信息】(请附上日志文件、截图、coredump信息):

【测试代码】:

评论 (3)

XiyeLan 创建了缺陷

Hey @XiyeLan, Welcome to openGauss Community.
All of the projects in openGauss Community are maintained by @opengauss-bot.
That means the developers can comment below every pull request or issue to trigger Bot Commands.
Please follow instructions at Here to find the details.

Hi @XiyeLan, please use the command /sig xxx to add a SIG label to this issue.
For example: /sig sqlengine or /sig storageengine or /sig om or /sig ai and so on.
You can find more SIG labels from Here.
If you have no idea about that, please contact with @zhangxubo , @xiangxinyong .

yansong_lee 负责人设置为pengjiong
yansong_lee 优先级设置为次要

原因分析:
直接原因是因为二级分区表的实现代码,可能会在整个sql执行过程多个阶段的不同地方调用heap_open或partitionOpen这些函数,触发消费InvalidationMessage,导致索引分区oid找不到而报错。
为什么索引分区oid不存在(一般这种情况都会通过加锁在解决并发问题),是因为 在线重建索引 后面会进行swap,原索引分区oid的parentid换成了临时创建的索引oid,导致代码中索引和原索引分区之间的关系变了。

出现缺陷中的问题的其中一个流程:
在PartIterator执行算子开始执行时,会触发ExecReScanIndexScan()->ExecInitNextPartitionForIndexScan(),其中会重新调用heap_open去获取Relation,该函数会去消费InvalidationMessage;
ExecEndIndexScan()->releasePartitionList()-> SubPartitionOidGetParentRelation(),在索引扫描最后释放Partition,发现Partition的parentid不等于 索引oid,后面把Partition当成二级分区索引尝试去打开分区的Relation,最终找不到相关系统条目,报 ERROR。

间接原因是因为 在线重建索引 中的swap步骤,这个swap动作已经属于 DDL 范畴,对于swap的对象必须要加 排它锁 来处理并发问题。

pengjiong 添加协作者pengjiong
pengjiong 负责人pengjiong 修改为花花怪
pengjiong 取消协作者pengjiong
陈栋 任务状态待办的 修改为已确认
陈栋 任务状态已确认 修改为修复中

登录 后才可以发表评论

状态
负责人
项目
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
预计工期 (小时)
参与者(3)
5622128 opengauss bot 1581905080
C++
1
https://gitee.com/opengauss/openGauss-server.git
git@gitee.com:opengauss/openGauss-server.git
opengauss
openGauss-server
openGauss-server

搜索帮助