MySQL连接池配置及FullGC分析

本文主要讲述MySQL连接池配置不合适时,由于MySQL以虚引用的方式作为线程清理的后备手段,导致JVM年老代随时间缓慢增长,直至FullGC的问题。为了优化数据库连接池配置,使得JVM进行尽量少的FullGC导致服务故障,本文提供了多种解决方案

问题描述

发现容器服务的老年代在不断的增长,直到FullGC回收

年老代使用比例

MAT dump分析

使用Java自带的jmapjstack,Java 8 引入的jcmd,或Arthas heapdump 等工具,来进行Thread dump

使用MAT进行堆栈日志分析

dump-overview

Leak Suspect

leak-suspect

mysql-connector-java-5.1.49com.mysql.jdbc.AbandonedConnectionCleanupThread单独的MySQL清理,负责关闭被遗弃的MySQL连接,即没有被显式关闭的连接

AbandonedConnectionCleanupThread

ConcurrentHashMap类型的connectionFinalizerPhantomRefs常量,包含了一系列的虚引用。目的是作为保底操作:当connection对象回收时,顺便回收相关资源

如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。

四种引用类型可见Java 垃圾收集器与内存分配策略

trackConnection

当创建新的连接的时候就会调用trackConnection方法,把MysqlConnection添加到虚引用的ConcurrentHashMap中

由此可以分析出造成年老代不断增长的原因是MySQL连接短时间内不断创建回收的

weak refs processing处理逻辑

此段抄自https://www.jianshu.com/p/2db280229343

void ReferenceProcessor::process_discovered_references(BoolObjectClosure*           is_alive,OopClosure*                  keep_alive,VoidClosure*                 complete_gc,AbstractRefProcTaskExecutor* task_executor) {NOT_PRODUCT(verify_ok_to_handle_reflists());assert(!enqueuing_is_done(), "If here enqueuing should not be complete");// Stop treating discovered references specially.disable_discovery();bool trace_time = PrintGCDetails && PrintReferenceGC;// Soft references{TraceTime tt("SoftReference", trace_time, false, gclog_or_tty);process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,is_alive, keep_alive, complete_gc, task_executor);}update_soft_ref_master_clock();// Weak references{TraceTime tt("WeakReference", trace_time, false, gclog_or_tty);process_discovered_reflist(_discoveredWeakRefs, NULL, true,is_alive, keep_alive, complete_gc, task_executor);}// Final references{TraceTime tt("FinalReference", trace_time, false, gclog_or_tty);process_discovered_reflist(_discoveredFinalRefs, NULL, false,is_alive, keep_alive, complete_gc, task_executor);}// Phantom references{TraceTime tt("PhantomReference", trace_time, false, gclog_or_tty);process_discovered_reflist(_discoveredPhantomRefs, NULL, false,is_alive, keep_alive, complete_gc, task_executor);}// Weak global JNI references. It would make more sense (semantically) to// traverse these simultaneously with the regular weak references above, but// that is not how the JDK1.2 specification is. See #4126360. Native code can// thus use JNI weak references to circumvent the phantom references and// resurrect a "post-mortem" object.{TraceTime tt("JNI Weak Reference", trace_time, false, gclog_or_tty);if (task_executor != NULL) {task_executor->set_single_threaded_mode();}process_phaseJNI(is_alive, keep_alive, complete_gc);}
}

看JVM源码,weak refs processing主要包括SoftReferenceWeakReferenceFinalReferencePhantomReference以及JNI Weak Reference这五种Reference对象的处理,处理的主要内容是对之前标记的Reference对象重新处理,重新判断是否需要标记(不标记就是要回收的),如果不标记就需要放到refqueue里,等待java ReferenceHandler线程处理

优化方法

调整数据库连接池配置

如果应用程序使用Hikari或任何其他连接池管理器且并在正确的配置下,这些引用将在MinorGC时被回收,不会造成问题

  1. 适当延长idleTimeout(默认值为10分钟,问题进程设置为30s)
  2. 适当延长maxLifetime(数据库默认的连接空闲时间是8小时,问题进程设置为25min)
  3. 调整空闲线程数minimumIdle(默认会和最大连接数一样为100)

