当前位置: 首页 > 科技观察

SpringBoot下如何记录SQL语句、SQL参数、慢SQL日志

时间:2023-03-12 02:18:17 科技观察

当我们的程序访问数据库,遇到BUG或者性能问题时,我们希望能够打印出SQL语句和参数,以便定位BUG和性能问题问题。你可能使用的方式通常,以SpringDataJPA和Hibernate为例(不要走开,解决方案与数据库访问技术无关,理论上可以使用Mybatis和JDBC),我们在应用程序中配置。yamlUse:spring.jpa.show-sql:true但是这个设置只能在开发测试环境下设置,因为使用这个属性相当于使用System.out.println来打印SQL语句,会有性能问题。并且不能显示SQL的参数。或者我们在application.yaml中通过设置Hibernate属性来配置它:有几个问题:在批处理的情况下,并不清楚实际上有多少条语句被发送到数据库服务器,因为日志消息是在准备阶段打印的,而不是在调用executeBatch方法时打印的。org.hibernate.type.descriptor.sql只能记录内置的Hibernate核心类型,如果使用自定义类型,则不会打印。下面介绍一个开源项目,名称为:datasource-proxy,地址:https://github.com/jdbc-observations/datasource-proxy。它提供了一个JDBCDataSource代理:ProxyDataSource,也就是说它可以用在SpringBoot下的任何数据访问技术中,比如:JPA、Mybatis等,即使多种数据访问技术混用,datasource-proxy也可以打印连接的所有语句通过JDBC。使用datasource-proxy新建demo工程:添加相关依赖我们可以直接添加datasource-proxy依赖,然后通过ProxyDataSourceBuilder自己创建ProxyDataSource。但是我们不需要这样做,因为已经有人为我们写好了datasource-proxy的SpringBootStarter,我们可以直接使用这个starter直接配置datasource-proxy。启动器地址:https://github.com/gavlyukovskiy/spring-boot-data-source-decorator。Gradleimplementation'com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.8.1'或Mavencom.github.gavlyukovskiydatasource-proxy-spring-boot-starter1.8.1简单的数据访问表现类:@Data@Entity@AllArgsConstructor@NoArgsConstructorpublicclassPerson{@Id@GeneratedValue(strategy=GenerationType.IDENTITY)privateLongID;私有字符串名称;privateIntegerage;}publicinterfacePersonRepositoryextendsJpaRepository{ListfindByNameStartsWith(Stringname);}简单的数据访问查询测试@SpringBootApplicationpublicclassLoggingSqlApplication{publicstaticvoidmain(String[]args){SpringApplication.run(LoggingSqlApplication.class,args);}@BeanCommandLineRunnercommandLineRunner(PersonRepositorypersonRepository){返回参数->{personRepository.save(newPerson(null,"wiselyman001",18));personRepository.save(newPerson(null,"wiselyman002",18));personRepository.save(newPerson(null,"wiselyman003",18));personRepository.save(newPerson(null,"wiselyman004",18));personRepository.findByNameStartsWith("wiselyman");};}}datasource-proxydatasource-proxy-spring-boot-starter的核心配置为我们提供了一个DataSourceProxyProperties来配置DataSourceProxy,我们可以通过application.yaml进行配置例如:#设置日志库,默认为slf4j(slf4j,jul,common,sysout)decorator.datasource.datasource-proxy.logging:slf4j#启用所有查询日志,默认为truedecorator.datasource.datasource-proxy。询问。enable-logging:truedecorator.datasource.datasource-proxy.query.log-level:debug#Lognamesettingdecorator.datasource.datasource-proxy.query.logger-name:#设置慢SQL的情况,慢的日志级别SQL是WARNdecorator.datasource.datasource-proxy.slow-query.enable-logging:truedecorator.datasource.datasource-proxy.slow-query.log-level:warndecorator.datasource.datasource-proxy.slow-query.logger-name:#setting认为是慢sql时间,用日志记录decorator.datasource.datasource-proxy.slow-query.threshold:300decorator.datasource.datasource-proxy.multiline:truedecorator.datasource.datasource-proxy.json-format:false#enableQueryindexdecorator.datasource.datasource-proxy.count-query:false以上为默认配置,如果满足要求,无需单独设置。如果我们没有特殊定制,只需要在application.yaml中添加:logging.level.net.ttddyy.dsproxy.listener:debugrunningprogramName:dataSource,Connection:3,Time:36,Success:TrueType:Prepared,Batch:False,QuerySize:1,BatchSize:0Query:["insertintoperson(age,name)values(?,?)"]Params:[(18,wiselyman001)]2022-10-1717:13:16.907DEBUG12740---[main]n.t.d.l.l.SLF4JQueryLoggingListener:Name:dataSource,Connection:4,Time:34,Success:TrueType:Prepared,Batch:False,QuerySize:1,BatchSize:0Query:["insertintoperson(age),name)values(?,?)"]Params:[(18,wiselyman002)]2022-10-1717:13:17.041DEBUG12740---[main]n.t.d.l.l.SLF4JQueryLoggingListener:Name:dataSource,Connection:5,Time:33,Success:TrueType:Prepared,Batch:False,QuerySize:1,BatchSize:0Query:["insertintoperson(age,name)values(?,?)"]Params:[(18,wiselyman003)]2022-10-1717:13:17.183DEBUG12740---[主要]n.t.d.l.l.SLF4JQueryLoggingListener:名称:dataSource,Connection:6,Time:36,Success:TrueType:Prepared,Batch:False,QuerySize:1,BatchSize:0Query:["insertintoperson(age,name)values(?,?)"]Params:[(18,wiselyman004)]2022-10-1717:13:17.407DEBUG12740---[主要]n.t.d.l.l.SLF4JQueryLoggingListener:名称:数据源,连接:7,时间:37,成功:TrueType:准备,批次:False,QuerySize:1、BatchSize:0Query:["selectperson0_.idasid1_0_,person0_.ageasage2_0_,person0_.nameasname3_0_frompersonperson0_whereperson0_.namelike?escape?"]Params:[(wiselyman%,\)]参考资料:https://github.com/jdbc-observations/datasource-proxyhttps://github.com/gavlyukovskiy/spring-boot-data-source-decoratorhttps://vladmihalcea.com/the-best-way-to-日志-jdbc-语句/https://vladmihalcea.com/log-sql-spring-boot/