事务与连接池

共 53 题
📑 题目列表 53 题
#
★★★

1. Bean 销毁时连接池优雅关闭

请说明 Bean 销毁时连接池的优雅关闭(graceful shutdown)?

  • 连接池关闭的时机与方式
  • 未完成事务与借出连接的处理
  • 优雅关闭的实现

连接池的优雅关闭是指在应用停机时,先停止接收新连接,等待正在执行的借出连接归还后,再关闭连接池。HikariCP 等连接池在 close() 时提供优雅关闭机制:标记关闭状态,等待活跃连接归还或超时,然后关闭底层连接。在 Spring 中,连接池 Bean 的销毁方法(@PreDestroy / DisposableBean)会在容器关闭时触发,配合停机钩子(shutdown hook)与 Spring Boot 的 graceful shutdown,先停止接收新请求、等待在途请求完成,再关闭连接池。未完成事务应回滚,借出连接需等待归还或强制关闭并告警。

优雅关闭的核心是"先停新请求,再等旧请求完成,最后关连接池",避免在途事务被强制中断导致数据不一致。理解停机顺序与连接归还等待,可避免数据丢失。

#
★★★

2. Druid 监控在 Spring Boot Actuator 中暴露的连接池指标与 Prometheus Micrometer 维度有何差异

请说明 Druid 监控在 Spring Boot Actuator 中暴露的连接池指标与 Prometheus Micrometer 维度有何差异?

  • Druid 监控指标(StatView)
  • Micrometer 指标
  • 维度差异与集成

Druid 监控(StatViewServlet/StatFilter)暴露连接池的 ActiveCount、PoolingCount、WaitCount、ErrorCount、SQL 执行统计等,维度围绕连接池健康与 SQL 性能。Spring Boot Actuator 通过 Micrometer 暴露标准指标(如 HikariCP 的 hikaricp.connections.active、idle、pending、acquire 等),维度围绕连接状态与获取时间。差异:Druid 侧重 SQL 统计与防火墙,Micrometer 侧重连接池状态与 Prometheus 抓取;Druid 指标需通过 Druid 的 StatView 或自定义适配,Micrometer 作为统一指标抽象可被 Prometheus 直接采集。集成时需将 Druid 指标适配到 Micrometer 或分别采集。

两者是"连接池 SQL 监控"与"标准指标抽象"的区别。理解维度差异,可正确选择监控方案(Druid 的 SQL 分析 vs Micrometer/Prometheus 的连接池指标)。

#
★★★

3. HikariCP 的 registerMbeans 边界

请说明 HikariCP 的 registerMbeans 的边界?

  • registerMbeans 配置
  • JMX 监控暴露
  • 使用边界

HikariCP 的 registerMbeans 配置项控制是否将连接池注册到 JMX(MBeanServer),以暴露连接池指标(活跃、空闲、等待、池大小等)供 JMX 客户端监控。默认 false。开启后可通过 JMX 查看/管理连接池。边界:registerMbeans 开启可能有轻微性能开销并需 JVM 支持 JMX;生产环境通常通过其他监控(Micrometer/Prometheus)采集,registerMbeans 用于 JMX 场景。需注意与 Spring Boot 的 JMX 暴露配合,避免重复注册。

registerMbeans 是"JMX 化连接池"的开关,用于 JMX 监控。理解其与 Micrometer 监控的边界,可选择合适的监控通道。

#
★★★

4. JDBC 事务的 ACID 与隔离级别

请说明 JDBC 事务的 ACID 与隔离级别?

  • ACID 四大特性
  • 隔离级别(READ_UNCOMMITTED 等)
  • 并发问题(脏读/不可重复读/幻读)

JDBC 事务遵循 ACID:原子性(Atomicity,事务要么全成功要么全失败)、一致性(Consistency,事务前后数据状态一致)、隔离性(Isolation,并发事务互不干扰)、持久性(Durability,提交后永久保存)。JDBC 提供四种隔离级别:READ_UNCOMMITTED(可脏读)、READ_COMMITTED(防脏读,允许不可重复读)、REPEATABLE_READ(防不可重复读)、SERIALIZABLE(完全隔离,防幻读)。通过 Connection.setTransactionIsolation 设置。隔离级别越高,并发越低、开销越大。并发问题对应:脏读、不可重复读、幻读。

ACID 与隔离级别是事务正确性的基础。隔离级别是"一致性"与"并发性能"的权衡,需结合数据库默认隔离级别(如 MySQL 默认 REPEATABLE_READ)选择。

#
★★★

5. JPA 与 Hibernate 6.x 在 Spring Boot 4.0 中是否默认支持 Scoped Values 替代 ThreadLocal 事务上下文

请说明 JPA 与 Hibernate 6.x 在 Spring Boot 4.0 中是否默认支持 Scoped Values 替代 ThreadLocal 事务上下文?

  • Scoped Values(JEP 429)与 ThreadLocal
  • 事务上下文的存储
  • Spring Boot 4.0 的默认行为

JDK 的 Scoped Values(JEP 429)是 ThreadLocal 的现代替代,用于在调用链内传递不可变值,但不支持可变绑定。Spring 事务上下文目前仍基于 ThreadLocal(TransactionSynchronizationManager)存储,Spring Boot 4.0 默认并未切换到 Scoped Values 作为事务上下文存储,因为事务上下文需要可变、可同步的绑定,Scoped Values 的不可变语义不完全匹配。Hibernate 6.x 的持久化上下文也仍基于 ThreadLocal/事务同步。虚拟线程下 ThreadLocal 的扩展性被关注,但迁移到 Scoped Values 是渐进过程,默认仍是 ThreadLocal。

Scoped Values 是 ThreadLocal 的演进,但事务上下文需要可变绑定与动态同步,默认仍用 ThreadLocal。理解其差异与默认行为,可正确评估虚拟线程下的上下文管理。

#
★★★

6. JTA 与 Spring Boot 4.0 的 Atomikos 集成在 Seata AT 模式下是否存在事务悬挂风险

请说明 JTA 与 Spring Boot 4.0 的 Atomikos 集成在 Seata AT 模式下是否存在事务悬挂风险?

  • JTA/Atomikos 分布式事务
  • Seata AT 模式
  • 事务悬挂风险

JTA 与 Atomikos 集成提供 XA 分布式事务(两阶段提交),而 Seata AT 模式是另一种分布式事务方案(基于全局锁与回滚日志的补偿式)。两者混用可能产生事务悬挂(hanging)风险:XA 的两阶段提交与 Seata 的全局事务在不同协调器下,若协调器故障或连接被占用,全局事务可能无法正常提交/回滚,导致事务悬挂、连接与资源长期占用。Seata AT 与传统 JTA/XA 的协调机制不同,混用需谨慎,避免双重事务管理冲突。应明确使用单一分布式事务方案,且监控悬挂事务。

分布式事务方案混用(XA 与 Seata AT)会引入协调器冲突与悬挂风险。理解两者的协调机制差异,可避免双重事务管理导致的不一致。

