JDBC FetchSize不生效,批量变全量致OOM问题分析

背景

一个简单的基于 JDBC 采集数据库表的功能,当采集 Postgre SQL 某表,其数据量达到 500万左右的时候,程序一启动就将 JVM 堆内存「6G」干满了。

问题是程序中使用了游标的只前进配置,且设置了 fetchSize 属性:

queryStat = connection.prepareStatement(executeSql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
queryStat.setFetchSize(batchSize);

为什么这个批量拉取数据的配置不生效呢?本文记录这个问题的排查过程及优化方法。

导出堆内存

程序一启动,jmap -heap 查看堆内存,老年代直接干到 99.98 % ,这时的程序直接 Stop all the world ,僵了。
在这里插入图片描述
JVM 启动最大堆内存已经调整到 6G 了,还是撑不住。感觉 SQL 查询的时候一下子将表的全部结果都加载到内存了,前面配置的批量拉取设置根本没生效。导出堆内存文件,进行分析。

nohup jmap -F -dump:live,format=b,file=/home/dump-result.hprof 23055 &

堆内存太大了,只能走后台进程的方式导出,接近一个小时才导出了 dump 文件,5.8G,确实跟 JVM 最大内存一样了。

堆内存分析

使用 mat 打开这个文件,直接内存溢出了。然后修改 mat 的 JVM 参数到8G后,得到分析结果不对,才几十M,明显不符合。

有很多 unreachable object,重新修改 mat 配置,勾选 “keep unreachable objects”,同时修改展示单位为 MB:
在这里插入图片描述

删除上次分析的结果文件后,重新导入 dump 文件分析,得到分析结果:
在这里插入图片描述
点开 Leak Suspects 查看内存泄漏的地方,发现最大的对象4.5G ,是一个列表,列表元素类型是 org.postgresql.core.Tuple ,盲猜这个类就是 JDBC 封装的查询结果
在这里插入图片描述
而这个类的对象总数跟表记录总数基本一致:
在这里插入图片描述
少掉的那些,应该是 GC 努力回收过的,但是剩余量还是很大。

这基本验证了前面的猜测,批量查询实际上成了全量查询了。为了再次确认,调整代码,造一张同结构、但是数据总量6万左右的表,然后在 while(result.next()) 遍历的循环里面加上 sleep 10 分钟后启动程序,导出堆内存。

这次程序老年代内存没有撑满,导出内存分析,Tuple 这个查询结果类对象的个数,跟数据库表总记录数「58000」多了21,基本可以确定这个批量size 没有生效。
在这里插入图片描述

问题分析

为什么批量加载不生效呢?是数据库的问题?驱动的问题?

尝试的方法:

  1. ❌升级数据库驱动为最新版本,无效。
  2. ❌在 while(result.next()) 遍历过程中,直接打印一个字符串后 continue,休眠5秒,手动调用 GC。不做任何操作,且手动触发 GC,JVM 内存还是满了。
  3. ❌怀疑数据库有问题,确定测试环境版本和出问题的现场环境一致。
  4. ❌目标数据库是基于 OpenGauss 自研的数据库,难道不支持游标的批量获取数据?

搜到一篇文章 《Postgres查询结果集的获取方法及其优缺点》 ,里面提到了 PostgreSQL 数据库的批量获取游标结果集生效的四个条件:

  1. 连到数据库服务的连接必须是基于V3协议的,V3协议是7.4及更新版本PG才能支持的,并且是他们的默认协议;
  2. Connection必须是非自动提交模式.后端会在事务的结束的时候关闭游标,所以,在自动提交模式里,还没从游标里获取任何东西的时候,后端就已经把游标关闭了。「冷知识:Connection 默认是自动提交的。」
  3. Statement必须以ResultSet.TYPE_FORWARD_ONLY的类型来创建,该结果集类型是默认的,所以可以直接使用stmt = conn.createStatement()来创建(或者stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY)).因此基于游标的结果集是只能向前获取,不能向后或者跳跃获取的。「PS:PostgreSQL默认就是这个类型,所以这个不是关键。
  4. 查询sql语句必须是一个单一的语句,不能是由分好分隔的多个语句。这个在本应用中不存在。

之前没仔细注意第2点,找了三天实在没办法了。又打开这篇文章,仔细看了一下,发现了这个点。

检查代码确实没有设置自动提交参数,加上它,还原 JVM 参数为2G,然后测试500万条数据顺利采集完成,老年代堆只占2%。

复测验证:再去掉这行代码,回到原点,还是一启动就堆满了,确定这行代码就是关键。排查了三天的问题,就这么简单的一行代码就解决了吗?赶在周末之前干掉问题,真是太幸运了。

优化结果

