记录一次mysql长事务的经历

目录

一.项目介绍

二.问题暴漏

三.问题排查

1.连接池方向

2.数据库方向

四.代码模拟

五.错误原因分析

1.MySQL参数优化

2.代码优化

六.总结


一.项目介绍

项目是springboot+nacos的微服务架构,商城购物类系统,分多个服务,问题出现在众多服务中的单个服务

二.问题暴漏

在系统日志中显示错误:connection holder is null,空连接

Caused by: java.sql.SQLException: connection holder is null
	at com.alibaba.druid.pool.DruidPooledConnection.checkStateInternal(DruidPooledConnection.java:1155)
	at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.java:1148)
	at com.alibaba.druid.pool.DruidPooledConnection.prepareStatement(DruidPooledConnection.java:336)

这种错误是偶发现象,日志出现时,重启后消失,使用druid连接池

三.问题排查

1.连接池方向

初步认为连接池的问题,通过给druid开源项目提issue,尝试调整druid参数

参数调优过程:

1.调整maxActive,加大连接数

2.开启remove-abandoned,调整remove-abandoned-timeout和log-abandoned,清除未使用的连接

3.druid从1.1.9升级当时最新版本1.2.23

4.开启test-while-idle,启用keep-alive,加大min-evictable-idle-time-millis,用于连接检测

5.开启test-on-borrow和test-on-return,连接在借还时进行检测

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/emall?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    druid:
      # 初始化时建立物理连接的个数
      initial-size: 0
      # 最小空闲连接数
      min-idle: 0
      # 设置连接池中最大活动连接数
      max-active: 10
      # 获取连接时最大等待时间,单位毫秒,1000毫秒等1秒
      max-wait: 30000
      # 多久进行一次空闲连接的检测,单位毫秒(60,000 毫秒为1分钟)
      time-between-eviction-runs-millis: 60000
      # 连接在池中最小生存的时间,单位毫秒
      min-evictable-idle-time-millis: 300000
      # 设置用于连接验证的 SQL 查询语句
      validation-query: SELECT 1
      # 在空闲时检测连接有效性
      test-while-idle: true
      # 获取连接时不测试连接,影响性能
      test-on-borrow: false
      # 归还连接时不测试连接,影响性能
      test-on-return: false
      # 启用keepAlive,确保连接池中的连接不被数据库服务端关闭
      keep-alive: true
      # 是否清除长时间未使用的连接
      remove-abandoned: false
      #定义连接被认定为被遗弃之前的超时时间(单位:秒)
      remove-abandoned-timeout: 1800
      #是否记录遗弃连接的日志信息
      log-abandoned: true  # 记录遗弃连接的日志

通过以上几个参数的调整,错误是有变化的,好像是一套组合拳,removeAbandoned: true/testOnBorrow=true/升级版本,三个操作下去,出现connection closed

Caused by: java.sql.SQLException: connection closed
  at com.alibaba.druid.pool.DruidPooledConnection.checkStateInternal(DruidPooledConnection.java:1178)
  at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.java:1169)
  at com.alibaba.druid.pool.DruidPooledConnection.prepareStatement(DruidPooledConnection.java:356)

关闭removeAbandoned: false,出现connection disabled

Caused by: java.sql.SQLException: connection disabled
        at com.alibaba.druid.pool.DruidPooledConnection.checkStateInternal(DruidPooledConnection.java:1184)
        at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.java:1169)
        at com.alibaba.druid.pool.DruidPooledConnection.prepareStatement(DruidPooledConnection.java:356)

错误都出自druid连接池的DruidPooledConnection的checkStateInternal方法

以上操作并没有解决问题,

2.数据库方向

1.对mysql数据库进行参数调优,应该是开启testOnReturn: true,配置mysq的'max_connections'最大连接数为2000,组合操作下来,看到的新错误,Lock wait timeout exceeded; try restarting transaction

Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

另一个错误是Statement cancelled due to timeout or client request

Cause: com.mysql.cj.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client request

2.调整mysql以下参数进行观察

SET innodb_lock_wait_timeout = 100; #增加锁等待时间为100s
set global innodb_print_all_deadlocks=1;#控制是否将所有死锁信息打印到 MySQL 错误日志
SET GLOBAL max_allowed_packet = 10M; 指定客户端与服务器之间通信时单个数据包的最大大小4改10

以上操作没有解决问题

3.通过查询数据库中的事务,锁,连接情况,查看是否有慢sql,性能查询语句:

SELECT
  trx.trx_id  事务的唯一标识符,
  trx.trx_state   事务的状态,
  trx.trx_started 事务开始的时间,
  trx.trx_mysql_thread_id 事务关联的MySQL线程ID,
  trx.trx_isolation_level 事物隔离级别,
  t.name 线程名称,
  pl.Id 线程ID,
  pl.USER 线程所属的用户,
  pl.HOST 线程连接的主机,
  pl.Command  线程的当前命令,
  pl.TIME 线程的运行时间,
  pl.State 线程的状态,
  pl.Info 正在执行的SQL语句,
  es.THREAD_ID ,
  es.SQL_TEXT 当前执行的SQL语句,
  es.CURRENT_SCHEMA 当前使用的数据库,
  es.TIMER_WAIT/1000000000 语句的执行时间,
  il.lock_id 锁的唯一标识符,
  il.lock_mode 锁的模式,
  il.lock_type 锁的类型,
  il.lock_table 被锁定的表,
  il.lock_index 被锁定的索引,
  il.lock_space 被锁定的表空间,
  il.lock_page 被锁定的页,
  il.lock_rec 被锁定的记录
