当前位置: 首页 > article >正文

别急着加内存!从一次OOM到MySQL锁表,我如何用jstack和jvisualvm揪出真凶

从OOM到MySQL锁表一套完整的问题排查与性能优化实战指南当线上系统突然崩溃屏幕上跳出Memory cgroup out of memory的红色告警时大多数开发者的第一反应往往是赶紧加内存。但真正的问题往往隐藏在这表面现象之下。本文将带你经历一次真实的生产环境故障排查全过程从内存溢出告警开始逐步揭开MySQL锁表、线程阻塞、资源竞争等一系列连环问题的真相。1. 告警初现系统为何被Kill那天下午3点监控系统突然发出刺耳的警报声。登录服务器后发现Java进程神秘消失只留下一条线索dmesg -T | grep -i kill输出结果显示[Mon Jul 12 15:23:45 2021] Memory cgroup out of memory: Kill process 7187 (java) score 1007 or sacrifice childLinux的OOM Killer机制在内存不足时会自动终止得分最高的进程。但这个得分是怎么计算的主要有三个因素内存占用比例进程使用的内存占系统总内存的百分比CPU使用时间进程最近消耗的CPU时间进程优先级nice值较低的进程更容易被选中提示在生产环境可以通过调整/proc/ /oom_score_adj来保护关键进程不被OOM Killer终止2. 初步分析GC日志与负载均衡查看GC日志发现一分钟内发生了3次Full GC这是一个明显的危险信号。正常的GC行为应该是GC类型频率阈值可能问题Young GC5次/分钟新生代设置过小Full GC1次/小时内存泄漏或老年代不足同时检查Nginx日志发现所有流量都被导向了这台故障机器。这解释了为何其他机器闲置而这一台崩溃。但简单的负载均衡调整真的解决问题了吗3. 深入线程分析jstack揭示的阻塞链两周后问题再次出现这次虽然没有进程被Kill但用户开始抱怨接口超时。使用jstack抓取线程快照jstack -l pid thread_dump.log分析日志发现两个关键现象Redisson客户端大量WAITINGredisson-netty-1-5 #31 prio5 os_prio0 tid0x00007f8b9406e800 nid0x1e03 waiting on condition [0x00007f8b7a7f7000]MySQL TIMED_WAITINGhttp-nio-8080-exec-5 #20 daemon prio5 os_prio0 tid0x00007f8b8c00a800 nid0x1d0f waiting on condition [0x00007f8b7b3f8000]这两者看似无关实则暗藏联系。通过线程状态转换图可以更清晰理解用户请求 → 获取Redis连接 → 执行MySQL更新 → 等待锁超时 → Redis连接未释放 → 连接池耗尽4. MySQL锁表罪魁祸首浮出水面错误日志中频繁出现Lock wait timeout exceeded; try restarting transaction检查相关表结构CREATE TABLE t_sys_session_rec ( sessionId VARCHAR(32) PRIMARY KEY, createIp VARCHAR(16), updateTime DATETIME, -- 其他字段... );问题出在一个定时任务上它每60秒执行一次全表扫描// 问题代码示例 Scheduled(fixedRate 60000) public void cleanExpiredSessions() { ListSessionRecord records sessionRecordMapper.selectAllWillExpireSession(); records.forEach(record - { record.setStatus(INVALID); sessionRecordMapper.updateByPrimaryKey(record); }); }这个任务有两个致命缺陷全表扫描where条件中的createIp和updateTime字段无索引长事务逐条更新导致锁持有时间过长5. 内存分析jvisualvm揭示的对象洪流生成堆转储文件jmap -dump:live,formatb,fileheap.hprof pid使用jvisualvm分析发现内存中充斥着HashMap$Node (32% of total objects)char[] (25% of total objects)Hashtable$Entry (18% of total objects)代码审查发现在核心接口中频繁创建临时Map对象public MapString, String getParams(HttpServletRequest request) { MapString, String paramMap new HashMap(); // 问题点1 EnumerationString names request.getParameterNames(); while (names.hasMoreElements()) { String name names.nextElement(); paramMap.put(name.trim(), request.getParameter(name).trim()); // 问题点2 } return paramMap; }每次请求创建多个Map和String对象在QPS 50的情况下每天产生超过150万个临时对象。6. 系统性解决方案6.1 MySQL优化方案方案优点缺点适用场景添加索引快速见效对updateTime无效静态字段查询改用Redis彻底解决锁问题改造量大高并发场景分区表减少单表大小维护复杂大数据量表最终选择将session数据迁移到Redis利用其原子操作和过期特性// 改进后的校验逻辑 public boolean validateTicket(String ticket) { String key session: ticket; return redisTemplate.execute(new RedisCallbackBoolean() { Override public Boolean doInRedis(RedisConnection connection) { byte[] value connection.get(key.getBytes()); if (value ! null) { connection.expire(key.getBytes(), SESSION_TIMEOUT); return true; } return false; } }); }6.2 内存优化关键点对象复用对于频繁创建的Map使用ThreadLocal缓存减少临时对象直接操作String而非创建新对象合理使用连接池spring.redis.pool.max-active100 spring.redis.pool.max-wait10007. 监控与预防体系建立完善的监控应该包括实时指标# GC监控 jstat -gcutil pid 1000 # 线程状态监控 jstack pid | grep -c BLOCKED预警规则Full GC频率 1次/小时线程阻塞率 10%MySQL锁等待 500ms压测验证# 模拟并发请求 ab -n 10000 -c 100 http://localhost:8080/api/ticket这次故障教会我们线上问题从来不是孤立的。从内存溢出到MySQL锁表再到Redis连接池耗尽各个环节环环相扣。真正的解决方案不在于增加硬件资源而在于发现并修复这些隐藏的连锁反应。

