datax连接池泄漏问题排查及解决

news2024/10/23 21:14:00

1、问题描述

频繁调用datax服务(从oracle同步到mysql)出现报错,获取不到连接

oracle读取时报错信息

"errorMessage": "Code:[DBUtilErrorCode-10], Description:[连接数据库失败. 请检查您的 账号、密码、数据库名称、IP、Port或者向 DBA 寻求帮助(注意网络环境).].  - 数据库连接失败. 因为根据您配置的连接信息,无法从:jdbc:oracle:thin:@//10.27.19.106:1722/BMS 中找到可连接的jdbcUrl. 请检查您的配置并作出修改. - java.lang.Exception: DataX无法连接对应的数据库,可能原因是:1) 配置的ip/port/database/jdbc错误,无法连接。2) 配置的username/password错误,鉴权失败。请和DBA确认该数据库的连接信息是否正确。\tat com.alibaba.datax.plugin.rdbms.util.DBUtil$2.call(DBUtil.java:73)\tat com.alibaba.datax.plugin.rdbms.util.DBUtil$2.call(DBUtil.java:53)\tat com.alibaba.datax.common.util.RetryUtil$Retry.call(RetryUtil.java:164)\tat com.alibaba.datax.common.util.RetryUtil$Retry.doRetry(RetryUtil.java:111)\tat com.alibaba.datax.common.util.RetryUtil.executeWithRetry(RetryUtil.java:30)\tat com.alibaba.datax.plugin.rdbms.util.DBUtil.chooseJdbcUrl(DBUtil.java:53)\tat com.alibaba.datax.plugin.rdbms.reader.util.OriginalConfPretreatmentUtil.dealJdbcAndTable(OriginalConfPretreatmentUtil.java:92)\tat com.alibaba.datax.plugin.rdbms.reader.util.OriginalConfPretreatmentUtil.simplifyConf(OriginalConfPretreatmentUtil.java:59)\tat com.alibaba.datax.plugin.rdbms.reader.util.OriginalConfPretreatmentUtil.doPretreatment(OriginalConfPretreatmentUtil.java:33)\tat com.alibaba.datax.plugin.rdbms.reader.CommonRdbmsReader$Job.init(CommonRdbmsReader.java:55)\tat com.alibaba.datax.plugin.reader.oraclereader.OracleReader$Job.init(OracleReader.java:37)\tat com.alibaba.datax.core.job.JobContainer.initJobReader(JobContainer.java:696)\tat com.alibaba.datax.core.job.JobContainer.init(JobContainer.java:315)\tat com.alibaba.datax.core.job.JobContainer.start(JobContainer.java:119)\tat com.alibaba.datax.core.Engine.start(Engine.java:101)\tat com.alibaba.datax.core.Engine.entry(Engine.java:227)\tat com.midea.logistics.datasync.dataxservice.service.impl.DataxServiceImpl.lambda$doExecute$0(DataxServiceImpl.java:114)\tat java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1640)\tat java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1632)\tat java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)\tat java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)\tat java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)\tat java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)"

mysql写入时报错信息

2024-10-18 15:32:07,133 [] ERROR c.a.datax.plugin.rdbms.util.DBUtil 420 - 从连接池中获取连接异常:
com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 10007, active 250, maxActive 250, creating 0
    at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1512)
    at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1255)
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1235)
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1225)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil.connect(DBUtil.java:418)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil.access$000(DBUtil.java:22)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil$3.call(DBUtil.java:324)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil$3.call(DBUtil.java:321)
    at com.alibaba.datax.common.util.RetryUtil$Retry.call(RetryUtil.java:164)
    at com.alibaba.datax.common.util.RetryUtil$Retry.doRetry(RetryUtil.java:111)
    at com.alibaba.datax.common.util.RetryUtil.executeWithRetry(RetryUtil.java:30)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil.getConnection(DBUtil.java:321)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil.getConnection(DBUtil.java:305)
    at com.alibaba.datax.plugin.rdbms.writer.CommonRdbmsWriter$Task.prepare(CommonRdbmsWriter.java:245)
    at com.alibaba.datax.plugin.writer.mysqlwriter.MysqlWriter$Task.prepare(MysqlWriter.java:73)
    at com.alibaba.datax.core.taskgroup.runner.WriterRunner.run(WriterRunner.java:50)
    at java.lang.Thread.run(Thread.java:750)