#
★★★

7. PreparedStatement 缓存与 Oracle cursor 关闭

请说明 PreparedStatement 缓存与 Oracle cursor 关闭?

  • PreparedStatement 缓存
  • Oracle 打开游标上限
  • 关闭与泄漏

PreparedStatement 缓存(如 Oracle 的 implicit statement cache、连接池的 PS 缓存)缓存已预编译的语句,减少重复解析。但 Oracle 对打开的游标(cursor)数量有上限(OPEN_CURSORS),若 PreparedStatement 未正确关闭或缓存管理不当,会导致游标耗尽(ORA-01000)。连接池(如 HikariCP)默认会关闭与数据库的连接,连带关闭其上的 Statement/游标,因此需保证连接使用后正确归还(池负责关闭)。配置 PS 缓存大小需与数据库游标上限协调,避免游标泄漏。通过监控已打开游标数可定位泄漏。

PS 缓存提升性能,但游标泄漏是 Oracle 常见问题。理解缓存与游标关闭的关系,保证连接正确归还,可避免 ORA-01000。

#
★★★

8. Spring @Transactional 嵌套调用与 REQUIRED 传播行为在 JDK 25 虚拟线程下的回滚边界如何正确处理

请说明 Spring @Transactional 嵌套调用与 REQUIRED 传播行为在 JDK 25 虚拟线程下的回滚边界如何正确处理?

  • REQUIRED 传播的嵌套事务
  • 回滚边界
  • 虚拟线程下的上下文

REQUIRED 传播行为下,嵌套调用会加入当前事务,共享同一事务边界与回滚范围:内层异常若被捕获,外层可决定是否回滚;若异常传播,整个事务回滚。回滚边界由"最外层事务边界"决定,内层不能独立提交。在 JDK 25 虚拟线程下,Spring 事务上下文通过 ThreadLocal 与虚拟线程绑定,虚拟线程阻塞时上下文仍正确关联(虚拟线程是线程,ThreadLocal 有效),但需注意虚拟线程的复用与上下文隔离,避免事务上下文泄漏到复用的载体线程。正确处理:保持事务边界清晰、异常向上传播以触发回滚、避免在事务内跨线程/非事务边界操作。

REQUIRED 的嵌套是"加入同一事务",回滚边界最外层。虚拟线程下 ThreadLocal 仍按虚拟线程隔离,但需防上下文复用泄漏。理解回滚边界与虚拟线程隔离,可正确设计事务。

#
★★★

9. Spring ChainedTransactionManager 在 Spring Boot 4.0 是否仍可用

请说明 Spring ChainedTransactionManager 在 Spring Boot 4.0 是否仍可用?

  • ChainedTransactionManager 的作用
  • 多数据源事务
  • 可用性与限制

ChainedTransactionManager 是 Spring 提供的多事务管理器链式协调器,按顺序提交多个事务管理器(用于多数据源),但并不能保证真正的原子性(非 XA),某一事务失败时前面的提交无法回滚。在 Spring Boot 4.0 中,ChainedTransactionManager 仍存在但官方不推荐,因为其一致性保证弱。多数据源强一致应使用 XA(Atomikos/Narayana)或分布式事务方案(Seata 等)。Spring Boot 4.0 不会移除但建议少用,除非是"尽力而为"的多数据源事务。

ChainedTransactionManager 是无原子性的广播式提交,仅适合容忍部分提交的场景。理解其限制,可正确选择多数据源事务方案。

#
★★★

10. Spring 事务管理器在 JDK 25 中是否仍依赖 TransactionSynchronizationManager 的 ThreadLocal

请说明 Spring 事务管理器在 JDK 25 中是否仍依赖 TransactionSynchronizationManager 的 ThreadLocal?

  • TransactionSynchronizationManager 的 ThreadLocal
  • 事务上下文绑定
  • 虚拟线程下的影响

Spring 事务管理器(如 DataSourceTransactionManager)通过 TransactionSynchronizationManager 的 ThreadLocal 绑定当前事务的同步资源(连接、事务状态、同步回调),默认仍依赖 ThreadLocal。在 JDK 25 虚拟线程下,每个虚拟线程有自己的 ThreadLocal,事务上下文按虚拟线程隔离,因此事务绑定仍正确。但虚拟线程数量大、复用载体线程时,ThreadLocal 的存储与清理需注意,避免上下文泄漏。Spring 正评估用 Scoped Values 等替代,但默认仍用 ThreadLocal。事务管理器在 JDK 25 中仍依赖 ThreadLocal 实现事务上下文。

事务上下文绑定仍基于 ThreadLocal,虚拟线程下按线程隔离有效。理解其绑定机制与清理,可避免上下文泄漏与跨线程错误绑定。

#
★★★

11. XA 分布式事务在多数据源连接池中 Atomikos/Narayana 的工程取舍

请说明 XA 分布式事务在多数据源连接池中 Atomikos/Narayana 的工程取舍?

  • XA 两阶段提交
  • Atomikos 与 Narayana
  • 工程取舍(性能、复杂度、一致性)

XA 分布式事务通过两阶段提交(2PC)保证跨数据源原子性,Atomikos 与 Narayana 是常见的 XA 事务管理器。Atomikos 轻量、易集成、适合微服务;Narayana(JBoss)功能全面、企业级。工程取舍:XA 保证强一致性,但 2PC 有性能开销、锁持有时间长、协调器故障可能导致悬挂与阻塞,且对数据库与连接池有要求(XA 数据源)。取舍决策:强一致场景用 XA,但需监控协调器;追求性能与最终一致可改用 Seata AT、TCC、本地消息表等补偿方案。多数据源连接池需使用 XA 数据源(XADataSource)配合 XA 事务管理器。

XA 用 2PC 换强一致,代价是性能与协调复杂度。工程取舍在"一致性等级"与"性能/复杂度"之间权衡,理解这一点有助于选型。

#
★★★

12. XADatasource(JTA)与分布式事务的边界

请说明 XADataSource(JTA)与分布式事务的边界?

  • XADataSource 与 JTA
  • 分布式事务的边界
  • connection 与 XA 连接的配合

XADataSource 是支持 XA 协议的数据源接口,提供 XAConnection 以参与 JTA 分布式事务。分布式事务边界由 JTA 事务管理器(如 Atomikos/Narayana)协调多个 XA 资源(多个 XADataSource),通过两阶段提交实现跨库原子性。使用 XA 时,连接池需配置 XADataSource,事务管理器管理全局事务,业务代码通过 @Transactional/JTA 参与。边界:XA 事务内的连接必须来自 XA 数据源,且全局事务的提交/回滚由 JTA 协调,普通连接池无法参与 XA。

XADataSource 是 XA 的资源提供者,JTA 是协调者。理解 XA 连接与全局事务边界,可正确配置分布式事务。

#
★★★

13. leakDetectionThreshold 只能报告疑似长占用而非证明泄漏,如何结合栈信息确认根因

