seata事务回滚引起的skywalking数据库存储空间剧增的问题排查
-
基本信息
产品名称:ATS3.0
问题分类:编码问题
环境类型:环境无关
-
问题现象
11月1日上午华润DBA收到数据库磁盘空间告警,检查后发现skywalking连接的mysql数据库占用空间从之前一直是比较稳定的,但是10月31日开始激增,一天左右原来剩250G+的磁盘空间只剩下了50G左右。进一步排查发现数据主要集中在skywalking的segment表中。 -
问题原因
seata回滚一个数据库操作较多的事务,由于seata客户端的问题,没有正常关闭PrepareStatement最终触发了ORA-01000-超出打开游标的最大数问题(生产库游标单个session最大300),导致回滚失败。然后seata每秒都会再次触发重试,又因为是一个大事务,导致每秒都有大量的事务回滚的sql操作。因为我们安装了skywalking的oracle插件,程序调用oracle的请求也会被记录,最终导致大量的链路信息被记录到segment表中造成了skywalking的存储数据库空间暴增。 -
排查过程
4.1 紧急处置
1.先让客户删除了mysql库今天之前的binlog,释放出部分空间,否正剩余50G很可能几个小时候就会耗尽,释放后剩余空间回到了250G左右,有了比较充足的排查时间。
2.预案:如果空间持续上升,且还没找到原因的话可以尝试临时删除部分skywalking的数据,因为只是用于监控,不影响业务。或者暂时停止下skywalking。
4.2 定位skywalking的空间是被什么请求占用
1.segment表里的endpoint_id表示请求服务及地址的信息,根据这个字段分类排序可以判断一段时间主要是哪个请求占用了空间。
sql: select count(*) as total , endpoint_id from segment s where start_time > 1667286000000 group by endpoint_id order by total desc;
start_time要根据查询的时间调整这个毫秒数
2. 发现主要是有两个请求触发的频率比较高
3. endponit_id下划线左边是服务名(最后的.1也要去掉才是服务名),右边是请求URL,查看skywalking源码,确定这串字符的编码规则,写了一个转换的逻辑new String(Base64.getDecoder().decode(待转换内容), StandardCharsets.UTF_8);
4. 转换后发现这两个请求分别是ntms-financing的Oracle/JDBI/PreparedStatement/executeQuery和Oracle/JDBI/PreparedStatement/executeUpdate
5. 发现都是数据库操作后去ELK查了下financing服务的日志发现有大量的数据库操作日志,都是seata回滚线程操作的,此时基本可以判断是seata不断尝试回滚事务产生的日志,接下来就需要具体是哪些事务回滚失败不停重试,以及回滚失败的原因。
4.3 确认为什么会触发大量的问题请求
触发大量请求的原因:
seata事务失败,如果能回滚成功,则会直接释放掉,如果回滚失败,则会一直尝试重试回滚,每1s重试一次,我们没有配置停止时间,所以会一直重试。回滚的时候会去做undo_log表的查询、根据undo_log表的数据做业务表的查询等操作,如果一个事务操作的数据量很大,那么每次回滚都会打印很多sql语句,也就会对skywalking记录的数据有影响了。
假设一个全局事务是插入1000条数据到表中,那么回滚的时候,会执行一次查询undo_log,对于每行数据,执行一次select for update,执行一次delete,共2001条sql。一次回滚正常要执行这么多sql,如果回滚失败了,过1s后还要再执行,可以看到数据量是很大的。一天之内回滚日志就有五千多万条:
查找回滚失败原因:
通过查看日志找到每次执行一堆回滚sql后都会有一个报错:
报错日志为”ORA-01000: maximum open cursors exceeded“,也就是说seata很可能因为这个问题导致数据无法回滚。
对这个异常的解释:oracle ORA-01000: maximum open cursors exceeded问题的解决方法-CSDN博客
简单地说就是conn.prepareStatement()会打开一个游标,如果循环里调用这段代码,并且没调用close方法的话,就有可能造成上面的问题。
一些命令:oracle怎么查询游标-Oracle-PHP中文网
# 查看当前打开的游标总数
select count(*) from v$open_cursor;
# 每个连接能打开的最大游标数
select value from v$parameter where name = 'open_cursors';
# 更改连接能开启的最大游标数(改成1000)alter system set open_cursors=1000 scope=both;
定位问题:
通过条件"100.100.3.253:8091:4602887063828890271" and "error" 可以看到有一个异常日志,通过调用栈可以大概找到报错的地方
再结合上面的”branchRollback failed. branchType:“可以大概定位到报错位置。
在io.seata.rm.datasource.undo.AbstractUndoLogManager#undo这段代码的位置,是对当前事务分支做回滚的操作。先获取undo_log的中该分支的数据,做反序列化后可以得到执行的每条sql的undo_log。(一个本地事务每次执行sql都会生成一个SQLUndoLog,在连接最后提交时会把该本地事务操作的所有SQLUndoLog封装为BranchUndoLog,序列化到undo_log表中)
再遍历该BranchUndoLog的SQLUndoLog的list,对每一条SQLUndoLog执行io.seata.rm.datasource.undo.AbstractUndoExecutor#executeOn回滚操作。问题就出在这个方法
public void executeOn(Connection conn) throws SQLException {//dataValidationAndGoOn执行一下select xxx for update,对该数据加锁。if (IS_UNDO_DATA_VALIDATION_ENABLE && !dataValidationAndGoOn(conn)) {return;}PreparedStatement undoPST = null;try {String undoSQL = buildUndoSQL();//在这里开启一个游标undoPST = conn.prepareStatement(undoSQL);TableRecords undoRows = getUndoRows();for (Row undoRow : undoRows.getRows()) {ArrayList<Field> undoValues = new ArrayList<>();List<Field> pkValueList = getOrderedPkList(undoRows, undoRow, getDbType(conn));for (Field field : undoRow.getFields()) {if (field.getKeyType() != KeyType.PRIMARY_KEY) {undoValues.add(field);}}undoPrepare(undoPST, undoValues, pkValueList);//做undolog的回滚undoPST.executeUpdate();}} catch (Exception ex) {if (ex instanceof SQLException) {throw (SQLException) ex;} else {throw new SQLException(ex);}}//处理完并没有关闭游标
}
看到该方法只开启了游标,并没有关闭。外面还有一个undo_log的循环,当BranchUndoLog的list过多时,会超过游标数量。
代码模拟:
public void add() {for (int i1 = 0; i1 < 10000; i1++) {TestPO testPO = new TestPO();testPO.setUrid("" + i1);testPO.setName("name" + i1);testPO.setAge(i1);testMapper.insert(testPO);}}@GlobalTransactionalpublic void update() {((TestService)AopContext.currentProxy()).doupdate();int i = 1/0;}@Transactionalpublic void doupdate(){for (int i1 = 0; i1 < 10000; i1++) {TestPO testPO = new TestPO();testPO.setUrid("" + i1);testPO.setName("name2" + i1);testPO.setAge(i1);testMapper.updateById(testPO);}}create table TSYS_TEST
(URID VARCHAR2(64) not nullconstraint TSYS_TEST_PKprimary key,NAME VARCHAR2(64),AGE NUMBER(38)
)
/
执行完add后,再执行update,会报上面超过游标数量的问题。
该问题seata新版本已经更改。就是在上面的方法后面把statement关闭了。
现场的解决方案时先把游标数调成了3000,该事务可以正常回滚了,把资源都释放掉了。等下次xx发版的时候,再把这段逻辑加上。
现场的最大游标是300,也就是说每次失败大概会打印300(回滚条数)+300(select for update)+1(select from undo_log)条日志,一天要打印601*60*60*24=51,926,400 ,基本上就是上面所有命中次数了。所以该结论没什么问题。
-
解决方案
1.临时调大了生产oracle库的游标数,从300调整到了3000,因为游标数不够而一直重试的回滚操作回滚成功了,暂时解决了问题
2.seata client没有正常关闭PrepareStatement的问题已修复,等下下次华润升级的时候更新过去
3. seata事务没有正常结束的情况需要监控起来,不然只能等到引起问题才发现,如果此时存在大量的未完成事务可能就非常难以解决了。
相关文章:

