没有配置该参数的时候,一条更新(update、insert)就代表了向Mysql发送一条语句

可以实现 多条更新语句合并提交给mysql ,他会把多条更新语句,拼接成一条语句发送给mysql

数据库连接 中的设置 URL 把参数加上即可

没有报错信息

故障排查过程

经过排查,发现是业务更新数据库走的是 jdbcTemplate.batchUpdate ,并且加了 rewriteBatchedStatements 这个参数才导致更新失败

那么我们仔细看看 batchUpdate 这个方法。

当我们继续往里面跟,就会直接去到第三方源码里面了:

JdbcTemplate.batchUpdate

这边我们可以很清晰地看到在Spring的JdbcTemplate是注册了一个 PreparedStatement 回调函数。

这个回调函数其实就是Spring用来接受数据库语句执行后的结果。

我们再进下一层 ps.executeBatch

PreparedStatement.executeBatch

看到这里其实已经能看到我们这个参数 rewriteBatchedStatements 判断是否开启的地方了

抑或是我们可以通过直接搜索这个参数,去看引用他的地方,也非常好定位

同样也能定位到刚刚那个地方。

我们可以看到这个参数要起作用还要满足一些条件:

  • 版本号要大于 4.1.0
  • 要有更新数据
  • 并且数量要大于3条sql
  • 否则还是去走一条一条sql。

    到这里,我们再进下一层 executePrepareBatchAsMultiStatement

    PreparedStatement.executePrepareBatchAsMultiStatement

    看到开头我就非常敏感, 他这里是直接拼接一个分号 ; ”到语句里面。而且我们看到他的注释:

    “这是一种比较滥用的方式,但是确实能够解决问题”

    异常出现的地方

    因为框架里面会给我们的语句添加一个分号 ; 如果我们在原语句也有分号,那么就会有2个分号,引起语法错误

  • 加上参数 rewriteBatchedStatements 能很大程度上提高我们对数据批量写入的能力
  • 注意 原sql语句结尾不要带分号;
  • 为什么没有 报错信息
  • 为什么批量更新 只有一行数据能更新成功
  • 问题1:无报错信息

    这边是捕获 DataACcessEXception 异常,我看可以看看他的继承关系图:

    然后我们去看看框架里面batchUpdate,捕获的是也是 DataAccessException 异常。

    我们再进下一里面一层查看,直接去看他在接口的定义,发现他抛的是 SQLException

    查看的继承关系图:

    这2个异常八竿子打不着,所以我们修改为抛父类的异常,这样在应用层面就能捕获到异常

    修改完了之后查看一下报错信息:

    不过我们一般不能直接写 e.printStackTrace ,好像是在阿里的Java规范手册里面说禁止这种写法。

    改成这种会比较好

     def updateBatch(sql: String, argList: List[Array[Any]]): Unit = {
       FrequentChecker.sqlRecord(sql)
       try {
         jdbcTemplate.batchUpdate(sql, argList.map(_.map(_.asInstanceOf[AnyRef])).asJava)
       } catch {
         case e: Exception => logger.error(s"updateBatch error, sql: ${sql}, error message: ${e.getMessage}")
    

    问题2:只有一行数据能更新成功