请说明 leakDetectionThreshold 只能报告疑似长占用而非证明泄漏,如何结合栈信息确认根因?

  • leakDetectionThreshold 的机制
  • 疑似占用与真实泄漏
  • 结合栈信息定位

HikariCP 的 leakDetectionThreshold 设置一个阈值,当连接被借出超过该阈值仍未归还时,HikariCP 会记录一条日志(含创建连接的调用栈),报告"疑似连接泄漏"。但超时占用不等于泄漏——长事务、慢查询、分布式锁阻塞等也可能导致连接长期未被归还。确认根因需结合:创建的栈信息(找到借出点)、借出处的调用栈、线程转储(jstack)查看连接持有线程当前状态、以及连接归还日志。若栈显示持有连接后未在 finally 归还,或线程阻塞在等待其他资源,则确认泄漏;若线程在正常执行长事务,则非泄漏。据此修复(try-with-resources 归还、事务边界)。

leakDetectionThreshold 是"疑似"信号,栈信息用于区分"真泄漏"与"长占用"。理解其机制与结合栈分析,可准确定位泄漏根因。

#
★★★

14. 事务中夹杂远程调用为何会长期占用连接,怎样重划事务边界又不破坏业务一致性

请说明事务中夹杂远程调用为何会长期占用连接,怎样重划事务边界又不破坏业务一致性?

  • 事务持有的连接长占用
  • 事务边界划分
  • 重划边界与一致性

事务开启时会从连接池借出连接,直到事务结束才归还。若在事务内夹杂远程调用(HTTP、RPC、消息发送),连接在整个远程调用期间被占用,导致连接长期不归还、并发高时连接池耗尽。重划事务边界:将远程调用移出事务(事务只包裹数据库操作),用"先本地事务提交、再发远程调用"或"事务后事件"(如 @TransactionalEventListener AFTER_COMMIT)触发远程操作。但这样会破坏原子性(本地提交后远程失败),需用补偿机制(对账、重试、消息表+本地事务)保证最终一致。核心是"只让数据库操作占事务,远程调用走事务后异步+补偿"。

事务持连接直至结束,远程调用在其中会占用连接急剧。重划边界是"事务内不碰远程",一致性靠补偿/最终一致。理解连接占用与补偿,可平衡一致性与并发。

#
★★★

15. 事务超时(@Transactional timeout)如何作用于底层连接,与连接池 connectionTimeout、JDBC socketTimeout 的协作与覆盖关系是什么

请说明 @Transactional timeout 如何作用于底层连接,与 connectionTimeout、socketTimeout 的协作与覆盖关系?

  • @Transactional timeout 的机制
  • 三个超时的作用阶段
  • 协作与覆盖

@Transactional(timeout=...) 设置事务超时,Spring 在事务内对每个 SQL 设置 JDBC 查询超时(Statement.setQueryTimeout),超时后抛异常回滚事务。它作用于"事务内单条 SQL 的执行时间"。连接池 connectionTimeout 是"获取连接的等待时间"(借出连接超时),socketTimeout 是"网络层读写超时"(socket 读写)。三者作用阶段不同:connectionTimeout 是拿连接阶段,socketTimeout 是网络传输阶段,@Transactional timeout 是事务内 SQL 执行阶段。不存在互相覆盖,而是分层协作:获取连接超时、网络读写超时、SQL 执行超时各自独立约束。若某层超时先触发则事务终止。

三种超时分别约束"借连接/网络/执行"阶段,是分层协作而非覆盖。理解各阶段超时,可全面设置超时避免连接的长期占用。

#
★★

16. 使用 R2DBC 响应式连接池与 JDBC 连接池并存时,事务边界如何跨线程同步

请说明使用 R2DBC 响应式连接池与 JDBC 连接池并存时,事务边界如何跨线程同步?

  • R2DBC 与 JDBC 连接池并存
  • 反应式事务上下文
  • 跨线程同步

使用 R2DBC 响应式连接池与 JDBC 连接池并存时,事务边界无法直接跨线程同步,因为两者编程模型不同:JDBC 用 ThreadLocal 绑定的同步事务,R2DBC 用响应式 Context 绑定的反应式事务(绑定在订阅链上,不依赖线程)。跨线程同步依赖 ThreadLocal 会失效(R2DBC 不阻塞线程)。正确做法是分别管理事务:JDBC 事务用 Spring 事务管理器,R2DBC 事务用 ReactiveTransactionManager(基于 Context 传播),两者不共享同一事务边界。若需在一个业务流程中同时操作两者,需意识到没有统一原子事务,只能分别提交或引入补偿/分布式事务。

同步(ThreadLocal)与反应式(Context)事务根本不同,无法简单跨线程同步。理解二者绑定机制,可正确设计混合数据访问的事务边界。

#
★★

17. 启用虚拟线程后数据库连接仍是稀缺资源,如何用信号量或池等待时间实施并发准入

请说明启用虚拟线程后数据库连接仍是稀缺资源,如何用信号量或池等待时间实施并发准入?

  • 虚拟线程与连接稀缺
  • 信号量并发准入
  • 池等待时间控制

虚拟线程消除了线程数限制,但数据库连接仍是稀缺资源,无限并发会耗尽连接池。可用信号量(Semaphore)限制同时访问数据库的并发数,超过则等待或拒绝,实现并发准入;或依赖连接池的池等待时间(connectionTimeout)作为隐式准入——连接耗尽时请求等待,超时则失败。合理设计:用信号量控制"进入数据库业务"的并发上限,配合连接池大小与等待超时,防止连接池线程被大量虚拟线程打满。准入控制需结合数据库实际并发能力与目标吞吐。

虚拟线程放大并发,连接成为瓶颈。信号量准入 + 池等待超时是保护连接的关键手段。理解准入控制,可避免连接池耗尽。

#
★★

18. 外层事务并发触发多个 REQUIRES_NEW 为何可能耗尽连接池导致自锁,容量规划应如何考虑嵌套关系

请说明外层事务并发触发多个 REQUIRES_NEW 为何可能耗尽连接池导致自锁,容量规划应如何考虑嵌套关系?

  • REQUIRES_NEW 的独立连接
  • 连接池耗尽与自锁
  • 嵌套容量规划

REQUIRES_NEW 会挂起当前事务并新建独立事务,独立事务需要新的数据库连接。若外层事务并发度高,每个外层事务又触发多个 REQUIRES_NEW,同时需要的外层连接 + 内层连接会超过连接池大小,导致连接池耗尽。此时外层事务持有连接等待内层连接,而内层连接因池耗尽等待归还,形成"自锁"(死锁间的等待)。容量规划需考虑嵌套关系:连接池大小需覆盖"外层连接数 × 每事务最多嵌套层数"的最坏情况,或限制 REQUIRES_NEW 的使用、用事务后异步替代。避免在同一事务内多层 REQUIRES_NEW。

REQUIRES_NEW 每层都占独立连接,嵌套会放大连接需求。理解嵌套连接占用与自锁,可合理规划连接池容量。