继续优化,循环遍历数据总量到达一个值后,手动触发 GC并休眠1秒:

// 手动触发GC,且休眠等待
if (count == maxFetchSize) {logger.info("Reach max batch size {}, sleep 1s to gc", maxFetchSize);count = 0;// 手动触发 GCRuntime.getRuntime().gc();// 等待GC完成Thread.sleep(1000);
}

将优化后的结果,加上 sleep 10分钟后,导出堆栈分析,发现这次 Tuple 类的个数就是 setFetchSize=2000,还多了21个。
在这里插入图片描述
跟上面那个一样,数据总量+21,说明额外还有 21 个对象,为查询操作提供了不为人知的功能。总归来说,只有加上这句话 connection.setAutoCommit(false); 才生效,才是真正的批量查询数据。

启示录

一开始就检索到了 《Postgres查询结果集的获取方法及其优缺点》 这篇文章,里面提到了 PostgreSQL 数据库的批量获取游标结果集生效的方法,但是忽略了重要的那个条件。

循环处理数据时,达到一个值后,手动触发 GC 还是有效的,可以让整个采集过程中老年代内存占用情况稳定在 2% 左右;如果去掉 GC 的话,内存会缓慢升至 10% 左右,但是已经不会再僵死了。

这个 JDBC 的批量查询不生效问题,前年冬天采集 Doris 的时候也发现了,只是后来没有细究。这次又碰到了,不知掉 Doris 能不能用这个配置解决呢?或者说 Doris 数据库支不支持批量查询呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/42657.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV 图形API(或称G-API)

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 引言 OpenCV 图形API(或称G-API)是一个新的OpenCV模块,旨在使常规图像处理更快且更便携。通过引入一种新的基于图的执行…

注意!ChatGPT 全新 AI 图像功能延迟对免费用户开放

2025 年 3 月 25 日,OpenAI 正式宣布在 ChatGPT 中推出基于 GPT-4o 模型的全新原生图像生成功能。 这一功能允许用户通过对话生成和编辑图像,支持从写实风格到插图风格的多种形式。OpenAI 首席执行官萨姆・奥特曼(Sam Altman)在社…

方阵幂次(矩阵快速幂)

#include <bits/stdc.h> using namespace std;int n; vector<vector<int>> fuc(vector<vector<int>> a,vector<vector<int>> b){ // 矩阵乘法函数vector<vector<int>> f(n,vector<int>(n));for(int i0;i<n;i){…

MySQL-- 多表查询的分类,SQL92与SQL99,7种JOIN的实现,SQL99语法的新特性

目录 一&#xff0c;多表查询的分类 角度1&#xff1a;等值连接 vs 非等值连接 角度2&#xff1a;自连接 vs 非自连接 角度3&#xff1a;内连接 vs 外连接 二&#xff0c;SQL92语法实现内连接&#xff1a;见上&#xff0c;略SQL92语法实现外连接&#xff1a;使用 -…

IEEE PDF Xpress校验出现 :字体无法嵌入问题以及pdf版本问题

文章目录 问题描述一、字体嵌入问题首先查看一下&#xff0c;哪些字体没有被嵌入查看window的font文件夹里的字体下载字体的网站修复字体嵌入问题 二、pdf版本不对 问题描述 在处理IEEE的camera ready的时候&#xff0c;提交到IEEE express的文件没有办法通过validate&#xf…

产生式系统的完整示例——医疗诊断系统(附python代码)

产生式系统在现实社会中依然有很重要的应用价值&#xff0c;为了更好的理解它的构建、推理以及完整的实现过程&#xff0c;本文一医疗诊断系统为例&#xff0c;进行详细说明。以下是一个包含10条规则的医疗诊断产生式系统示例&#xff0c;包含完整的规则定义、推理流程图、Pyth…

【CSS3】02-选择器 + CSS特性 + 背景属性 + 显示模式

本文主要介绍&#xff1a;选择器、CSS属性、背景属性和显示模式的操作写法。 目录 1. 复合选择器 1.1 后代选择器 1.2 子代选择器 1.3 并集选择器 1.4 交集选择器 2. 伪类选择器 2.1 超链接&#xff08;拓展&#xff09; 3. CSS特性 3.1 继承性 3.2 层叠性 3.3 优先…

清华大学第10讲:迈向未来的AI教学实验396页PPT 探索未来教育的无限可能|附PPT下载方法

导 读INTRODUCTION 今天跟大家分享的是清华大学新闻与传播学院、人工智能学院双聘教授沈阳教授团队出品的《迈向未来的AI教学实验》课程作业集&#xff0c;随着人工智能技术的飞速发展&#xff0c;教育领域也迎来了前所未有的变革。该报告为沈阳教授与学生们在“迈向未来的AI教…

