已采纳
回答正文
回复
讨论正文
该问题的正文与回答。
背景
我负责一条实时 ETL 管道的核心组件:从 MySQL 读 50~200 万行增量数据做转换后写回目标库。JDK 17 + HikariCP 5.1,maxSize=20。触发方式是定时任务 + Kafka 事件双驱动,高峰期并发读连接数可达 10~15,同时还有大量 RT 5~10ms 的小查询共享同一个池。
现象
开启 useCursorFetch=true, fetchSize=5000 后,单次读 200 万行约 45s。核心矛盾在于:这 45s 内连接一直被占住(HikariCP active 计数不降)。高峰期若 3 个大查询同时触发,20 个连接立刻只剩 5 个可用,其他小查询(正常 P99 12ms)开始排队等连接,P99 飙到 800ms+。但如果不开游标、一次性拉全量,200 万行直接 OOM。
已尝试的排查与结果
fetchSize=1000:内存降了,但读 200 万行耗时翻倍到 90s+,连接占用时间更长,P99 更差;leakDetectionThreshold 频繁告警,且 4 次读之间的"拿-放-再拿"增加了连接池抖动;useCursorFetch 在 5.1 和 8.x 行为有差异(8.x 默认走 useServerPrepStmts 路径),但官方文档没写清楚 fetchSize 对 server-side cursor 的实际生效逻辑。期望得到的答案
fetchSize、maxSize、并发大查询数三者之间有没有一个量化的决策框架或经验公式?比如"大查询并发数 × 预估持有时间 ≤ maxSize × 可接受排队时间"这类;useCursorFetch 行为差异,你们踩过什么坑?fetchSize 到底控制的是"每次从服务端拉多少行"还是"JVM 端 buffer 大小"?LOAD DATA OUTFILE 绕开 JDBC 连接?最好能带上具体的 JDBC URL 参数、HikariCP 配置片段或线上监控截图,谢谢。