#
★★

19. 如何根据数据库并发能力、查询耗时和目标吞吐估算连接池大小,而不是按虚拟线程数量配置

请说明如何根据数据库并发能力、查询耗时和目标吞吐估算连接池大小?

  • 连接池大小的估算公式
  • 数据库并发能力
  • 目标吞吐

连接池大小应根据数据库并发能力与目标吞吐估算,而非按虚拟线程数或应用线程数配置。经验公式:连接数 ≈ 目标并发请求数 × 单请求平均查询耗时 / (单请求总耗时)(即活跃连接数 = 并发请求数 × 数据库占用时间占比)。更实际的做法:结合数据库服务端最大并发连接数上限、单连接能支撑的吞吐(QPS)、单查询耗时与目标吞吐,留有余量。例如数据库每连接可处理约若干 QPS,目标吞吐除以单连接 QPS 得到所需连接数。连接池过小会排队,过大浪费数据库资源并可能拉低性能。需通过压测验证。

连接池大小是"数据库并发能力 × 目标吞吐"的函数,过大过小都有问题。理解估算逻辑与压测验证,可合理配置连接池。

#
★★

20. 应用优雅停机时应先拒绝新请求还是先关闭连接池,未完成事务与借出连接如何处理

请说明应用优雅停机时应先拒绝新请求还是先关闭连接池,未完成事务与借出连接如何处理?

  • 优雅停机顺序
  • 拒绝新请求与关闭连接池
  • 未完成事务与借出连接

优雅停机应先拒绝新请求(停止接收流量),再等待在途请求完成,最后关闭连接池。顺序是:先让负载均衡/网关摘除流量、停止接收新请求;等待在途请求处理完成(含事务提交/回滚);之后关闭连接池,等待借出连接归还或超时强制关闭。未完成事务应让其正常提交或回滚,借出连接需等待归还,若超时未归还则强制关闭并告警(可能有泄漏)。关闭连接池在最后,避免在途请求因连接被关闭而失败。

优雅停机顺序是"先停流量→等在途→关连接池",保证在途事务不被破坏。理解顺序与连接归还,可安全停机。

#
★★

21. 连接归还池前需要重置 autoCommit、只读、隔离级别和 catalog,遗漏会导致怎样的请求串扰

请说明连接归还池前需要重置 autoCommit、只读、隔离级别和 catalog,遗漏会导致怎样的请求串扰?

  • 连接重置
  • 状态残留
  • 请求串扰

连接池复用连接时,若上一个请求修改了连接的 autoCommit、只读模式、隔离级别或 catalog/schema 而未在归还时重置,下一个请求会继承这些残留状态,导致请求串扰(如以为 autoCommit=true 却实际处于长事务、隔离级别被改、schema 错乱)。HikariCP 等连接池默认会重置 autoCommit、只读、隔离级别(依据配置),但 catalog 等需显式处理。连接池的 isReset 与连接校验负责在归还时重置状态。遗漏重置会导致数据一致性与隔离错误,需依赖连接池的复位机制或业务代码规范。

连接复用要求"归还即干净",状态残留会串扰到下一个用户。理解连接池的复位机制,可避免跨请求的状态污染。

#
★★

22. 连接池与 Spring Boot 4.x 的默认切换

请说明连接池与 Spring Boot 4.x 的默认切换?

  • 默认连接池(HikariCP)
  • Spring Boot 4.x 的默认
  • 切换与配置

Spring Boot 默认使用 HikariCP 作为连接池(spring-boot-starter-jdbc 内置)。Spring Boot 4.x 延续默认 HikariCP,但可通过配置更换为其他连接池(如 Druid、Tomcat Pool、Hikari 之外的实现)。切换方式:排除默认连接池依赖并引入目标连接池,或通过 spring.datasource.type 指定 DataSource 类型。Spring Boot 4.x 的默认数据源配置与自动配置仍基于 HikariCP,若切换需注意连接池专属配置(如 Druid 的监控、Wall 过滤器)与自动配置的适配。默认切换通常在需要特定连接池功能(如 Druid 监控)时进行。

Spring Boot 默认 HikariCP,切换连接池需适配其自动配置与专属功能。理解默认与切换方式,可满足特定连接池需求。

#
★★

23. @Transactional 在 Spring Data 与 MyBatis 的差异

请说明 @Transactional 在 Spring Data 与 MyBatis 的差异?

  • Spring Data JPA 的事务
  • MyBatis 的事务
  • 差异

@Transactional 在 Spring Data JPA 与 MyBatis 中都是 Spring 事务边界,但底层:Spring Data JPA 通过 JpaTransactionManager + EntityManager(持久化上下文)管理事务,事务内实体被持久化上下文跟踪,提交时 flush;MyBatis 通过 DataSourceTransactionManager + SqlSessionTemplate,事务内共用 SqlSession 执行 SQL。差异:JPA 有实体生命周期与脏检查(提交时自动 flush),MyBatis 是显式 SQL 执行;两端都支持 Spring 事务传播与回滚规则。@Transactional 的语义(回滚、传播)对两者一致,但"事务内数据的追踪方式"不同。

两者共用 Spring 事务机制,差异在底层数据访问模型(JPA 实体 vs MyBatis SQL)。理解差异可正确使用注解与事务边界。

#
★★

24. @Transactional 的 Connection 持有与释放

请说明 @Transactional 的 Connection 持有与释放?

  • 事务期间连接持有
  • 连接释放时机
  • 与连接池的配合

@Transactional 方法开始时,Spring 事务管理器从连接池借出 Connection 并绑定到事务(ThreadLocal),整个事务期间该连接被持有;事务提交或回滚时,连接归还连接池。连接持有时间 = 事务持续时间,因此事务越长、并发越高,占用连接越多。连接释放由事务管理器在事务边界(提交/回滚)统一处理,业务代码无需手动关闭。若事务内嵌套远程调用或耗时操作,连接被长时间占用。理解连接持有与释放,可合理控制事务边界。

连接在事务边界持有与释放,事务时长决定连接占用时长。理解此机制可避免长事务导致连接耗尽。

#
★★

25. @TransactionalEventListener(phase = AFTER_COMMIT) 的应用

请说明 @TransactionalEventListener(phase = AFTER_COMMIT) 的应用?

  • AFTER_COMMIT 阶段
  • 事务提交后处理
  • 应用场景

@TransactionalEventListener(phase = AFTER_COMMIT) 监听事务提交事件,在事务提交后执行回调,常用于"事务提交后发送消息、清理缓存、异步通知、审计"等副作用操作,避免在事务未提交时就执行导致的数据不一致(如提交失败却已发消息)。它与 @EventListener 的区别是绑定事务生命周期,默认仅在事务提交后触发,可配置 fallbackExecution 处理无事务场景。应用场景:本地事务提交后可靠地触发后续操作,配合发送消息/事件保持一致性。

AFTER_COMMIT 在提交后执行,保证"数据已落库再发副作用"。理解其阶段语义,可避免事务未提交就发消息的不一致。

