spring 大事务

1,084 阅读2分钟

这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战

什么是大事务

耗时比较长的事务称之为大事务

spring中开启@Trancational注解开启事务或者AOP切面开启事务。不手动开启事务,mysql默认自动提交事务,一条语句执行完自动提交。

慢sql,执行一条sql的时间超过设定值即慢sql。慢sql记录在慢sql日志中,log_slow_queries= "C:/temp/mysql_slow.log"。系统中一般会对慢sql进行监控,对高频影响性能的慢sql进行优化处理。

大事务产生的原因

  • 操作的数据比较多
  • 大量的锁竞争
  • 事务中有其他非DB的耗时操作
  • 运算量比较大

常见的形式有 select较多,调用了rpc方法较多,for循环处理数据较多,执行了比较耗时的计算,执行了较大的batch数据库操作。

大事务造成的影响

  • 并发情况下,数据库连接池容易被撑爆
  • 锁定太多的数据,造成大量的阻塞和锁超时
  • 执行时间长,容易造成主从延迟
  • 回滚所需要的时间比较长
  • undo log膨胀

最主要的影响数据库连接池容易被撑爆,导致大量线程等待,造成请求无响应或请求超时。

从监控维度来看qps基于之前无太大变化,jvm数据指标正常,但数据库连接已占满,存在大量等待线程。

如何查询大事务

sql查询

select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>10

如何避免大事务

  • 非必要不需要手动开启事务即添加@Trancational注解。如select操作,不要回滚的crud操作,单条语句mysql本身存在事务。
  • 在一个事务里面, 避免一次处理太多数据
  • 在一个事务里面,尽量避免不必要的查询
  • 在一个事务里面, 避免耗时太多的操作,造成事务超时。一些非DB的操作,比如rpc调用,消息队列的操作尽量放到事务之外操作
  • 在一个事务里面,尽量避免复杂的计算

对复杂的耗时较长的业务,在逻辑处理层不要开启事务,进行数据查询,逻辑处理,组装要进行db操作的数据,最后再在dbservice层开启事务,以减少事务持续的时间。

优化for循环的处理,如多次rpc的调用,改为单次批量调用。

对于数据库批量操作,控制批次最大提交量,不要在同一事务中多批次提交。

提供一个大事务导致连接池占满的监控图,请求链接的耗时Acquire time飙升。

Snipaste_2021-08-06_11-36-53.png