Hikari官方强烈推荐设置maxLifetime,并只比数据库引擎connectionTimeout短一些

spring:datasource:test:# 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),默认:10分钟idle-timeout: 1800000# 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 1800000ms,建议设置比数据库超时时长少60秒,参考MySQL wait_timeout参数(show variables like '%timeout%';) -->  ) -->max-lifetime: 14400000# 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)maximum-pool-size: 100# 最小连接数minimum-idle: 10

设置JVM参数

在Java参数中设置了-Dcom.mysql.cj.disableAbandonedConnectionCleanup=true,停止生成这些引用

删除connectionFinalizerPhantomRefs集合

数据库连接的释放有连接池保证,这个保底机制其实是多余的,可以起个定时任务线程,去清理这个connectionFinalizerPhantomRefs集合。

下面是一个旧版本的清理示例代码。
在这里插入图片描述


参考资料:

  1. MySQL AbandonedConnectionCleanupThread Memory Leak
  2. 记一次数据库连接池导致的OOM的问题
  3. 数据库连接池配置不当导致的full gc问题记录
  4. HikariCP

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

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

相关文章

解决springboot项目中的groupId、package或路径的混淆问题

对于像我一样喜欢跳跃着学习的聪明人来说,肯定要学springboot,什么sevlet、maven、java基础,都太老土了,用不到就不学。所以古代的聪明人有句话叫“书到用时方恨少”,测试开源项目时,编译总是报错&#xff…

配置化开发的核心设计 - Schema

前端配置化SchemaServerless FaaS BaaS useImperativeHandle() react-helmet 参考链接 schema进入

Multicast IP Interface

该模块通过多播IPv4和IPv6在UDP上实现CAN和CAN FD消息的传输。此虚拟接口允许在多个进程甚至主机之间进行通信。这与虚拟接口不同,虚拟接口只能在单个进程中传递消息,但不需要网络堆栈。 它在UDP上运行以具有尽可能低的延迟(与使用TCP相反),并且因为正常的IP多播本质上是…

后端数据配置相对路径,前端添加网站根 URL (根路径)- js获取网站项目根路径- 获取根路径后的第一个斜杠前 / 的项目- - 判断url包含某字符串

1、js获取网站项目根路径 js获取项目根路径,如下: 原 http://localhost:8080/testproject/test.html 根路径:http://localhost:8080 function getRootPath(){//获取当前网址,// 如: http://localhost:8080/testpro…

为什么中国软件需要国产化?

国产化是指技术引进项目投产后所生产的产品中,国内生产件的数量占整件产品生产件数量。换句话说,软件国产化的占比,直接影响到技术是否会在某一个时点上被”卡脖子“。 随着国家经济的发展和技术水平的提高,国家整体实力大大增强…

跨足多领域:人脸美颜SDK在医疗、娱乐和安全中的应用案例

随着科技的不断发展,人脸美颜技术不再局限于满足用户的审美需求,而是在医疗、娱乐和安全领域展现出了广泛的应用前景。本文将深入探讨人脸美颜SDK 在这三个领域中的创新应用案例,展示其在不同场景中的独特价值和潜力。 一、医疗领域 1、皮…

2023腾讯全球数字生态大会预约报名入口

报名入口 2023腾讯全球数字生态大会即将开启,点击打开预约报名入口。 主题与介绍 主题 2023腾讯全球数字生态大会将聚焦产业未来发展新趋势,针对云计算、大数据、人工智能、安全、SaaS等核心数字化工具做关键进展发布,并联合生态伙伴推出最…

c++20 多线程并发 latch barrier semaphore

背景: c20 关于多线程并发新增了 latch, barrier, semaphore ,接下来就按照一个一个进行介绍 latch latch 是一次性使用的线程协调点, 一旦给定数量的线程达到latch点时, 所有线程都会解除阻塞, 并继续执行. 基本上它是一个计数器, 在每个线程到达latch点时倒数, 一旦计数器达…