FROM
  information_schema.INNODB_TRX trx
  LEFT JOIN information_schema.PROCESSLIST pl ON trx.trx_mysql_thread_id = pl.Id
  LEFT JOIN information_schema.INNODB_LOCKS il ON trx.trx_id = il.lock_trx_id
	LEFT JOIN PERFORMANCE_SCHEMA.threads t ON t.processlist_id =  pl.id
	LEFT JOIN PERFORMANCE_SCHEMA.events_statements_current es ON es.THREAD_ID  = t.thread_id

查询mysql大量的长事务和锁等待,事务执行时间太长,这个是明显能查到的问题,应该是事务长时间未提交导致,即着手先解决长事务问题.

四.代码模拟

通过对事务不提交操作,模拟长事务

数据库出现长时间的事务未提交,锁类型:表锁和行锁,锁模式:IX:表级别意向排他锁,X:行级别排他锁,REC_NOT_GAP: 记录锁(不包括间隙,确保锁定的是精确的行记录,避免幻读),InnoDB存储引擎使用多种锁模式来实现事务隔离和一致性

再执行一次方法,出现锁等待,

五.错误原因分析

可能长事务存在时间超过了druid连接池的生存时间,连接被连接池回收关闭,程序报错,并且大量的长事务造成锁等待或者死锁,消耗资源.

1.MySQL参数优化

可以缩短mysql的wait_timeout一个连接在服务器端闲置多长时间后会被自动关闭,默认是8小时,比如600秒

2.代码优化

1.缩小事务控制范围,比如,只有在更新数据库时,再开启事务,对于查询等这类逻辑操作无需开启事务.

2.发生异常时,捕捉异常,进行事务回滚.

3.逻辑判断需要提前结束方法时.对于已经开启的事务记得关闭.

六.总结

问题为何偶发,并且系统自上线的这几年来只有近期才出现问题.

        可能是在近期MySQL提升了隔离级别,由读已提交(Read Committed)改为可重复读(Repeatable Read),为保证数据的一致性,数据库的锁竞争会变的激烈,并发事务对同一资源(如表或行)的访问需求较高,导致锁(行锁或者表锁)争用严重,并且造成死锁,虽然 InnoDB 通常会自动检测和处理死锁,但在某些复杂情况下,可能会导致事务超时。较高的事务隔离级别(如 SERIALIZABLE)可能会导致更多的锁竞争和等待超时。之前适合RC级别的代码写法已经不适用RR级别.

        近期又是系统使用高发期,使用人数较多,业务牵扯的范围较广,但代码优化的覆盖面却很窄,导致问题暴漏,功能阻塞,后续将继续做好监测.        

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AI学习】LLaMA 系列模型的进化(一)

一直对LLaMA 名下的各个模型关系搞不清楚,什么羊驼、考拉的,不知所以。幸好看到两篇综述,有个大致了解,以及SEBASTIAN RASCHKA对LLaMa 3的介绍。做一个记录。 一、文章《Large Language Models: A Survey》中对LLaMa的介绍 论文…

解决 执行 jar 命令 控制台乱码

Springboot项目,编码为utf8 打包后,为了在控制台运行时不乱码,需要在控制台中依次执行以下命令: 第一步: chcp 65001第二步: java -jar -Dfile.encodingutf-8 你的.jar

【GUI软件】小红书蒲公英数据批量采集!高效筛选优质博主,助力品牌商

文章目录 一、背景介绍1.0 爬取目标1.1 演示视频1.2 软件说明 二、代码讲解2.0 关于接口2.1 爬虫采集模块2.2 cookie获取2.3 软件界面模块2.4 日志模块 三、获取采集软件 一、背景介绍 1.0 爬取目标 众所周知,蒲公英是小红书推出的优质创作者商业合作服务平台&…

《庆余年》在前,《玫瑰的故事》在后,阅文发现“新大陆”?

奋笔疾书的网文作家,即将迎来网络文学的高光时代。 近日,阅文集团于安徽省举办2024阅文创作大会。现场数据显示,2023年阅文活跃作家平均收入增长32%,创造近五年最大增幅。其中,中位数作家收入增幅达135%,已…

SSH 远程执行任务

SSH 是 Linux 下进行远程连接的基本工具,但是如果仅仅用它来登录那可是太浪费啦!SSH 命令可是完成远程操作的神器啊,借助它我们可以把很多的远程操作自动化掉!下面就对 SSH 的远程操作功能进行一个小小的总结。 远程执行命令 如…

