StarRocks关于ConcurrentModificationException 问题的解决
背景
本文基于 StarRocks 3.1.7
目前在基于Starrocks做一些数据分析的操作(主要是做一些简单的查询),同事遇到了一些并发的问题:
ontent:2024-11-27 07:04:34,048 WARN (starrocks-mysql-nio-pool-214933|3593819) [StmtExecutor.execute():643] execute Exception, sql SELECT distinct(id) FROM `db`.`table` WHERE col1='xxx' AND col2='xxx'
java.util.ConcurrentModificationException: nullat java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:719) ~[?:?]at java.util.LinkedHashMap$LinkedValueIterator.next(LinkedHashMap.java:746) ~[?:?]at com.starrocks.sql.optimizer.statistics.StatisticsCalcUtils.deltaRows(StatisticsCalcUtils.java:176) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.statistics.StatisticsCalcUtils.getTableRowCount(StatisticsCalcUtils.java:114) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.statistics.StatisticsCalculator.computeOlapScanNode(StatisticsCalculator.java:257) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.statistics.StatisticsCalculator.visitLogicalOlapScan(StatisticsCalculator.java:225) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.statistics.StatisticsCalculator.visitLogicalOlapScan(StatisticsCalculator.java:161) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.operator.logical.LogicalOlapScanOperator.accept(LogicalOlapScanOperator.java:149) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.statistics.StatisticsCalculator.estimatorStats(StatisticsCalculator.java:177) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.task.DeriveStatsTask.execute(DeriveStatsTask.java:57) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.task.SeriallyTaskScheduler.executeTasks(SeriallyTaskScheduler.java:69) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.Optimizer.memoOptimize(Optimizer.java:595) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.Optimizer.optimizeByCost(Optimizer.java:201) ~[starrocks-fe.jar:?]at com.starrocks.sql.optimizer.Optimizer.optimize(Optimizer.java:134) ~[starrocks-fe.jar:?]at com.starrocks.sql.StatementPlanner.createQueryPlan(StatementPlanner.java:146) ~[starrocks-fe.jar:?]at com.starrocks.sql.StatementPlanner.planQuery(StatementPlanner.java:121) ~[starrocks-fe.jar:?]at com.starrocks.sql.StatementPlanner.plan(StatementPlanner.java:92) ~[starrocks-fe.jar:?]at com.starrocks.sql.StatementPlanner.plan(StatementPlanner.java:61) ~[starrocks-fe.jar:?]at com.starrocks.qe.StmtExecutor.execute(StmtExecutor.java:456) ~[starrocks-fe.jar:?]at com.starrocks.qe.ConnectProcessor.handleQuery(ConnectProcessor.java:392) ~[starrocks-fe.jar:?]at com.starrocks.qe.ConnectProcessor.dispatch(ConnectProcessor.java:506) ~[starrocks-fe.jar:?]at com.starrocks.qe.ConnectProcessor.processOnce(ConnectProcessor.java:782) ~[starrocks-fe.jar:?]at com.starrocks.mysql.nio.ReadListener.lambda$handleEvent$0(ReadListener.java:69) ~[starrocks-fe.jar:?]at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[?:?]at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[?:?]at java.lang.Thread.run(Thread.java:829) ~[?:?]
涉及到的表如下:
CREATE TABLE `table` (`id` bigint(20) NOT NULL ,`create_date` datetime NOT NULL ,`col1` varchar(64) NOT NULL ,`col2` varchar(20) NOT NULL
) ENGINE = OLAP PRIMARY KEY(`create_date`, `id`
) COMMENT ""
PARTITION BY date_trunc('month', create_date) DISTRIBUTED BY HASH(`id`) PROPERTIES ("replication_num" = "3", "in_memory" = "false", "enable_persistent_index" = "true", "replicated_storage" = "true", "partition_live_number" = "18", "compression" = "LZ4");
结论
StarRocks 对分区带有TTL的表,会后台启动线程轮询的去删除分区,轮询的间隔受到 dynamic_partition_check_interval_seconds
控制,
然而在查询的时候, Starrocks会做语法解析,以及基于CBO的优化,在这期间会统计涉及到的表的分区信息统计,而此时恰好遇到了后台线程的分区删除,导致了ConcurrentModificationException
并发异常。
目前可以参考这个issue ConcurrentModificationException when query during drop partition,以及 增大 dynamic_partition_check_interval_seconds(目前是10分钟) 这个参数来降低这种冲突的概率。
分析
这里主要涉及到两个部分:
一个部分是查询部分(主要是StmtExecutor.execute),一个是后台清理分区部分(DynamicPartitionScheduler)
查询部分
每个SQL查询都会经过 StmtExecutor.execute
方法,进而生成物理执行计划,而在生成物理执行计划的阶段,会经过Optimizer
阶段,这个阶段由于默认情况下是基于CBO的优化,所以会统计涉及的表所扫描的数据量,最终会走到 StatisticsCalcUtils.deltaRows
方法:
private static long deltaRows(Table table, long totalRowCount) {long tblRowCount = 0L;for (Partition partition : table.getPartitions()) {long partitionRowCount;TableStatistic tableStatistic = GlobalStateMgr.getCurrentStatisticStorage().getTableStatistic(table.getId(), partition.getId());if (tableStatistic.equals(TableStatistic.unknown())) {partitionRowCount = partition.getRowCount();} else {partitionRowCount = tableStatistic.getRowCount();}tblRowCount += partitionRowCount;}if (tblRowCount < totalRowCount) {return Math.max(1, (totalRowCount - tblRowCount) / table.getPartitions().size());} else {return 0;}}
这里会对 table.getPartitions
进行 迭代,也就是OlapTable的 idToPartition.valus
进行迭代, 注意 idToPartition
是HashMap
类型的,
总体的流程如下:
StmtExecutor.execute||\/
StatementPlanner.plan||\/
StatementPlanner.planQuery||\/
StatementPlanner.createQueryPlan||\/
Optimizer.optimize||\/
Optimizer.optimizeByCost||\/
Optimizer.memoOptimize||\/
SeriallyTaskScheduler.executeTasks||\/
DeriveStatsTask.execute||\/
StatisticsCalculator.estimatorStats||\/
StatisticsCalculator.computeOlapScanNode||\/
StatisticsCalcUtils.getTableRowCount||\/
StatisticsCalcUtils.deltaRows
后台清理部分
对于这种带有TTL的分区表来说,会有 DynamicPartitionScheduler
这个后台线程进行分区的删除。具体代码见:
protected void runAfterCatalogReady() {if (!initialize) {// check Dynamic Partition tables only when FE startinitDynamicPartitionTable();}setInterval(Config.dynamic_partition_check_interval_seconds * 1000L);if (Config.dynamic_partition_enable) {executeDynamicPartition();}executePartitionTimeToLive();}
其中删除分区的频率就是由 Config.dynamic_partition_check_interval_seconds
也就是dynamic_partition_check_interval_seconds
来决定的,
其中executeDynamicPartition
方法就是执行分区删除,具体数据流如下 :
executeDynamicPartition||\/
executeDynamicPartitionForTable||\/
getDropPartitionClause||\/
GlobalStateMgr.getCurrentState().dropPartition(db, olapTable, dropPartitionClause);||\/
olapTable.dropPartition(db.getId(), partitionName, clause.isForceDrop());||\/
idToPartition.remove(partition.getId());
其中 在 executeDynamicPartitionForTable
中 RangePartitionInfo rangePartitionInfo = (RangePartitionInfo) olapTable.getPartitionInfo();
会根据PartitionInfo
的信息来进行判断,只有 RangePartitionInfo
类型支持partition TTL删除,也就是Expression partitioning (recommended) 和Dynamic partitioning支持.
在最后的idToPartition.remove(partition.getId())
中就会删除正在进行查询迭代的idToPartition.values
,就是导致并发问题
相关文章:
StarRocks关于ConcurrentModificationException 问题的解决
背景 本文基于 StarRocks 3.1.7 目前在基于Starrocks做一些数据分析的操作(主要是做一些简单的查询),同事遇到了一些并发的问题: ontent:2024-11-27 07:04:34,048 WARN (starrocks-mysql-nio-pool-214933|3593819) [StmtExecutor.execute():643] execute Exceptio…...

网络安全防护指南:筑牢网络安全防线(5/10)
一、网络安全的基本概念 (一)网络的定义 网络是指由计算机或者其他信息终端及相关设备组成的按照一定的规则和程序对信息收集、存储、传输、交换、处理的系统。在当今数字化时代,网络已经成为人们生活和工作中不可或缺的一部分。它连接了世…...

替代FTP最佳跨网文件传输解决方案——FileLink
在传统的企业文件传输中,FTP(文件传输协议)曾因其便捷性和高效性被广泛应用。然而,其固有的安全漏洞、对大文件传输支持的局限性、易受网络攻击等问题,已逐渐暴露出FTP在现代企业环境下的不足。针对这一问题࿰…...
Cesium在vue2中的引入和注意事项
在Vue2中,可以使用npm包管理工具来安装Cesium,并通过import语句将其引入到项目中。下面是在Vue2中引入Cesium的步骤和注意事项: 步骤: 首先,打开终端并进入Vue项目的根目录。 运行以下命令来安装Cesium: …...

CentOS 9 配置静态IP
文章目录 1_问题原因2_nmcli 配置静态IP3_使用配置文件固定IP4_重启后存在的问题5_nmcli 补充 1_问题原因 CentOS 7 于 2014年6月发布,基于 RHEL 7,并在 2024年6月30日 结束维护。 CentOS 9 作为目前的最新版本,今天闲来闲来无事下载下来后…...
深入解析 Webhook:从原理到实践的全面指南
1. 引言 1.1 什么是 Webhook? Webhook 是一种基于 HTTP 回调的轻量级通信机制,它允许一个系统实时向另一个系统发送数据。当特定事件发生时,Webhook 会主动向指定的 URL 发送 HTTP 请求,通常携带事件相关的数据。这种被动接收通…...

基于springboot+vue实现的创新创业学分管理系统 (源码+L文+ppt)4-111
4 系统总体设计 4.1系统功能结构设计图 根据需求说明设计系统各功能模块。采用模块化设计方法实现一个复杂结构进行简化,分成一个个小的容易解决的板块,然后再将小的板块继续分化成功能单一的更小模块。模块化设计方法使测试调试、维护更容易ÿ…...

如何高效地架构一个Java项目
引言 Java是企业级应用开发的主流语言之一,而我们作为使用Java语言的程序员,职称有初级、中级、高级、资深、经理、架构,但我们往往只是慢慢通过经验的积累迭代了自己的等级,如果没有保持学习的习惯,大多数程序员会停留…...
Scala的模式匹配(8)
package hfdobject Test35_1 { //需求:现在有一个数组Array(1,2,3,4)。我希望能定义三个变量,他们的值分别是数组中的第1,2,3个元素的值 def main(args: Array[String]): Unit {val arr Array(1,2,3,4,5)//第一个元素的值:arr(0…...

nodejs30: CSS 剪辑路径clip-path导致伪元素不可见问题及解决方法
相关问题 应用圆角裁剪时无法显示::after 取消clip-path设置: 完整问题代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, i…...

Git分布式版本控制工具 Git基本概念、Git工作流程、Git常用命令、Git远程仓库、IDEA操作Git
目录 1.Git基本概念 1.1 概述 1.1.1 开发中的实际场景 1.1.2 版本控制器的方式 1.1.2.1 集中式版本控制工具(SVN) 1.1.2.2 分布式版本控制工具(Git) 2.概述git工作流程 3.Git常用命令 3.1 Git环境配置 3.1.1 下载与安装 3.1.2 基本配置 3.1.3 为常用指令配置别名&…...

十,[极客大挑战 2019]Secret File1
点击进入靶场 查看源代码 有个显眼的紫色文件夹,点击 点击secret看看 既然这样,那就回去查看源代码吧 好像没什么用 抓个包 得到一个文件名 404 如果包含"../"、"tp"、"input"或"data",则输出"…...
Android 获取数字键盘和输入类型
在Android中,获取数字键盘可以通过为EditText设置输入类型为number或numberPassword来实现。以下是一个简单的例子: <!-- 在XML布局文件中 --> <EditText android:id"id/editTextNumber" android:layout_width"match_parent…...

8. 一分钟读懂“代理模式”
8.1 模式介绍 代理模式是一种结构型设计模式,它通过提供一个代理对象来替代对另一个对象(真实对象)的访问。代理对象与真实对象实现相同的接口,并通过代理类对真实对象的访问进行控制,可以在调用前后执行附加操作&…...
【实战攻略】如何从零开始快速实现深度学习新想法?——四步走战略
标题 【实战攻略】如何从零开始快速实现深度学习新想法?——四步走战略 【核心结论】 通过四步走战略,即找到baseline论文、深入baseline代码、搭建自己的pipeline、融入核心算法,新手也能快速实现深度学习新想法。 【通俗解释࿰…...

Creating Server TCP listening socket *:6379: bind: No error
启动redis报错:Creating Server TCP listening socket *:6379: bind: No error 解决方案: 1、直接在命令行中输入 redis-cli.exe 2、输入shutdown,关闭 3、输exit,退出 4、重新输入 redis-server.exe redis.windows.conf&…...

Go热加载工具air-使用说明-win11问题解决指南
写web程序 每次都要ctrlc 然后go run .非常但疼 用一下这个热加载工具air Live reload for Go apps 贴个github地址:https://github.com/air-verse/air 1. go版本1.23先install一下 go install github.com/air-verse/airlatest下载完发现输入air windows还是报…...

华为HarmonyOS 让应用快速拥有账号能力 -- 2 获取用户头像昵称
场景介绍 如应用需要完善用户头像昵称信息,可使用Account Kit提供的头像昵称授权能力,用户允许应用获取头像昵称后,可快速完成个人信息填写。以下只针对Account kit提供的头像昵称授权能力进行介绍,若要获取头像还可通过场景化控…...

oracle表迁移至postgre
第一步: 导出表结构 进入脚本 第二步: 删除spool相关和prompt相关(不需要表空间的情况下) 类似以下语句 第三步: 修改数据类型 VARCHAR2 --> VARCHAR VARCHAR2(200 CHAR) --> VARCHAR(200) NUMBER(10,2) --> numeric(10,2…...

【PlantUML系列】类图(一)
目录 一、类 二、接口 三、抽象类 四、泛型类 五、类之间的关系 六、添加注释 七、包图 八、皮肤参数 一、类 使用class关键字定义类,类名后跟大括号,声明类的属性和方法。 属性:格式为{visibility} attributeName : AttributeType…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...