seata事务回滚引起的skywalking数据库存储空间剧增的问题排查
基本信息 产品名称:ATS3.0 问题分类:编码问题 环境类型:环境无关 问题现象 11月1日上午华润DBA收到数据库磁盘空间告警,检查后发现skywalking连接的mysql数据库占用空间从之前一直是比较稳定的,但是10月31日…...

数据库SQL
数据库&SQL 数据库基本概念数据库DataBase定义 数据库管理系统(DBMS)定义在JAVA项目中与数据库的结合数据库管理系统中常见的概念库与表的关系 SQL数据类型数字类型浮点类型字符类型TEXT类型日期类型 SQL语言的分类DDL:数据定义语言修改表结构的注意事项 DML:数据操作语言D…...

C语言实现给一个不多于5位的正整数,要求:一、求它是几位数,二、逆序打印出各位数字。
完整代码: // 给一个不多于5位的正整数,要求:一、求它是几位数,二、逆序打印出各位数字。 #include<stdio.h>int main(){int num;int len0;printf("请输入一个不多于5位的正整数:");scanf("%d",&n…...
101 对称二叉树
原题链接:101 对称二叉树 全代码: /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : va…...

安全测试,接口返回内容遍历~
最近公司被人大量爬取数据,查了一下发现,用户主页接口,没有加用户登录校验,返回了用户的敏感信息有手机号和邮箱,其实这个接口是用不到这些信息的。再加上用户id是自增长的,所以很容易被别人爬取。 既然这…...
【GIS】地理坐标系与投影坐标系的区别
在地理信息系统中,坐标系的选择和使用是至关重要的。我们通常使用的坐标系有两种:地理坐标系和投影坐标系。本文将详细介绍这两种坐标系的概念、区别、转换方式以及常见投影。 一、定义 地理坐标系(Geographic Coordinate System)…...