#
★★

26. DataSource 的标准接口与 DriverManager 的演进

请说明 DataSource 的标准接口与 DriverManager 的演进?

  • DataSource 接口
  • DriverManager 的演进
  • 连接获取的演进

DataSource 是 JDBC 2.0 引入的标准连接工厂接口,提供 getConnection() 获取连接,支持连接池、分布式事务、JNDI 等特性,是容器与框架管理连接的标准。DriverManager 是更早的 JDBC 1.0 机制,通过类加载驱动并静态管理连接,缺少连接池等能力。演进:从 DriverManager(静态、无池)到 DataSource(可扩展、配合连接池与 JTA)。现代框架(Spring、连接池)都基于 DataSource,DriverManager 逐步被替代。DataSource 接口是连接管理的标准抽象。

DataSource 是连接获取的标准抽象,替代 DriverManager 的静态机制。理解其演进,可掌握连接管理的基础。

#
★★

27. Druid 的 SQL 防火墙(Wall Filter)配置

请说明 Druid 的 SQL 防火墙(Wall Filter)配置?

  • WallFilter 的作用
  • 黑白名单与拦截策略
  • 配置方式

Druid 的 WallFilter(SQL 防火墙)用于拦截危险 SQL,防止 SQL 注入、全表更新删除、危险函数调用等。通过配置 WallConfig 设置拦截策略:禁止 DDL、禁止多语句、禁止危险函数、限制表访问、白名单/黑名单等。WallFilter 挂在 Druid 数据源的 filters 中,拦截经过连接的 SQL。配置项包括 wall 的 allowMultiQueries、condition 等。合理配置可提升 SQL 安全性,但需注意勿误拦截合法 SQL(如复杂函数)。

WallFilter 是 SQL 层安全防线,拦截注入与危险操作。理解其策略配置,可增强数据安全同时避免误伤。

#
★★

28. Druid 的功能(Filter、StatView、Wall)配置

请说明 Druid 的功能(Filter、StatView、Wall)配置?

  • Filter 链
  • StatView 监控
  • Wall 防火墙

Druid 提供多种 Filter 通过 filters 配置启用:StatFilter(SQL 统计监控)、WallFilter(SQL 防火墙)、LogFilter(SQL 日志)、Slf4jFilter 等。StatViewServlet 提供一个 Web 监控页面,展示 SQL 执行、连接池状态、慢查询等。Wall 是防火墙。三者配合:StatFilter 采集统计、WallFilter 拦截危险 SQL、StatView 可视化监控。配置在 Druid 数据源(filters、stat-view-servlet、wall 配置)。多数据源或多 Filter 需注意顺序与配置边界。

Druid 的 Filter 体系(统计/防火墙/日志)+ StatView 监控构成完整连接池管理能力。理解各 Filter 作用与配置,可充分发挥 Druid 价值。

#
★★

29. HikariCP 的 connectionTestQuery 与 JDBC 4 兼容性

请说明 HikariCP 的 connectionTestQuery 与 JDBC 4 兼容性?

  • connectionTestQuery 的作用
  • JDBC 4 的 isValid
  • 连接校验

connectionTestQuery 是 HikariCP 用于验证连接是否可用的测试查询(如 "SELECT 1")。但 HikariCP 优先使用 JDBC 4 的 Connection.isValid() 进行连接校验(无需额外查询),只有驱动不支持 JDBC 4 或未实现 isValid 时才需要配置 connectionTestQuery。JDBC 4 兼容的驱动(大多数现代驱动)通过 isValid 校验,减少额外查询开销。connectionTestQuery 是回退方案,用于校验连接健康(防死连接)。

现代 JDBC 4 驱动用 isValid 校验,connectionTestQuery 是旧驱动回退。理解其优先级,可正确配置连接校验。

#
★★

30. HikariCP 的 connectionTimeout 与 idleTimeout 在云原生弹性扩缩容下应如何动态调整

请说明 HikariCP 的 connectionTimeout 与 idleTimeout 在云原生弹性扩缩容下应如何动态调整?

  • connectionTimeout 与 idleTimeout
  • 弹性扩缩容
  • 动态调整

connectionTimeout 是获取连接的等待超时,idleTimeout 是空闲连接的回收时间(超过则从池中移除)。云原生弹性扩缩容下,实例数/流量动态变化,连接配置需动态调整:流量高峰时可能需提高 connectionTimeout(容忍排队)或增大池;但 idleTimeout 固定可能导致空闲连接随实例缩容而浪费,或高峰时连接不足。实践中通过配置中心/环境变量动态调整池大小与超时,或让连接池随负载自适应(HikariCP 的 pool 大小在运行时调整)。动态调整需结合目标吞吐与数据库能力,避免扩缩容时连接过载或不足。

弹性扩缩容下连接池配置需动态匹配流量。理解 connectionTimeout/idleTimeout 的语义,可设计动态调整策略。

#
★★

31. HikariCP 的 leakDetectionThreshold 在生产环境检测连接泄漏的工程价值

请说明 HikariCP 的 leakDetectionThreshold 在生产环境检测连接泄漏的工程价值?

  • leakDetectionThreshold 的机制
  • 泄漏检测价值
  • 生产环境应用

leakDetectionThreshold 设置连接借出超时监控阈值,超过阈值 HikariCP 记录连接创建栈,提示疑似泄漏。工程价值:在连接池耗尽前及早发现连接未被归还的问题,结合日志定位泄漏源头(借出点)。生产环境设置合理的阈值(大于最慢正常事务时间)可有效监控泄漏,避免连接池被耗尽导致系统不可用。但阈值过高会延迟发现,过低会误报。价值在于"提前预警 + 定位借出栈",是连接池健康的重要保障。

leakDetectionThreshold 是连接泄漏的预警机制,帮助定位借出点。理解其阈值与误报,可安全用于生产监控。

#
★★

32. HikariCP 的 maxLifetime 为什么应短于数据库或网络设备的连接寿命,并保留随机退避

请说明 HikariCP 的 maxLifetime 为什么应短于数据库或网络设备的连接寿命,并保留随机退避?

  • maxLifetime 的意义
  • 与数据库/网络连接寿命
  • 随机退避

maxLifetime 是连接的最大存活时间,HikariCP 会在连接超过 maxLifetime 后主动关闭该连接。应短于数据库或网络设备(防火墙、负载均衡)的连接空闲超时,避免底层连接被设备静默断开后连接池仍持有"死连接"。保留随机退避(randomization)是因为若所有连接同时达到 maxLifetime 并在同一瞬间被关闭,会导致连接池短暂空窗、请求排队;随机退避让连接错峰关闭,减少抖动。maxLifetime 应小于数据库连接空闲超时,并保持随机化。

maxLifetime 提前于底层超时主动回收,随机退避避免集中断连。理解其与底层超时的关系,可避免死连接与断连抖动。

#
★★