亮数据爬取API爬取亚马逊电商平台实战教程

前言 在当今数据驱动的商业环境中&#xff0c;企业需要快速、精准地获取互联网上的公开数据以支持市场分析、竞品调研和用户行为研究。然而&#xff0c;传统的手动网页爬取方式面临着诸多挑战&#xff1a;IP封锁、验证码干扰、网站结构频繁变更&#xff0c;以及高昂的运维成本…

【新手初学】读取服务器敏感文件数据

一、引言 想要让利用注入点让SQL语句能执行读取相关文件的操作&#xff0c;需要一个非常重要的条件&#xff0c;即在MySql数据库的配置文件my.ini中一定要有 secure file priv" " 二、读取文件配置 ①在虚拟机中查看my.ini文件中有没有secure file priv" &qu…

央视少儿APP V2.6.2

安装好软件就能直接看&#xff0c;界面干净&#xff0c;播放流畅得很。里面的内容都是经过严格筛选的&#xff0c;动画、纪录片、教育课程这些资源应有尽有 这款软件的画质高清到让人惊艳&#xff0c;就算不登录也丝毫不影响观看体验&#xff0c;播放的时候几乎不用缓冲&#…

mysqlworkbench导入.sql文件

1、MySQL Workbench 新建数据库 或者 在左侧导航栏的 ​Schemas 区域右键选择 ​Create Schema...输入数据库名称&#xff08;例如 mydatabase&#xff09;&#xff0c;点击 ​Apply确认创建&#xff0c;点击 ​Finish 2、选择目标数据库 在左侧导航栏的 ​Schemas 列表中&a…

比较4点结构和4次函数

在行列可自由变换的平面上3点结构只有6个 设与之对应的函数分别是 3a1 x*x*y y*y*x 3a2 xy*y*y 3a3 x*x*y y*y*y 3a4 x*x*x y*y*x 3a5 x*x*xy*y*y 3a6 x*x*xy 用同样的办法计算4点结构的16个函数 4(4a1-1)2*3a32*3a1 4(4a2-1)3a43a33a53a1 4(4a3-1)3a23a3…

线性回归 + 基础优化算法

线性回归 线性回归是机器学习最基础的模型&#xff0c;也是理解后续所有深度学习的基础。 线性模型可以看做是单层神经网络。 上述有个0.5是在求导的时候可以很方便的将2消去。 实际上&#xff0c;这里的数据样本受限很大&#xff0c;比如地球上房子就那么多&#xff0c;肯…

邪性!Anaconda安装避坑细节Windows11

#工作记录 最近不断重置系统和重装Anaconda&#xff0c;配置的要累死&#xff0c;经几十次意料之外的配置状况打击之后&#xff0c;最后发现是要在在Anaconda安装时&#xff0c;一定要选“仅为我安装”这个选项&#xff0c;而不要选“为所有用户安装”这个选项。 选“仅为我安…

llamafactory微调效果与vllm部署效果不一致如何解决

在llamafactory框架训练好模型之后&#xff0c;自测chat时模型效果不错&#xff0c;但是部署到vllm模型上效果却很差 这实际上是因为llamafactory微调时与vllm部署时的对话模板不一致导致的。 对应的llamafactory的代码为 而vllm启动时会采用大模型自己本身设置的对话模板信息…

修改菜品-02.代码开发

一.Controller层 package com.sky.controller.admin;import com.sky.dto.DishDTO; import com.sky.dto.DishPageQueryDTO; import com.sky.entity.Dish; import com.sky.result.PageResult; import com.sky.result.Result; import com.sky.service.DishService; import com.sk…

探秘Transformer系列之(19)----FlashAttention V2 及升级版本

探秘Transformer系列之&#xff08;19&#xff09;----FlashAttention V2 及升级版本 文章目录 探秘Transformer系列之&#xff08;19&#xff09;----FlashAttention V2 及升级版本0x00 概述0x01 FlashAttention V21.1 动机1.2 方案1.2.1 减少冗余计算1.2.2 增加并行1.2.3 调整…

解决HuggingFaceEmbeddings模型加载报错:缺少sentence-transformers依赖包

遇到报错 报错信息: Error loading model: Could not import sentence_transformers python package. Please install it with pip install sentence-transformers. 装包信息&#xff1a; pip install modelscope langchain sentence_transformers langchain-huggingface on…

外星人入侵(python设计小游戏)

这个游戏简而言之就是操作一个飞机对前方的飞船进行射击&#xff0c;和一款很久之前的游戏很像&#xff0c;这里是超级低配版那个游戏&#xff0c;先来看看效果图&#xff1a; 由于设计的是全屏的&#xff0c;所以电脑不能截图。。。。 下面的就是你操控的飞船&#xff0c;上面…