用Rust打印hello world!

步骤1 桌面新建1个名为 rustDemo 的文件夹(文件夹名字随便取) 步骤2 打开新建的文件夹,在地址输入栏输入 cmd 按回车键进入命令行窗口 步骤3 打开编译器,按 Ctrl S,保存文件到 rustDemo 文件夹中,保存的…

【git】从一个git仓库迁移到另外一个git仓库

在远端服务器创建一个新的仓库 用界面创建&#xff0c;当然也可以用命令创建 拉去源仓库 git clone --bare git192.168.10.10:java/common.gitgit clone --bare <旧仓库地址>拉去成功以后会出现 进入到文件夹内部 出现下面信息&#xff1a; 推送到新的远端仓库 git …

【IOTE】物联网射频模组和芯片级方案提供商——深圳信驰达科技将精彩亮相IOTE物联网展

►►►强势来袭 Strong Attack 主物联场&#xff0c;相约深圳&#xff1b;2023&#xff0c;共论商机&#xff01;IOTE2023第二十届国际物联网展深圳站将于2023年9月20-22日在深圳国际会展中心(宝安新馆)开展&#xff01;汇聚全球超800家参展企业&#xff0c;呈现更多数字化纷呈…

.NET Framework 微软官方下载地址

微软官方下载地址&#xff1a; 下载 .NET Framework | 免费官方下载 (microsoft.com) 版本发布日期终止支持.NET Framework 4.8.12022年8月9日.NET Framework 4.82019年4月18日.NET Framework 4.7.22018年4月30日.NET Framework 4.7.12017年10月17日.NET Framework 4.72017年…

ARM驱动开发

驱动 以来内核编译&#xff0c;依赖内核执行 驱动可以同时执行多份代码 没main 驱动是依赖内核的框架和操作硬件的过程 一&#xff0c;Linux系统组成 app: [0-3G] ---------------------------------系统调用&#xff08;软中断…

C# PaddleDetection yolo 印章检测

效果 项目 代码 using OpenCvSharp; using OpenCvSharp.Extensions; using Sdcb.PaddleDetection; using Sdcb.PaddleInference; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq…

chrono 模块学习

三大类 顶级clock: system_clock日期时间; steady_clock启动时间, 硬件震动clock; 内置四大类型: duration使用精度类型(min,sec,ms,ns等 加 数量); rep记录对应精度数量的类型(默认longlong, 也可以自定义其他类型); period: 精度, 即当前精度等于1s*ratio, (ms 1 / 1000s)…

【数据结构】 二叉树面试题讲解->贰

文章目录 &#x1f30f;引言&#x1f384;[二叉树遍历](https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId60&&tqId29483&rp1&ru/activity/oj&qru/ta/tsing-kaoyan/question-ranking)&#x1f431;‍&#x1f464;题目描述&#…

Java 创建一个线程的方式

Java中创建线程主要有三种方式&#xff0c;分别为继承Thread类、实现Runnable接口、实现Callable接口。 继承Thread类&#xff0c;重写run()方法&#xff0c;调用start()方法启动线程 public class ThreadTest {/*** 继承Thread类*/public static class MyThread extends Thr…

1.(python数模)单函数读取常用文件

Python单函数读取常用文件 代码如下&#xff1a; import pandas as pd# 读取数据文件 def readDataFile(readPath): # readPath: 数据文件的地址和文件名try:if (readPath[-4:] ".csv"):dfFile pd.read_csv(readPath, header0, sep",") # 间隔符为逗…

音频——I2S TDM 模式(六)

I2S 基本概念飞利浦(I2S)标准模式左(MSB)对齐标准模式右(LSB)对齐标准模式DSP 模式TDM 模式 文章目录 TDM formatTDM format ATDM format BTDM format C总结 TDM format TDM 分为两种常用操作模式&#xff1a;TDM A mode 和 TDM B mode, 统称为TDM mode 基于 TDM mode&#x…

leetcode做题笔记114. 二叉树展开为链表

给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 思路一&#x…