相关文章:

别急着加内存!从一次OOM到MySQL锁表,我如何用jstack和jvisualvm揪出真凶

从OOM到MySQL锁表:一套完整的问题排查与性能优化实战指南 当线上系统突然崩溃,屏幕上跳出"Memory cgroup out of memory"的红色告警时,大多数开发者的第一反应往往是"赶紧加内存"。但真正的问题往往隐藏在这表面现象之下…...

通过 curl 命令直接测试 Taotoken 聊天接口的快速验证方法

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过 curl 命令直接测试 Taotoken 聊天接口的快速验证方法 在接入大模型服务时,有时我们希望在无特定编程语言 SDK 的环…...

从《只狼》到你的项目:聊聊UE4布娃娃系统如何做出更‘有戏’的死亡动画

从《只狼》到你的项目:用UE4布娃娃系统打造叙事级死亡动画 在《只狼》中,当敌人从悬崖坠落时扭曲的肢体,或是Boss战败后跪地缓缓倒下的瞬间,这些死亡动画远不止是技术实现——它们成为玩家情感体验的延伸。作为UE4开发者&#xff…...

MAA助手终极指南:解放双手的明日方舟全自动游戏体验

MAA助手终极指南:解放双手的明日方舟全自动游戏体验 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: https://gitco…...

别再手动点鼠标了!用MATLAB脚本批量跑COMSOL仿真,效率提升10倍

别再手动点鼠标了!用MATLAB脚本批量跑COMSOL仿真,效率提升10倍 每次打开COMSOL Desktop界面,重复点击那些熟悉的菜单和按钮时,你有没有想过——这些机械操作能不能交给程序自动完成?特别是在需要跑几十组参数组合的优化…...

Qobuz-DL终极指南:解锁无损音乐下载的完整高效方案

Qobuz-DL终极指南:解锁无损音乐下载的完整高效方案 【免费下载链接】qobuz-dl A complete Lossless and Hi-Res music downloader for Qobuz 项目地址: https://gitcode.com/gh_mirrors/qo/qobuz-dl 在数字音乐追求极致音质的今天,无损音频获取工…...

如何彻底解决IDM试用期限制:三步实现永久免费使用的完整指南

如何彻底解决IDM试用期限制:三步实现永久免费使用的完整指南 【免费下载链接】idm-trial-reset Use IDM forever without cracking 项目地址: https://gitcode.com/gh_mirrors/id/idm-trial-reset 还在为Internet Download Manager(IDM&#xff0…...

大模型行业爆发式增长,程序员转型的最佳时机,现在上车还不晚

文章目录前言一、2026年大模型行业爆发式增长,风口已经来了1.1 市场规模爆炸式增长,企业需求井喷1.2 人才缺口巨大,薪资水涨船高1.3 技术门槛大幅降低,普通人也能上车二、程序员转型大模型,这4个方向性价比最高2.1 AI工…...