33. HikariCP 的 maximumPoolSize 与数据库服务端最大连接数的容量规划取舍

请说明 HikariCP 的 maximumPoolSize 与数据库服务端最大连接数的容量规划取舍?

  • maximumPoolSize
  • 数据库最大连接数
  • 容量规划

maximumPoolSize 是连接池的上限,需与数据库服务端最大连接数(max_connections)协调。多个应用实例的 maximumPoolSize 之和不能超过数据库服务端最大连接数(否则连接被拒绝)。容量规划取舍:连接池过大浪费数据库资源并拖慢性能,过小导致排队;需权衡目标吞吐、数据库并发能力与实例数。规划时:每个实例的 maximumPoolSize 乘以实例数 < 数据库 max_connections - 运维预留。理解服务端上限与实例分摊,可合理规划避免连接耗尽。

连接池容量受数据库服务端上限约束,需按实例分摊。理解取舍(吞吐 vs 资源)可避免连接被拒或资源浪费。

#
★★

34. HikariCP 的关键配置(maximumPoolSize、connectionTimeout)

请说明 HikariCP 的关键配置(maximumPoolSize、connectionTimeout)?

  • maximumPoolSize
  • connectionTimeout
  • 其他关键配置

HikariCP 关键配置:maximumPoolSize 是连接池最大连接数(默认 10),决定并发数据库能力;connectionTimeout 是获取连接的等待超时(默认 30 秒),超时抛异常;idleTimeout 是空闲连接回收时间;maxLifetime 是连接最大存活时间;minimumIdle 是最小空闲连接数;validationTimeout 是连接校验超时。合理配置:maximumPoolSize 结合数据库能力与吞吐,connectionTimeout 权衡排队与快速失败,idleTimeout/maxLifetime 管理连接生命周期。这些配置共同决定连接池的性能与稳定性。

maximumPoolSize 与 connectionTimeout 是最常调优的两个核心配置,其他配置管理生命周期。理解其语义可合理配置连接池。

#
★★

35. JDBC RowSet(离线型)在断开连接后仍可操作数据的场景与连接池释放时机

请说明 JDBC RowSet(离线型)在断开连接后仍可操作数据的场景与连接池释放时机?

  • 离线型 RowSet
  • 断开连接后操作
  • 连接释放时机

离线型 RowSet(如 CachedRowSet)在查询后与数据库连接断开,数据加载到内存,可离线操作(增删改、滚动),之后可重新连接同步。场景:数据在断开连接后仍可编辑、批量传输、无需持连接的场景。连接池释放时机:离线型 RowSet 在查询完成后即可释放连接(数据已加载),不长期占用连接,适合释放连接后继续处理数据。相比持连接操作,离线型释放连接更快,降低连接占用。

离线型 RowSet 数据脱离连接,可离线操作并提前释放连接。理解其数据加载时机,可优化连接占用。

#
★★

36. MySQL JDBC 驱动的 AOT 初始化配置如何最小化

请说明 MySQL JDBC 驱动的 AOT 初始化配置如何最小化?

  • AOT 与原生镜像
  • MySQL 驱动初始化
  • 最小化配置

在 GraalVM Native Image/AOT 下,MySQL JDBC 驱动默认的运行时初始化(反射、动态加载)需通过配置最小化。可通过 native-image 的 -H:ReflectionConfigurationResources 提供反射元数据,或用 -H:InitializationAtBuildTime 将驱动初始化提前到构建期,减少运行时初始化。最小化配置:将 MySQL 驱动的 Class 注册到反射/初始化配置,声明驱动类与需要的接口,避免运行时反射。Spring Boot 的 AOT 处理会自动生成部分元数据,但 MySQL 驱动自定义部分需补充。最小化目标是减少运行时动态初始化,加快启动。

AOT 下驱动的运行时初始化需转为构建期并补充反射元数据。理解最小化配置,可让 MySQL 驱动在原生镜像中正常加载。

#
★★

37. NESTED 传播借助 savepoint 实现局部回滚,与 REQUIRES_NEW 在连接占用和回滚范围上有何本质差异

请说明 NESTED 传播借助 savepoint 实现局部回滚,与 REQUIRES_NEW 在连接占用和回滚范围上的本质差异?

  • NESTED 的 savepoint
  • REQUIRES_NEW 的独立事务
  • 连接占用与回滚范围

NESTED 传播基于 savepoint 实现嵌套事务:内层事务在 savepoint 上建立,内层失败只回滚到 savepoint(局部回滚),不影响外层;但外层回滚时会一并回滚内层。NESTED 不新建独立连接,复用外层连接(同一条连接上的 savepoint)。REQUIRES_NEW 挂起当前事务并新建独立事务,占用新的独立连接,其提交/回滚完全独立,与外层无关。本质差异:NESTED 复用连接、靠 savepoint 局部回滚、受外层影响;REQUIRES_NEW 占新连接、事务完全独立、可独立提交。连接占用上 NESTED 不增连接,REQUIRES_NEW 增加连接。

NESTED 是"外层事务内的 savepoint 子事务",REQUIRES_NEW 是"独立新事务"。理解连接占用与回滚范围差异,可正确选择传播行为。

#
★★

38. Spring @Transactional 在哪些场景会静默失效(自调用、非 public 方法、异常被 catch、rollbackFor 未配置、代理未生效)

请说明 Spring @Transactional 在哪些场景会静默失效?

  • 自调用
  • 非 public 方法
  • 异常被 catch

Spring @Transactional 基于 AOP 代理,以下场景会静默失效:1. 自调用(同类内方法调用 this.method(),绕过代理);2. 非 public 方法(事务代理只拦截 public);3. 异常被 catch 吞掉(事务无法感知);4. rollbackFor 未配置(默认只回滚 RuntimeException/Error,检查异常不回滚);5. 代理未生效(未开启代理、final 类、实例化绕过代理)。这些都会导致事务不开启或异常不触发回滚。解决:通过注入代理调用、方法设为 public、异常向上传播或正确配置 rollbackFor、确保代理生效。

事务失效多因"没走代理"或"异常未传播"。理解这些失效场景,可避免事务静默失效导致的数据不一致。

#
★★

39. javax.sql.DataSource 与 Jakarta 演进

请说明 javax.sql.DataSource 与 Jakarta 演进?

  • javax.sql 到 Jakarta SQL
  • DataSource 接口
  • Jakarta EE 演进

javax.sql.DataSource 是 JDBC 的标准连接工厂接口,仍返回 java.sql 的连接。在 Jakarta EE 演进中,javax.sql 属于 JDBC(java.sql/javax.sql)而非 Jakarta EE 重命名的 API,因此 DataSource 接口本身未改名为 jakarta.sql(JDBC 仍用 javax.sql 命名空间)。但 Jakarta Persistence、Jakarta Transactions 等从 javax 改为 jakarta。理解:DataSource 接口位于 JDBC 的 javax.sql 命名空间,不受 Jakarta EE 重命名影响,仍是标准的连接获取抽象。