ThreeJS-截屏下载pdf或者图片时白屏

JS-页面截图下载为pdf 关于如何下载为 pdf 在上面的这篇文章中有写,大家可以看下,下载图片代码在最下面 这时我们发现 three 部分是空白的如下: 这就多少有点尴尬了,这时我们习惯性的看下后台报错 是不是发现了惊喜,…

操作系统 内存管理

实验目的: 理解虚拟内存在内存管理中的核心作用。掌握常见的内存分配回收算法思想。 实验内容: 编程模拟实现内存伙伴buddy分配器。 实验步骤: 1.理解Buddy分配算法原理: 在开始编码之前,先要深入理解Buddy分配算法的原理。…

Web应用安全测试-综合利用(二)

Web应用安全测试-综合利用(二) Host头攻击 漏洞描述 Web应用程序获取网站域名一般是依赖HTTP Host header(比如在JSP里通过request.getHeader()获取),这里的header很多情况下是不可靠的。 攻击者恶意利用HTTP Host h…

小米HyperOS 澎湃os机型免答题 免社区等级 秒接bl锁操作步骤解析【二】

前面两期博文; 小米HyperOS 澎湃os机型免答题 免社区等级 秒接bl锁操作步骤解析 小米机型解锁bl 绕过社区等级5才可以解锁的限制的教程_没有五级社区怎么解锁bl-CSDN博客 小米对米粉解锁bl是越来越苛刻了。目前社区等级 答题 审核等等步骤越来越繁琐。而且通过率很低。知名开…

细说MCU输出互补型PWM波形时设置死区时间的作用

目录 一、工程背景 二、死区时间的作用 一、工程背景 在作者的文章里建立工程时,为配置输出互补型PWM波形曾经设置了死区时间,DEAD100个定时器的时间周期(简称实例1):细说MCU输出互补型PWM波形的实现方法-CSDN博客 …

计算机行业的现状与未来之2024

年年都说编程好,编程工资涨不了。 人家骑车送外卖,月入两万好不好。 一、计算机专业的背景与现状 在过去几十年里,计算机科学相关专业一直是高考考生的热门选择。无论是计算机科学与技术、软件工程,还是人工智能与大数据&#xff…

数据链路层知识分享【计算机网络】【以太网帧 | MTU的影响 | ARP技术】

博客主页:花果山~程序猿-CSDN博客 文章分栏:Linux_花果山~程序猿的博客-CSDN博客 关注我一起学习,一起进步,一起探索编程的无限可能吧!让我们一起努力,一起成长! 目录 前文 一, 以…

《算法笔记》总结No.2——模拟

一.简单模拟 考察代码能力,不涉及算法:一类题目怎么说你就怎么做的类型~ 巴音布鲁克比赛,以车队为基准评选冠军。业务要求是:第一行输入正整数N,代表车手的总个数;接下来的N行每行键入两个数字&#xff1a…

在同一个 Blazor 应用中结合 SQL-DB 和 MongoDB

介绍 传统上,在单应用程序中,我们对整个应用程序使用单个数据库服务器。但是,我将 SQL 数据库和 MongoDB 结合在同一个应用程序中。此应用程序将是 RDBMS 和 No SQL 数据库的组合。我们将从头开始创建一个 Blazor 应用程序,并使用…

全域外卖系统源码部署怎么做,外卖市场新机遇!

随着本地生活下半场的到来,全域外卖逐渐成为众多创业者关注的焦点,再加上抖音关于新增《【到家外卖】内容服务商开放准入公告》的意见征集通知(以下简称“通知”)的发布,更是将当前全域外卖赛道重点入局方式之一的全域…

《无与伦比》Centos7 扩容到已有逻辑卷

命令可以查找硬盘和分区情况 fdisk -l lsblk

MyBatis的配置文件,即:src->main->resources的配置

目录 1、properties 标签 1.1 mybatis-config.xml 1.2 db.properties 1.3 在SqlMapConfig.xml 中 引入数据库配置信息 2、typeAliases 标签 2.1 定义别名 2.2 使用别名 3、Mappers标签 作用:用来在核心配置文件中引入映射文件 引入方式,有以下…

RocketMQ源码学习笔记:源码启动NameServer,Broker

这是本人学习的总结,主要学习资料如下 马士兵教育rocketMq官方文档 目录 1、Overview2、NameServer2.1、源码启动NameServer 3、Broker启动过程 1、Overview 这篇文章的源码的版本是release-4.9.8。在启动各个模块之前应该先对项目进行打包mvn install -Dmaven.te…

Ubuntu-24.04-live-server-amd64启用ssh

系列文章目录 Ubuntu-24.04-live-server-amd64安装界面中文版 Ubuntu安装qemu-guest-agent Ubuntu乌班图安装VIM文本编辑器工具 文章目录 系列文章目录前言一、输入安装命令二、使用私钥登录(可选)1.创建私钥2.生成三个文件说明3.将公钥复制到服务器 三…

Android面试题之App的启动流程和启动速度优化

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点 App启动流程 ①点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求; ②system_se…