NPYViewer:让NumPy数据可视化变得像看图说话一样简单

NPYViewer:让NumPy数据可视化变得像看图说话一样简单 【免费下载链接】NPYViewer Load and view .npy files containing 2D and 1D NumPy arrays. 项目地址: https://gitcode.com/gh_mirrors/np/NPYViewer 还在为查看二进制NumPy数据而烦恼吗?NPY…...

如何快速配置黑苹果:OpenCore Configurator的完整入门指南

如何快速配置黑苹果:OpenCore Configurator的完整入门指南 【免费下载链接】OpenCore-Configurator A configurator for the OpenCore Bootloader 项目地址: https://gitcode.com/gh_mirrors/op/OpenCore-Configurator OpenCore Configurator是一款专为黑苹果…...

告别复杂配置!5分钟在Vue/React项目中集成讯飞语音听写WebSocket API

5分钟实现Vue/React与讯飞语音听写的优雅集成方案 在智能语音交互逐渐成为标配的今天,前端开发者经常面临将语音识别能力快速集成到现代Web应用中的需求。讯飞语音听写WebSocket API凭借其流式传输、低延迟的特性,成为众多项目的首选方案。但官方示例往往…...

从ROS到飞控:ENU与NED坐标系转换的实战解析与避坑指南

1. 为什么ENU和NED坐标系让开发者头疼? 第一次接触无人机开发时,我被ROS和飞控之间的坐标系问题坑得不轻。明明在ROS里跑得好好的导航算法,一接入PX4飞控就出现飞机往反方向飞、高度控制错乱的情况。后来才发现,这全是ENU和NED坐标…...

Python开发者必备:高效获取whl包的三种实战路径

1. 为什么我们需要whl包? 作为Python开发者,你一定遇到过这样的场景:兴冲冲地pip install某个包,结果等待你的是一连串红色报错。最常见的就是"Microsoft Visual C 14.0 is required"这类编译错误。这时候,w…...

NoFences:开源桌面分区神器,让你的数字空间焕然一新

NoFences:开源桌面分区神器,让你的数字空间焕然一新 【免费下载链接】NoFences 🚧 Open Source Stardock Fences alternative 项目地址: https://gitcode.com/gh_mirrors/no/NoFences 每天打开电脑,你是否也曾面对那一片混…...

Hermes Agent 深度解析:从架构、安装、核心能力到与 OpenClaw 的区别

一、前言 近两年,AI Agent 项目越来越多。从早期的 AutoGPT,到面向开发者的 Claude Code、OpenAI Codex CLI,再到各种本地个人助手类项目,大家都在探索一个问题: 如何让大模型不只是“回答问题”,而是真正能调用工具、执行任务、积累经验,并长期为用户工作? NousResea…...

STM32F103 Flash读写避坑大全:从解锁失败到数据丢失,我踩过的坑你别再踩

STM32F103 Flash读写避坑大全:从解锁失败到数据丢失,我踩过的坑你别再踩 第一次在STM32F103上操作内部Flash时,我以为按照手册步骤就能轻松完成。直到调试灯疯狂闪烁、数据神秘消失、芯片莫名锁死,才意识到这片存储区域远没有想象…...

超轻角度传感器内部结构

简 介: 本文拆解分析了一款超轻磁编码器PD-015-SDI-ENC-1024,其总重仅1.5克(含引线1.7克)。该编码器采用铝制金属外壳,内部由旋转轴磁铁和QFN16封装的KTH7102磁编码芯片组成,实现1024脉冲/圈输出。结构紧凑…...

Elasticvue深度实战:终极Elasticsearch图形化管理工具完全指南

Elasticvue深度实战:终极Elasticsearch图形化管理工具完全指南 【免费下载链接】elasticvue Elasticsearch gui - desktop app, browser extension, docker, self hosted 项目地址: https://gitcode.com/gh_mirrors/el/elasticvue Elasticsearch作为现代应用…...

从零构建Firefly-RK3399的Ubuntu系统:镜像定制、内核编译与固件打包全流程