2、问题排查解决过程

2.1 第一反应猜测是数据库连接池连接不够用,获取连接等待时长过短,导致获取不到连接时报错,原来设置的maxActive(最大连接)200个,maxWai(t最大等待时长)6s,修改为maxActive=250,maxWai=12s

     结果发现并没什么效果,排除了这两个因素,但是发现了一个规律:maxActive=200时,从第201个任务就开始一直报错,maxActive=250时,从第251个任务就开始一直报错,于是猜测很有可能是连接池没有回收获取的连接

2.2 咨询业务系统报错任务的执行频率(配了5个任务,有的任务是每隔3分钟执行一次,有的任务是4分钟执行一次,基本是同一个时间点,耗时最长80S秒,3个小时后,就报连接失败了),发现频率也不是特别高,耗时也不是特别长

      补充描述:datax源码oracle切片那里获取了连接,没关闭。排查代码发现确实没关闭,调整后如下图,正常关闭连接

接着担心还有其它地方有类似问题,于是把调用关闭连接那里的所有引用代码都排查了一遍,未发现其它有遗漏的

2.3 接着2.2调整后测试,虽然没有了oracle的报错,但是mysql的报错依然存在,于是又仔细排查了一下代码,mysql写入时调用关闭连接的方法,有没有正常关闭连接,结果发现都是没问题的,但是连接没回收确实是事实,只能怀疑有些地方代码没按套路出牌

2.4 验证主动关闭连接触发回收和强制回收,看看是哪个环节有问题(主动关闭肯定有问题),当前参数removeAbandonedTimeout(连接池强制回收连接)是8h,为了看出效果,把removeAbandonedTimeout设置成了10s,

     测试发现:大部分任务都是成功的,仍有少部分任务获取不到连接,并且报错任务无规律,于是得出结论:强制回收连接是生效的,如果当前任务刚好获取到了强制回收的连接就是成功的,那么就要研究如何从代码中排查连接池泄漏

2.5 上百度搜索如何排查数据库连接池泄漏,了解到durid连接池有个参数:LogAbandoned,设置为true时,会打印回收连接时的错误信息,于是调整后有了新的发现,如下,直接把回收连接异常时的堆栈信息打印出来了,主要是这个方法有问题:OriginalConfPretreatmentUtil.dealColumnConf()

2024-10-21 10:33:19,144 [] ERROR c.a.druid.pool.DruidDataSource 2666 - abandon connection, owner thread: job-0, connected at : 1729477939179, open stackTrace
    at java.lang.Thread.getStackTrace(Thread.java:1564)
    at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1313)
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1235)
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1225)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil.connect(DBUtil.java:419)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil.access$000(DBUtil.java:22)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil$3.call(DBUtil.java:324)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil$3.call(DBUtil.java:321)
    at com.alibaba.datax.common.util.RetryUtil$Retry.call(RetryUtil.java:164)
    at com.alibaba.datax.common.util.RetryUtil$Retry.doRetry(RetryUtil.java:111)
    at com.alibaba.datax.common.util.RetryUtil.executeWithRetry(RetryUtil.java:30)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil.getConnection(DBUtil.java:321)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil.getConnection(DBUtil.java:305)
    at com.alibaba.datax.plugin.rdbms.util.JdbcConnectionFactory.getConnecttion(JdbcConnectionFactory.java:27)
    at com.alibaba.datax.plugin.rdbms.writer.util.OriginalConfPretreatmentUtil.dealColumnConf(OriginalConfPretreatmentUtil.java:125)
    at com.alibaba.datax.plugin.rdbms.writer.util.OriginalConfPretreatmentUtil.dealColumnConf(OriginalConfPretreatmentUtil.java:140)
    at com.alibaba.datax.plugin.rdbms.writer.util.OriginalConfPretreatmentUtil.doPretreatment(OriginalConfPretreatmentUtil.java:35)
    at com.alibaba.datax.plugin.rdbms.writer.CommonRdbmsWriter$Job.init(CommonRdbmsWriter.java:41)
    at com.alibaba.datax.plugin.writer.mysqlwriter.MysqlWriter$Job.init(MysqlWriter.java:31)
    at com.alibaba.datax.core.job.JobContainer.initJobWriter(JobContainer.java:727)
    at com.alibaba.datax.core.job.JobContainer.init(JobContainer.java:316)
    at com.alibaba.datax.core.job.JobContainer.start(JobContainer.java:119)
    at com.alibaba.datax.core.Engine.start(Engine.java:101)
    at com.alibaba.datax.core.Engine.entry(Engine.java:227)
    at com.midea.logistics.datasync.dataxservice.service.impl.DataxServiceImpl.lambda$doExecute$0(DataxServiceImpl.java:108)