太细了:美团一面连环夺命20问,搞定就60W起
说在前面 在40岁老架构师尼恩的(50)读者社群中,经常有小伙伴,需要面试美团、京东、阿里、 百度、头条等大厂。 下面是一个小伙伴成功拿到通过了美团一面面试,现在把面试真题和参考答案收入咱们的宝典。 通过美团一面…...

休眠和睡眠有哪些区别?如何让电脑一键休眠?
电脑中有休眠和睡眠,那么它们有什么区别呢?下面我们就通过本文来了解一下。 休眠和睡眠的区别 电脑在睡眠状态时,会切断内存之外的设备电源,电脑会进入睡眠状态,当再次唤醒电脑后,不会影响睡眠前保存好的工…...

Kibana使用Timelion根据时间序列展示数据
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...

基础:JavaScript的怪癖之一:提升(Hoisting)
JavaScript,通常被称为“Web 语言”,是一种多功能且广泛使用的编程语言。它以其怪癖而闻名,其中之一就是 hoisting(提升)。无论你是经验丰富的开发人员还是刚刚开始你的编码之旅,理解提升对于编写干净和高效…...

前端特殊字符转码
前端特殊字符转码 建议 最好不要传名称,传ID 是在不行就用这个方法 name encodeURIComponent(name),...

Python开发运维:Python3.7安装Django3.2
目录 一、理论 1.pip 2.Django 3.Pycharm国内镜像源 二、实验 1.Python3.7安装Django3.2 三、问题 1.安装django3.2报错 2.pip更新报错 一、理论 1.pip (1)概念 1)pip pip 是 Python 的包安装程序。其实,pip 就是 Pyt…...

B站双11,联手天猫暴涨2亿消费新势力
一直以来,手持高活跃、高粘性用户群体的B站是行业用来观察年轻人消费习惯的重要平台。以至于用户群体的不断壮大带动了B站的商业价值。如今B站的商业舞台越来越大,不断地向外界招手,欢迎更多品牌积极加入到这个千万年轻人聚集的内容社区。 2…...

如何选择SVM中最佳的【核函数】
参数“kernel"在sklearn中可选以下几种 选项: 接下来我们 就通过一个例子,来探索一下不同数据集上核函数的表现。我们现在有一系列线性或非线性可分的数据,我们希望通过绘制SVC在不同核函数下的决策边界并计算SVC在不同核函数下分类准确…...

RT-Thread的构建与配置系统
Kconfig:kernel config配置文件(提供系统的配置裁剪功能)Scons:构建工具env工具:主要提供构建系统所需的各种环境变量以及软件包的管理 Env Env是RT-Thread推出的开发辅助工具,针对基于RT-Thread操作系统…...

合肥中科深谷嵌入式项目实战——基于ARM语音识别的智能家居系统(一)
基于ARM语音识别的智能家居系统 我们接下来带大家完成基于语音识别的智能家居系统嵌入式项目实战,使用到stm32开发板,讯飞的离线语音识别,我们在此之前,我们先学习一些Linux系统的基本操作。 。 一、Linux简介 在嵌入式开发中&am…...

Git的简介以及基本使用
目录 一.Git的简介 拓展:Git与SVN的区别(各自的优点与缺点) 二.Git文件的4种状态 三.Git的常用命令 搭建完成之后,将项目文件也上传之后,现在模拟其他人来下载这个代码 今天就分享到这啦!!…...

django安装数据库
使用pip安装django pip3 install django注意我使用的是python3所以用pip3安装,如需安装指定版本 django ..* 检测是否安装成功,不报错,则安装成功 # python3 # import django下边这是报错的 django迁移数据库 再mysql中简历数据库 CREATE DATABA…...

springboot--外部环境配置
外部环境配置 前言1、配置优先级配置文件优先级如下(后面的覆盖前面的)测试 2、外部配置3、导入配置4、属性占位符 前言 场景:线上应用如何快速修改配置,并引用最新配置? springBoot 使用配置优先级外部配置 简化配置…...

『MySQL快速上手』-④-表的操作
文章目录 1.创建表2.查看表结构3.修改表4.删除表 1.创建表 语法格式如下: CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎;说明: field 表示列名࿱…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...