JDBC 的 javax.sql 命名空间未随 Jakarta EE 重命名,DataSource 仍是标准连接工厂。理解命名空间演进,可正确导入与使用。

#
★★

40. keepaliveTime、idleTimeout 与 minimumIdle 如何共同作用,保活查询为何不能解决活动连接失效

请说明 keepaliveTime、idleTimeout 与 minimumIdle 如何共同作用,保活查询为何不能解决活动连接失效?

  • keepaliveTime
  • idleTimeout 与 minimumIdle
  • 保活查询的局限

HikariCP 中:minimumIdle 保持池中最小空闲连接数;idleTimeout 回收超过空闲时间的连接;keepaliveTime 控制对空闲连接执行保活查询的间隔(防止被网络设备/数据库断开)。三者共同作用:keepaliveTime 定期保活维持空闲连接有效性,idleTimeout 回收长时间空闲连接,minimumIdle 补齐最少空闲数。但保活查询只能维持"空闲"连接,不能解决"活动"连接失效:若连接正被使用(事务中)时数据库/设备断开,保活查询不会触发(它在空闲时执行),活动连接失效需靠连接校验(validationTimeout)与异常处理(重连)来解决。保活无法覆盖使用中的连接。

保活针对空闲连接,活动连接失效靠校验与重连。理解 keepaliveTime 的作用域,可正确搭配连接保活与失效处理。

#
★★

41. validationTimeout 与 connectionTimeout 分别约束什么阶段,配置倒置会产生哪些误判

请说明 validationTimeout 与 connectionTimeout 分别约束什么阶段,配置倒置会产生哪些误判?

  • validationTimeout 的连接校验
  • connectionTimeout 的获取连接
  • 配置倒置的误判

connectionTimeout 约束"获取连接"阶段:从池中借出连接最多等待多久,超时抛异常(连接池耗尽)。validationTimeout 约束"连接校验"阶段:从连接池借出后,校验连接有效性(isValid)的最大等待时间。两者阶段不同:connectionTimeout 是等待借连接,validationTimeout 是校验连接。配置倒置(如 validationTimeout 大于 connectionTimeout)会误判:校验超时可能被误认为获取超时,或连接池耗尽时校验等待掩盖真实问题;且 validationTimeout 应小于 connectionTimeout,否则校验失败不能及时反馈。错误配置会导致超时诊断错误。

两个超时约束不同阶段,validationTimeout 应小于 connectionTimeout。理解阶段与大小关系,可避免误判连接问题。

#
★★

42. JDK 25 虚拟线程下连接池的 maxPoolSize 默认值是否应根据载体线程数动态调整

请说明 JDK 25 虚拟线程下连接池的 maxPoolSize 默认值是否应根据载体线程数动态调整?

  • 虚拟线程与连接池
  • maxPoolSize 依据
  • 动态调整

虚拟线程下,并发线程数不再受限于平台线程,但 maxPoolSize 应基于数据库并发能力与目标吞吐,而非载体线程数。虚拟线程数可以非常多,但连接池是稀缺资源,MAX 应依据数据库能力设置,而不是等于载体线程数。不建议按载体线程数动态调整 maxPoolSize,因为连接池上限应稳定匹配数据库能力;虚拟线程过多时靠信号量/准入控制限制并发,而非放大连接池。是否需要动态调整取决于负载:稳态下可固定,弹性扩缩容时结合流量调整。默认值应保守,避免连接打满数据库。

虚拟线程解耦线程与连接,maxPoolSize 应匹配数据库能力而非载体线程数。理解依据,可避免连接池过大或过小。

#

43. Druid 连接池的 WallFilter SQL 防火墙在多数据源应用中的配置边界与绕过风险

请说明 Druid 连接池的 WallFilter SQL 防火墙在多数据源应用中的配置边界与绕过风险?

  • WallFilter 多数据源配置
  • 配置边界
  • 绕过风险

多数据源应用中,WallFilter 需为每个数据源配置(挂在各自 Druid 数据源的 filters 中),若某数据源未配置 WallFilter 则其 SQL 不受防火墙保护,形成配置边界缺口。绕过风险:多数据源某个未配置防火墙、应用层绕过 Druid 直接使用 JDBC(不经过 Druid 数据源)、或配置的 WallConfig 策略被绕过(如禁用某项检查)。需确保所有入口数据源都配置 WallFilter,且统一策略,避免某数据源成为绕过缺口。

WallFilter 是"每数据源"的安全配置,遗漏即绕过。理解配置边界,可确保多数据源全量受保护。

#

44. HikariCP 在 Spring Boot 4.x 虚拟线程下使用 synchronized 获取连接的 JEP 491 兼容性与性能边界

请说明 HikariCP 在 Spring Boot 4.x 虚拟线程下使用 synchronized 获取连接的 JEP 491 兼容性与性能边界?

  • JEP 491 虚拟线程 synchronized 固定
  • HikariCP 的锁
  • 性能边界

JEP 491(虚拟线程增强)处理虚拟线程在 synchronized 块中阻塞时对载体线程的"固定"(pinning)问题。HikariCP 内部使用 synchronized 管理连接(如获取连接的锁),在虚拟线程下,若虚拟线程在 synchronized 内阻塞等待连接,可能固定载体线程,影响并发扩展。JEP 491 的目标是让虚拟线程在 synchronized 中不固定载体线程(或提供替代),HikariCP 的同步锁在虚拟线程下存在性能边界:高并发下 synchronized 竞争可能成为瓶颈并造成固定。解决方案:使用无锁/非阻塞的连接获取或调整,Spring Boot 4.x 下需评估 HikariCP 的锁实现与虚拟线程的兼容性。

JEP 491 关注 synchronized 对虚拟线程的固定。HikariCP 的同步锁在虚拟线程并发下是性能与兼容性边界,需评估。

#

45. 多租户切换 schema 或会话变量时,怎样保证异常路径也能清理并避免连接泄露租户上下文

请说明多租户切换 schema 或会话变量时,怎样保证异常路径也能清理并避免连接泄露租户上下文?

  • 租户上下文切换
  • 异常路径清理
  • 连接池复用的污染

多租户切换 schema(USE db)或会话变量(SET @tenant_id)时,切换状态残留到连接上,若连接归还连接池后未清理,下一个请求会继承上一个租户的 schema/变量,导致租户串扰。确保异常路径也清理:用 try-finally 或事务同步清理,在 finally 中恢复默认 schema/清空会话变量,或依赖连接池归还时的状态重置。关键是"无论成败都清理",避免异常导致租户上下文残留。可用 AOP 统一清理或连接池校验重置,保证连接归还时干净。

租户上下文残留会串扰,异常路径清理是安全关键。理解连接复用的清理机制,可避免租户数据泄露。

#

46. 连接池与反应式(R2DBC Pool)的边界

请说明连接池与反应式(R2DBC Pool)的边界?

  • R2DBC 连接池
  • 与 JDBC 连接池的不同
  • 编程模型