2.6 进入相关代码发现获取连接是个野路子,而常规都是从DBUtil封装的从连接池获取连接

点进去 dealColumnConf(originalConfig, jdbcConnectionFactory, oneTable);

发现非异常逻辑,会调用DBUtil.getColumnMetaData(connectionFactory.getConnecttion(), oneTable,StringUtils.join(userConfiguredColumns, ","));点进去

看到这里已经真相大白了,根本没关闭连接,于是对代码进行了改造,从DBUtil获取连接,并在最外面一层调用后关闭连接,如下:

修改完后继续测试,发现又多了个新的报错信息:

com.alibaba.datax.common.exception.DataXException: Code:[DBUtilErrorCode-01], Description:[获取表字段相关信息失败.].  - 获取表:GEN_IDGEN_TEST_18 的字段的元信息时失败. 请联系 DBA 核查该库、表信息. - java.sql.SQLException: connection holder is null
    at com.alibaba.druid.pool.DruidPooledConnection.checkStateInternal(DruidPooledConnection.java:1157)
    at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.java:1148)
    at com.alibaba.druid.pool.DruidPooledConnection.createStatement(DruidPooledConnection.java:636)
    at com.alibaba.datax.plugin.rdbms.util.DBUtil.getColumnMetaData(DBUtil.java:602)
    at com.alibaba.datax.plugin.rdbms.writer.util.OriginalConfPretreatmentUtil.dealColumnConf(OriginalConfPretreatmentUtil.java:119)
    at com.alibaba.datax.plugin.rdbms.writer.util.OriginalConfPretreatmentUtil.dealColumnConf(OriginalConfPretreatmentUtil.java:136)
    at com.alibaba.datax.plugin.rdbms.writer.util.OriginalConfPretreatmentUtil.doPretreatment(OriginalConfPretreatmentUtil.java:36)
    at com.alibaba.datax.plugin.rdbms.writer.CommonRdbmsWriter$Job.init(CommonRdbmsWriter.java:41)
    at com.alibaba.datax.plugin.writer.mysqlwriter.MysqlWriter$Job.init(MysqlWriter.java:31)
    at com.alibaba.datax.core.job.JobContainer.initJobWriter(JobContainer.java:727)
    at com.alibaba.datax.core.job.JobContainer.init(JobContainer.java:316)
    at com.alibaba.datax.core.job.JobContainer.start(JobContainer.java:119)
    at com.alibaba.datax.core.Engine.start(Engine.java:101)
    at com.alibaba.datax.core.Engine.entry(Engine.java:227)
    at com.midea.logistics.datasync.dataxservice.service.impl.DataxServiceImpl.lambda$doExecute$0(DataxServiceImpl.java:108)

于是根据报错信息找到相关代码

第一反应就是连接为空,猜测可能是连接被关闭了,还在执行逻辑

   接着排查这一部分的代码,发现:List<String> allColumns = DBUtil.getTableColumnsByConn(DATABASE_TYPE, conn, oneTable, ""),这段代码提前将连接关闭了

