什么是大事务
耗时比较长的事务称之为大事务
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飙升。