1. 为什么需要从零构建Firefly-RK3399的Ubuntu系统? 第一次拿到Firefly-RK3399开发板时,我也像大多数人一样直接刷写官方镜像。但很快就遇到瓶颈——预装系统缺少我需要的开发工具,内核版本不支持某些硬件特性,甚至系统分区方案都…...

独立开发者如何借助Taotoken快速试验不同模型效果

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 独立开发者如何借助Taotoken快速试验不同模型效果 对于独立开发者或产品经理而言,在验证一个产品创意或构建原型时&…...

为Node.js应用集成Taotoken实现多模型对话与流式响应

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为Node.js应用集成Taotoken实现多模型对话与流式响应 在构建客服机器人或内容生成工具时,开发者常常面临一个核心需求&…...

告别手动拷贝DLL!用CMake+Qt 5.12管理Qgis 3.10依赖,实现跨平台环境一键部署

告别手动拷贝DLL!用CMakeQt 5.12管理Qgis 3.10依赖,实现跨平台环境一键部署 在跨平台GIS应用开发中,手动管理Qt和Qgis的依赖项堪称开发者的噩梦。想象一下:每次新建项目都要复制数百MB的DLL文件,不同环境下的路径差异导…...

终极Windows窗口置顶工具:AlwaysOnTop完整使用指南

终极Windows窗口置顶工具:AlwaysOnTop完整使用指南 【免费下载链接】AlwaysOnTop Make a Windows application always run on top 项目地址: https://gitcode.com/gh_mirrors/al/AlwaysOnTop 你是否经常在多个窗口间频繁切换,重要信息总被其他程序…...

微信数据安全警示:为什么PyWxDump项目被永久移除及其合规性启示

微信数据安全警示:为什么PyWxDump项目被永久移除及其合规性启示 【免费下载链接】PyWxDump 删库 项目地址: https://gitcode.com/GitHub_Trending/py/PyWxDump 在当今数字时代,数据安全和个人隐私保护已成为技术开发领域的核心议题。今天我们要探…...

从根目录到数据区:FAT16与FAT32目录结构差异全解析

1. FAT文件系统基础认知 第一次接触FAT文件系统时,很多人都会被各种专业术语绕晕。其实理解它并不难,我们可以把整个存储设备想象成一本厚厚的记事本。这本记事本最前面有几页固定的"使用说明"(系统保留区),…...

从STP到RSTP:一次协议‘进化’带来的网络稳定性实战(避坑BPDU攻击与根桥抢占)

从STP到RSTP:构建高弹性企业网络的实战指南 在当今高度依赖网络连接的业务环境中,即使是几秒钟的网络中断也可能导致严重的业务损失。想象一下在线教育平台正在直播重要课程,或者金融网点处理实时交易时突然遭遇网络震荡——这种场景下&#…...

从零到一:支付宝小程序获取用户手机号的完整配置与实战解析

1. 为什么获取手机号要先配置开发设置? 很多刚接触支付宝小程序开发的同学可能会觉得奇怪:为什么获取个手机号要搞这么多前置配置?直接调个API不就行了吗?这里其实涉及到支付宝生态的安全设计理念。和微信小程序不同,…...

什么是AI-Native Development?20年架构师亲历3代AI工程演进后给出的5条铁律

更多请点击: https://intelliparadigm.com 第一章:什么是AI-Native Development?2026奇点智能技术大会给你答案 AI-Native Development 并非简单地将大模型 API 接入传统应用,而是以 AI 为一等公民重构软件生命周期——从需求建…...

保姆级教程:手把手教你用Qemu在Win10上虚拟树莓派(从下载镜像到SSH连接)

零基础实战:Windows 10环境下用Qemu搭建树莓派虚拟开发环境 在技术爱好者和开发者的世界里,树莓派以其小巧的体积和强大的功能成为了学习和实践的热门选择。然而,并非所有人都有条件随时准备一块实体树莓派板子。这时,虚拟化技术就…...

告别访问失败!手把手教你用中标麒麟OS挂载Win10的SMB共享(附终端挂载命令)

中标麒麟OS与Win10 SMB共享深度配置指南:从原理到实战避坑 在跨平台协作成为常态的今天,Linux与Windows系统间的文件共享已成为运维人员的必备技能。中标麒麟作为国产操作系统的代表,其与Windows的SMB协议互通却常因配置细节不到位而引发&quo…...