排查发现这段代码还有一处地方调用,于是决定将这里调整为不关闭连接,引用到这个方法的地方自行关闭,如下:

继续测试,任务成功,没有报错信息

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

print_hex_dump调试内核,嘎嘎香

本文首发于我的公众号 皮塞作坊 专注于干货分享&#xff0c;号欢迎大家关注,二维码文末可以扫。 公众号: 使用print_hex_dump调试内核/驱动&#xff0c;太香了 最近在验证芯片功能的过程中发现了一个好用的内核调试接口&#xff0c;print_hex_dump&#xff0c;除了直接打印16…

【AIGC】关键词智能匹配:AI驱动的RAG知识库检索技术全解析

随着大语言模型的快速发展&#xff0c;AI在知识获取和生成中的应用越发广泛。RAG&#xff08;Retrieval-Augmented Generation&#xff09;模型通过结合外部知识库&#xff0c;提升了生成文本的质量与准确性&#xff0c;而关键词搜索是其关键组成部分。本文将深入探讨AI如何通过…

【java】数组(超详细总结)

目录 一.一维数组的定义 1.创建数组 2.初始化数组 二.数组的使用 1.访问数组 2.遍历数组 3.修改数据内容 三.有关数组方法的使用 1.toString 2. copyOf 四.查找数组中的元素 1.顺序查找 2.二分查找binarySearch 五.数组排序 1.冒泡排序 2.排序方法sort 六.数组逆置…

LabVIEW伺服压机是如何实现压力位移的精度?

LabVIEW伺服压机通过精确的压力和位移控制&#xff0c;实现了高精度的压装操作。为了达到这种精度&#xff0c;系统通常依赖于多个硬件和软件模块的协同工作&#xff0c;包括伺服电机、压力传感器、位移传感器以及LabVIEW的实时控制和数据处理功能。以下是LabVIEW伺服压机如何实…

Linux修改npm的镜像源为淘宝镜像

起因&#xff1a;使用官方镜像源下载软件包速度太慢 1.查看npm当前镜像源命令 npm get registry 执行结果 2.还原为官方镜像源命令 npm config set registry https://registry.npmjs.org/ 3.修改为淘宝镜像命令 npm config set registry https://registry.npmmirror.com …

【你也能从零基础学会网站开发】 SQL Server结构化查询语言数据操作应用--DML篇 delete语句数据删除操作的使用方法

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 delete介绍与语…

关于武汉芯景科技有限公司的限流开关芯片XJ6288开发指南(兼容SY6288)

一、芯片引脚介绍 1.芯片引脚 二、系统结构图 三、功能描述 1.EN引脚控制IN和OUT引脚的通断 2.OCB引脚指示状态 3.过流自动断开

NC 单据模板自定义项 设置参照,比如部门参照、自定义参照等

NC 单据模板自定义项 设置参照&#xff08;自定义参照&#xff09; 一、如图下图&#xff0c;NC 单据模板自定义项 设置自定义参照&#xff1a; 1、选择需要设置参照的自定义字段&#xff0c;选择高级属性页签&#xff0c;在类型设置中&#xff0c;数据类型选择参照信息&#…

使用JUC包的AtomicXxxFieldUpdater实现更新的原子性

写在前面 本文一起来看下使用JUC包的AtomicXxxxFieldUpdater实现更新的原子性。代码位置如下&#xff1a; 当前有针对int&#xff0c;long&#xff0c;ref三种类型的支持。如果你需要其他类型的支持的话&#xff0c;也可以照葫芦画瓢。 1&#xff1a;例子 1.1&#xff1a;普…

Maven的进阶

目录 一、pom.xml文件 二、坐标 2.1 坐标的概念 2.2 坐标的意义 2.3 坐标的含义 2.4 在IDEA中查看项目的坐标 三、依赖 3.1 依赖的意义 3.2 依赖的使用 3.3 第三方依赖的查找使用方法 3.4 依赖的范围 3.5 依赖传递和可选依赖 3.5.1 依赖传递 3.5.2 依赖范围对传…

