性能优化-实战一次性读数据太多

63 阅读1分钟

背景

springboot web应用,宕机,无法接受响应,性能优化

初步排查

  • jps找到对应的java进程 pid
  • top -Hp 对应的java进程pid

  • 通过这个pid 126,找到对应的线程 (126通过 print(%x))
  • jstack 进程pid | grep 7f
  • 发现是一个叫VM THREAD的线程cpu高

内存dump

  • jmap -dump:format=b,file=heapdump.hprof java进程pid
  • jprofile读取hprof文件
  • 看到byte[]特别多

  • 我们选中byte[] 查看合并的传入应用,发现和mysql相关

都指向了一段代码,查询数据太多

cleanTicketWarnData

代码排查

发现一个sql查了100多万的数据,直接gc了

改进

方案一

用了mybatis stream 方式(游标形式)读取全表数据

上面这个做法不对,应该是handleResult里面去处理

注意点

开启游标在mysql的驱动,需要设置

resultSetType="FORWARD_ONLY" fetchSize="-2147483648"

主要原因,在mysql驱动中是这样写的

/**
 * We only stream result sets when they are forward-only, read-only, and the
 * fetch size has been set to Integer.MIN_VALUE
 * 
 * @return true if this result set should be streamed row at-a-time, rather
 *         than read all at once.
 */
protected boolean createStreamingResultSet() {
    return ((this.resultSetType == java.sql.ResultSet.TYPE_FORWARD_ONLY) && (this.resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY)
            && (this.fetchSize == Integer.MIN_VALUE));
}

方案二

通过主键,每次1000,减少查询的数量