多数据源日志需通过mdc注入数据源标识(如pg-main)并在logback中用%x{ds}输出;mybatis可按sqlsessionfactory配置独立logger名隔离;事务与连接层需在determinecurrentlookupkey、druid慢sql、transactionsynchronizationmanager等处打标;避免仅靠包路径或线程名区分,异步任务须手动传递mdc。

多数据源操作时,日志本身不会自动标记SQL来自哪个数据源,必须通过主动增强日志上下文来区分。核心思路是:在执行SQL前,把当前数据源标识(比如 pg-main 或 sqlserver-bi)注入到日志上下文中,让每条MyBatis日志、事务日志、甚至自定义业务日志都带上来源标签。
用MDC绑定数据源名称
MDC(Mapped Diagnostic Context)是SLF4J提供的线程级键值存储,特别适合在请求或事务开始时写入上下文信息,并在日志格式中引用。
- 在切换数据源的逻辑入口(如自定义
@TargetDataSource("pg-main")注解的AOP切面)里,调用MDC.put("ds", "pg-main") - 在日志配置(如logback.xml)中,把
%X{ds}加入pattern,例如:%d{HH:mm:ss.SSS} [%X{ds}] [%thread] %-5level %logger{36} - %msg%n - 这样每条日志开头就会显示类似
[pg-main] [http-nio-8080-exec-2] INFO c.a.m.UserMapper - ==> Preparing: SELECT * FROM users
为MyBatis配置独立日志前缀
MyBatis自身支持为每个SqlSessionFactory指定不同的日志实现类,可配合Logback的Logger命名空间做隔离。
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 给PostgreSQL的
SqlSessionFactory设置logger name为mybatis.pg,SQL Server的设为mybatis.sqlserver - 在logback.xml中分别配置两个logger,使用不同appender或不同
pattern,例如:<logger name="mybatis.pg" level="DEBUG" additivity="false">...</logger> - 启动时加上
-Dlogging.level.mybatis.pg=DEBUG,就能单独控制某一个数据源的SQL日志开关
在事务和连接层打标
Spring事务管理器和数据库连接获取过程也是关键节点,可在这些位置埋点。
- 自定义
AbstractRoutingDataSource的determineCurrentLookupKey()方法,在返回key前记录日志:log.debug("Switched to data source: {}", key); - 如果用Druid连接池,可开启
connection-properties中的druid.stat.mergeSql=true,并配合logSlowSql=true,慢SQL日志会自动包含数据源别名 - 在
TransactionSynchronizationManager回调中(如beforeCommit),读取当前事务绑定的DataSource对象并输出摘要
避免混淆的实操提醒
有些做法看似能区分,实际效果有限,需要注意:
- 不要只靠包路径区分——比如把PostgreSQL的Mapper全放在
pg.*包下,SQL Server的放sqlserver.*,因为日志里只显示类名,不体现运行时真实数据源 - 不要依赖线程名——HTTP线程名(如
http-nio-8080-exec-5)和数据源无关,且会被复用 - 异步任务(如
@Async)会丢失MDC内容,需手动传递:MDC.getCopyOfContextMap()+MDC.setContextMap()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










