MySQL 连接池配置及 FullGC 分析

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 本文主要讲述MySQL连接池配置不合适时,由于MySQL以虚引用的方式作为线程清理的后备手段,导致JVM年老代随时间缓慢增长,直至FullGC的问题。为了优化数据库连接池配置,使得JVM进行尽量少的FullGC导致服务故障,本文提供了多种解决方案单独的MySQL清理,负责关闭被遗弃的MySQL连接,即没有被显式关闭的连接。发现容器服务的老年代在不断的增长,直到。

本文主要讲述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
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8天前
|
存储 SQL 关系型数据库
MySQL体系结构与配置
MySQL体系结构与配置
20 0
|
1天前
|
弹性计算 关系型数据库 MySQL
centos7 mysql安装及配置
本文详细介绍了在阿里云服务器ECS上通过yum源安装MySQL 8.0.12的过程,包括更新yum源、下载并安装MySQL源、解决安装过程中可能遇到的问题等步骤。此外,还介绍了如何启动MySQL服务、设置开机自启、配置登录密码、添加远程登录用户以及处理远程连接异常等问题。适合初学者参考,帮助快速搭建MySQL环境。
15 8
centos7 mysql安装及配置
|
5天前
|
存储 JSON 关系型数据库
MySQL与JSON的邂逅:开启大数据分析新纪元
MySQL与JSON的邂逅:开启大数据分析新纪元
|
9天前
|
关系型数据库 MySQL Linux
在Linux中,如何配置数据库服务器(如MySQL或PostgreSQL)?
在Linux中,如何配置数据库服务器(如MySQL或PostgreSQL)?
|
10天前
|
缓存 关系型数据库 MySQL
在Linux中,如何优化MySQL性能,包括索引优化和查询分析?
在Linux中,如何优化MySQL性能,包括索引优化和查询分析?
|
15天前
|
SQL 负载均衡 关系型数据库
*配置MySQL集群
【8月更文挑战第16天】*配置MySQL集群
22 2
|
20天前
|
SQL 关系型数据库 MySQL
Nacos 1.2.1 集群搭建(二)MySQL、cluster 配置
Nacos 1.2.1 集群搭建(二)MySQL、cluster 配置
35 1
|
22天前
|
存储 关系型数据库 MySQL
"Linux环境下MySQL数据库名及表名大小写敏感性设置详解:从配置到影响,确保数据库操作的准确与高效"
【8月更文挑战第9天】在Linux环境中,MySQL数据库名及表名的大小写敏感性是一项重要配置。默认情况下,MySQL在Linux上区分大小写,但这可通过配置文件 `/etc/my.cnf` 中的 `lower_case_table_names` 参数调整。该参数设为0时,名称存储时保持原样,查询时不区分大小写;设为1则全部转换为小写。通过编辑配置文件并重启MySQL服务,可根据需求灵活控制名称的大小写敏感性,确保数据一致性和应用兼容性。
38 3
|
17天前
|
SQL 关系型数据库 MySQL
MySql⭐一、配置MySql数据库,并创建一个表单
MySql⭐一、配置MySql数据库,并创建一个表单
|
22天前
|
安全 关系型数据库 MySQL
"深度解析:MySQL密码修改与远程登录配置全攻略,保障数据库安全与灵活访问"
【8月更文挑战第9天】MySQL是广受青睐的开源关系型数据库系统,其安全性和易用性对DBA和开发者至关重要。本文通过实例解析MySQL中用户密码更新及远程登录配置,确保数据库安全访问与高效管理。首先介绍如何分步修改密码,包括登录MySQL、选择数据库、使用`ALTER USER`命令更新密码,并刷新权限。接着,指导如何配置远程访问,涉及调整MySQL监听地址、授权用户远程登录、检查网络设置及测试远程连接。遵循这些步骤,可强化数据库安全性并实现灵活管理。
89 0

热门文章

最新文章

下一篇
云函数