R2DBC 连接池(r2dbc-pool)是反应式连接池,提供以 Reactive 方式获取/归还连接(acquire/release 返回 Monos),不阻塞线程,与 JDBC 连接池(阻塞获取)的编程模型根本不同。R2DBC 连接池管理反应式连接,获取连接在订阅时异步完成,连接数仍受数据库能力限制。边界:JDBC 连接池用于阻塞式数据访问,R2DBC 连接池用于反应式数据访问,两者不能混用(一个连接不能同时用于阻塞与反应式)。选择取决于应用编程模型(WebFlux vs MVC)。

R2DBC 连接池是反应式语义,与 JDBC 阻塞式连接池边界分明。理解边界,可正确选择连接池与编程模型。

#

47. 连接池在 Spring Modulith 多模块的边界

请说明连接池在 Spring Modulith 多模块的边界?

  • 连接池的模块归属
  • 多模块共享数据源
  • 边界

在 Spring Modulith 多模块架构中,连接池/数据源通常作为基础设施模块(infrastructure)提供,业务模块通过注入使用,不重复创建连接池。连接池 Bean 是全局单例,多个业务模块共享同一个数据源,避免每模块各自建池导致连接打满。边界:连接池属于基础设施层,业务模块不应直接管理连接池细节(如关闭),通过标准接口访问。事务边界也应遵循模块边界,避免跨模块的数据库操作因连接/事务归属混乱。

连接池是基础设施层的全局单例,业务模块共享。理解其归属边界,可避免重复建池与资源浪费。

#

48. 连接池的 connectionTestQuery/validationTimeout 在数据库连接健康检查中的设置

请说明连接池的 connectionTestQuery/validationTimeout 在数据库连接健康检查中的设置?

  • connectionTestQuery
  • validationTimeout
  • 健康检查

连接池健康检查用于发现失效连接(死连接、已断开)。validationTimeout 约束校验连接的最大等待时间,connectionTestQuery 是校验测试 SQL(旧驱动回退)。设置上:validationTimeout 应小于 connectionTimeout,避免校验超时误判;connectionTestQuery 在驱动不支持 isValid 时配置(如 "SELECT 1")。合理设置健康检查可及时剔除失效连接,避免应用使用死连接导致异常。结合 keepaliveTime 维持空闲连接有效。

健康检查参数(validationTimeout/connectionTestQuery)配合连接校验,剔除失效连接。理解其设置关系,可保证连接可靠。

#

49. 连接池的监控指标(活跃、空闲、获取时长)

请说明连接池的监控指标(活跃、空闲、获取时长)?

  • 活跃/空闲连接
  • 获取时长
  • 监控意义

连接池监控指标包括:活跃连接数(active)、空闲连接数(idle)、池大小(max/min)、等待获取连接数(pending)、获取连接时长(acquire time)、连接使用时长(usage time)等。活跃高说明并发负载高,空闲高说明池偏大,获取时长长说明池耗尽或数据库慢,使用时长长说明长事务或慢查询。监控这些指标可定位容量问题:活跃接近 max 且等待多 → 池不足;获取时长高 → 池耗尽或数据库性能;使用时长高 → 长事务/慢 SQL。结合指标可调优连接池。

连接池指标反映并发与容量状态。理解各指标含义,可定位容量与性能问题。

#

50. 连接池监控中 active、idle、pending、acquire time 和 usage time 如何组合定位容量问题

请说明连接池监控中 active、idle、pending、acquire time 和 usage time 如何组合定位容量问题?

  • 各指标含义
  • 组合分析
  • 容量定位

连接池监控中:active 是当前借出连接数,idle 是空闲连接数,pending 是等待获取连接的请求数,acquire time 是获取连接耗时,usage time 是连接使用时长。组合定位:若 active 长期接近 max 且 pending>0、acquire time 高 → 连接池容量不足,需增大池或优化;若 active 低但 idle 高 → 池过大浪费;若 acquire time 低但 usage time 高 → 连接被长事务/慢查询占用,非池容量问题,需优化 SQL/事务;若 pending 高且 usage time 高 → 连接被长占用导致排队。综合各指标可区分"池不足"与"连接被长占用"。

组合指标可区分"池容量不足"与"连接被长事务占用"。理解各指标关系,可精准定位容量瓶颈。

#

51. 连接泄漏(Connection Leak)的检测与防范

请说明连接泄漏(Connection Leak)的检测与防范?

  • 泄漏的成因
  • 检测手段
  • 防范措施

连接泄漏指连接从池中借出后未归还(如未在 finally 关闭、异常路径未释放),导致连接池逐渐耗尽。检测:连接池的 leakDetectionThreshold 监控借出超时并记录栈;监控 active 连接数异常增长;连接池相关日志。防范:使用 try-with-resources 或 finally 确保归还;用连接池的泄漏检测;正确划分事务边界避免长占用;监控连接池指标告警。结合栈信息定位泄漏源头。

连接泄漏是常见的资源问题,检测靠池的泄漏监控与指标,防范靠正确的资源管理与事务边界。理解其机制可避免连接耗尽。

#

52. HikariCP 在 GraalVM Native Image 的边界

请说明 HikariCP 在 GraalVM Native Image 的边界?

  • Native Image 的反射
  • HikariCP 的初始化
  • 配置与限制

GraalVM Native Image 下,HikariCP 依赖反射(创建数据源、代理、属性访问)与动态初始化,需通过反射配置(reflect-config.json)声明相关类,或用 build-time 初始化确保 HikariCP 在构建期初始化。边界:HikariCP 默认的运行时初始化(基于反射的配置)在原生镜像中需适配,Spring Boot 的 AOT 处理会生成部分配置。部分 HikariCP 功能(如 JMX 注册、动态配置)在原生镜像中受限。需通过配置元数据使其在 Native Image 中正常工作。

Native Image 的封闭世界与 HikariCP 的反射/动态初始化冲突,需配置元数据。理解边界,可评估 HikariCP 在原生镜像的可行性。

#

53. JDK 25 中虚拟线程与连接池的协作(spring.threads.virtual.enabled=true)

请说明 JDK 25 中虚拟线程与连接池的协作(spring.threads.virtual.enabled=true)?

  • 虚拟线程启用
  • 连接池协作
  • 并发与连接

spring.threads.virtual.enabled=true 让 Spring Boot 使用虚拟线程执行请求(如 Web 容器),阻塞式数据库调用在虚拟线程上执行时,阻塞会释放载体线程,提升并发吞吐。虚拟线程与连接池协作:虚拟线程并发数远超连接池,连接成为瓶颈,需结合连接池大小与准入控制(信号量等)防止连接耗尽。虚拟线程的阻塞式 JDBC 在释放载体线程时仍占用连接(连接是稀缺资源),因此连接池需要合理配置与监控。协作重点是"虚拟线程扩并发 + 连接池控资源"。

虚拟线程提高并发吞吐,连接池仍是资源瓶颈。理解其协作,可在虚拟线程下合理配置连接池与准入。