拓冰建站拓冰建站
首页 / 资讯中心 / 正文

MyBatis Plus SQL日志配置与优化实践

1. MyBatis Plus打印SQL日志的核心价值在数据库操作开发过程中SQL日志是排查问题、优化性能的重要依据。MyBatis Plus作为MyBatis的增强工具默认的日志输出往往无法满足深度调试需求。当我们需要检查执行的SQL语句是否正确、参数是否合理时完整的SQL日志输出就显得尤为关键。实际开发中遇到过这样的场景一个复杂的多表联查在测试环境运行正常上了生产却返回空结果。没有完整的SQL日志我们花了3个小时才定位到是生产环境数据库字段命名规范不同导致的。如果当时开启了详细SQL日志可能5分钟就能发现问题所在。2. MyBatis Plus日志配置方案对比2.1 内置日志实现分析MyBatis Plus支持多种日志实现每种实现方式在输出内容和格式上有所区别日志实现类输出特点适用场景性能影响StdOutImpl控制台输出完整SQL及参数本地开发调试低Slf4jImpl通过SLF4J输出到日志文件生产环境调试中NoLoggingImpl不输出任何SQL日志生产环境运行无提示生产环境建议使用Slf4jImpl配合日志级别控制避免日志量过大影响性能2.2 推荐配置方案在application.yml中配置最完整的日志输出mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl log-sql: true这种配置会输出类似如下的日志格式 Preparing: SELECT id,name FROM user WHERE age ? Parameters: 18(Integer) Total: 33. 高级日志配置技巧3.1 使用P6Spy实现SQL拦截对于需要更详细SQL监控的场景可以集成P6Spy添加依赖dependency groupIdp6spy/groupId artifactIdp6spy/artifactId version3.9.1/version /dependency配置spy.propertiesmodule.logcom.p6spy.engine.logging.P6LogFactory appendercom.p6spy.engine.spy.appender.StdoutLogger logMessageFormatcom.p6spy.engine.spy.appender.MultiLineFormat修改数据源配置spring.datasource.urljdbc:p6spy:mysql://localhost:3306/testP6Spy会输出包含执行时间的完整SQL1592200395102|0|statement|connection 5|SELECT id,name FROM user WHERE age 18|SELECT id,name FROM user WHERE age 183.2 动态日志级别控制通过代码动态调整日志级别RestController RequestMapping(/log) public class LogController { GetMapping(/sql/{level}) public String setSqlLogLevel(PathVariable String level) { Logger logger (Logger) LoggerFactory.getLogger(com.baomidou.mybatisplus); logger.setLevel(Level.valueOf(level)); return SQL日志级别设置为 level; } }4. 生产环境日志优化4.1 慢SQL监控配置在application.yml中添加慢SQL阈值mybatis-plus: global-config: db-config: slow-sql-millis: 1000 log-slow-sql: true当日志中出现如下警告时就需要关注SQL性能Slow SQL: 1256ms - SELECT * FROM large_table WHERE ...4.2 日志文件分离配置在logback-spring.xml中单独配置SQL日志文件appender nameSQL_FILE classch.qos.logback.core.rolling.RollingFileAppender filelogs/sql.log/file rollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicy fileNamePatternlogs/sql.%d{yyyy-MM-dd}.log/fileNamePattern /rollingPolicy encoder pattern%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n/pattern /encoder /appender logger namecom.baomidou.mybatisplus levelDEBUG additivityfalse appender-ref refSQL_FILE/ /logger5. 常见问题排查指南5.1 日志不输出问题检查清单确认配置文件中没有设置log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl检查日志级别是否为DEBUG或TRACE确保没有其他日志框架覆盖了MyBatis Plus的日志配置5.2 参数显示为问号如果看到SQL日志中的参数显示为?通常是因为没有使用推荐的StdOutImpl参数类型转换器配置有问题使用了某些安全插件对敏感信息进行了脱敏解决方案Bean public ConfigurationCustomizer configurationCustomizer() { return configuration - { configuration.setLogPrefix(MYBATIS-LOG - ); configuration.setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class); }; }5.3 多数据源日志配置对于多数据源场景需要为每个数据源单独配置Bean ConfigurationProperties(spring.datasource.db1) public DataSource dataSourceDb1() { return DataSourceBuilder.create() .type(HikariDataSource.class) .build(); } Bean public SqlSessionFactory sqlSessionFactoryDb1() throws Exception { MybatisSqlSessionFactoryBean factoryBean new MybatisSqlSessionFactoryBean(); factoryBean.setDataSource(dataSourceDb1()); factoryBean.setConfiguration(new Configuration() {{ setLogImpl(StdOutImpl.class); }}); return factoryBean.getObject(); }6. 日志分析与性能优化6.1 日志分析技巧通过正则表达式提取关键信息# 提取执行时间超过100ms的SQL grep -E Time: \d{3,}ms sql.log # 统计各SQL执行频率 awk -FPreparing: {print $2} sql.log | sort | uniq -c | sort -nr6.2 基于日志的优化建议当发现以下日志模式时需要特别注意频繁出现的相同SQL - 考虑使用缓存大量SELECT *查询 - 优化为只查询必要字段多次单条INSERT - 合并为批量INSERT没有使用索引的查询 - 添加适当索引我在实际项目中遇到过这样一个案例日志显示某个分页查询每次都要执行count语句通过添加缓存后性能提升了20倍// 优化前 PageUser page new Page(1, 10); userMapper.selectPage(page, null); // 优化后 PageUser page new Page(1, 10, false); // 不查询总记录数7. 安全与隐私注意事项生产环境避免输出完整SQL参数特别是包含敏感信息的字段使用日志脱敏插件处理密码等敏感信息定期清理历史日志文件设置适当的日志文件权限推荐的安全配置示例public class SensitiveDataSqlLogger extends StdOutImpl { Override public void debug(String text) { text text.replaceAll((password|token)([^]*), $1***); super.debug(text); } }在配置中指定自定义loggermybatis-plus: configuration: log-impl: com.example.config.SensitiveDataSqlLogger8. 扩展应用场景8.1 结合Arthas进行动态调试当生产环境不能直接修改日志级别时可以使用Arthas动态修改# 查看当前logger logger --name com.baomidou.mybatisplus # 修改日志级别 logger --name com.baomidou.mybatisplus --level debug8.2 与Prometheus监控集成通过日志解析实现SQL监控指标Aspect Component public class SqlMonitorAspect { private final Counter sqlCounter Counter.build() .name(sql_exec_total) .help(Total SQL executions) .register(); AfterReturning(execution(* org.apache.ibatis.session.SqlSession.*(..))) public void afterSqlExecution() { sqlCounter.inc(); } }8.3 多租户场景下的日志区分在多租户系统中可以在日志中增加租户标识public class TenantAwareLogger extends StdOutImpl { Override public void debug(String text) { String tenantId TenantContext.getCurrentTenant(); super.debug([ tenantId ] text); } }9. 日志格式自定义9.1 实现自定义日志格式继承BaseJdbcLogger实现个性化日志public class CustomSqlLogger extends BaseJdbcLogger { Override public void debug(String text) { String formatted LocalDateTime.now() | Thread.currentThread().getName() | text; System.out.println(formatted); } }9.2 彩色日志输出在支持ANSI颜色的终端中输出彩色日志public class ColorSqlLogger extends StdOutImpl { private static final String GREEN \033[32m; private static final String RESET \033[0m; Override public void debug(String text) { super.debug(GREEN text RESET); } }10. 性能考量与最佳实践开发环境可以使用最详细的日志级别但生产环境应该根据实际情况调整高频执行的SQL可以考虑抽样记录避免日志爆炸将SQL日志输出到单独文件便于后续分析定期检查日志文件大小设置合理的滚动策略实测数据表明开启DEBUG级别日志会使系统吞吐量降低约15-20%因此建议开发环境DEBUG级别测试环境INFO级别慢SQL日志生产环境WARN级别告警日志在Spring Boot中可以通过Profile区分配置--- spring: profiles: dev mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl --- spring: profiles: prod mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门