【前端】如何制作自己的网站(7)

以下内容接上文。 结合图片的超链接 将img元素作为内容&#xff0c;放在a元素中。即可为图片添加一个超链接。 例如右边的代码&#xff0c;点击头像就会打开“aboutme.html“。 点击右边的图片试试&#xff5e; 两个非文本元素——图片与超链接。 从现在开始&#xff0…

蘑菇书(EasyRL)学习笔记(1)

1、强化学习概述 强化学习&#xff08;reinforcement learning&#xff0c;RL&#xff09;讨论的问题是智能体&#xff08;agent&#xff09;怎么在复杂、不确定的环 境&#xff08;environment&#xff09;里面去最大化它能获得的奖励。如下图所示&#xff0c;强化学习…

【Petri网导论学习笔记】Petri网导论入门学习(七) —— 1.5 并发与冲突

导航 1.5 并发与冲突1.5.1 并发定义 1.14定义 1.15 1.5.2 冲突定义 1.17 1.5.3 一般Petri网系统中的并发与冲突定义 1.18一般网系统中无冲撞概念阻塞&#xff08;有容量函数K的P/T系统&#xff0c;类似于冲撞&#xff09;一般Petri网中并发与冲突共存情况 1.5 并发与冲突 Petr…

计算机导论

概述 计算机简史 1935年代&#xff0c;英国数学家图灵(Alan Turing)提出“图灵机”&#xff0c;奠定了计算机的理论基础。 1952年&#xff0c;冯诺依曼确定了计算机由运算器、控制器、存储器、输入、输出等5部分组成&#xff08;Von Neumann 体系结构&#xff09;。 60年代…

【MySQL备份】Percona XtraBackup

这份文档针对的是最新发布的版本&#xff1a;Percona XtraBackup 2.4.29&#xff08;发布说明&#xff09;。 Percona XtraBackup是一款针对MySQL系列服务器的开源热备份工具&#xff0c;在备份过程中不会锁定您的数据库。它能够对MySQL 5.1、5.5、5.6和5.7服务器以及带有Xtra…

实战华为AC6508无线控制器+华为无线AP上线配置(AirEngine5762S-12+AirEngine5760-10)+无线WIFI配置

一、适用场景 1、适用于企业环境、校园环境、大户型家庭多层楼环境。 2、对于无线网络需要集中管理和监测的环境&#xff0c;无线wifi覆盖范围面积大&#xff0c;适用本实例。 3、当无线WIFI需要从一个区域到另一个区域无缝漫游时&#xff0c;确保应用不掉线&#xff0c;可使用…

Linux下的隐藏技术(文件隐藏、进程隐藏、端口隐藏、权限隐藏、命令隐藏)

目录 隐藏文件 隐藏权限 隐藏历史操作命令 端口复用 进程隐藏 隐藏文件 Linux 下创建一个隐藏文件:touch .test.txt touch 命令可以创建一个文件,文件名前面加一个 点 就代表是隐藏文件,如下图: 一般的Linux下的隐藏目录使用命令ls -l是查看不出来的,只能查看到文件及…

从0到1实现你自己的AI Chat应用

目标 基于大语言模型的 Chat 应用&#xff0c;是一种利用自然语言处理技术来进行对话交互的智能应用。 大语言模型通过大量数据的学习和训练&#xff0c;能够理解自然语言表达的语义&#xff0c;具备智能对话的能力。当用户向 Chat 应用提出问题时&#xff0c;Chat 应用就会利…

理解TypeScript模块-声明-配置

目录 模块化内置类型导入命名空间类型查找内置类型外部定义声明第三方库自定义声明 tsconfig.json文件在Vue项目中应用在React项目中应用 模块化 在TypeScript中最主要使用的模块化方案就是ES Module&#xff0c;先理解 TypeScript 认为什么是一个模块&#xff1a; JavaScript…