You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot内嵌内存H2DB内存泄漏问题求助

内存H2DB循环删插后OOM问题(MVStore内存泄漏解决方案)

问题背景

使用Spring Boot 2.7.1 + Spring Data JPA 2.7.1 + H2 2.1.212内嵌内存数据库,保持最新10万条记录,持续删除旧数据并插入新数据。运行4-5小时后触发OOM,删除记录后内存占用仍持续增长;MAT堆分析显示org.h2.mvstore.tx.TransactionStore$TxMapBuilder$TMVMap实例占用77.95%堆内存,内存集中在org.h2.mvstore.Page$PageReference[];重启应用后相同记录数仅占用30%内存。

解决方案

1. 强制MVStore页压缩与清理

H2的MVStore默认不会主动回收已删除数据占用的页,需手动触发压缩释放内存。建议在每次批量删除后执行:

-- 针对单表压缩
ALTER TABLE YOUR_TABLE_NAME COMPRESS;
-- 全局压缩所有MVStore数据
CALL COMPRESS();

2. 调整H2数据源配置参数

修改JDBC URL,添加MVStore优化参数:

jdbc:h2:mem:db;DB_CLOSE_ON_EXIT=FALSE;DATABASE_TO_LOWER=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE;MV_STORE=TRUE;MVCC=FALSE;MV_AUTO_COMPRESS=TRUE;MV_PAGE_SIZE=16384;MV_MAX_PAGE_COUNT=100000
  • MV_AUTO_COMPRESS=TRUE:开启自动压缩,当页使用率低于阈值时自动触发
  • MV_PAGE_SIZE=16384:调大页大小(默认4k),减少总页数量
  • MV_MAX_PAGE_COUNT:限制最大页数量,超过后强制清理无用页

3. 排查并关闭长事务

未提交的长事务会导致MVStore保留旧版本数据,无法释放内存。确保所有数据库操作都在短事务内完成,及时提交或回滚,避免事务长时间持有资源。

4. 升级H2版本

H2 2.1.x版本存在MVStore内存泄漏已知问题,建议升级至2.2.x及以上稳定版,官方已修复该场景下的部分内存泄漏问题。

5. 主动触发内存回收

通过H2 API主动执行检查点与压缩,在Spring Boot中可通过数据源调用:

try (Connection conn = dataSource.getConnection()) {
    Statement stmt = conn.createStatement();
    stmt.execute("CALL COMPRESS()");
    stmt.execute("CALL CHECKPOINT()");
} catch (SQLException e) {
    // 异常处理逻辑
}

CHECKPOINT()会强制刷写内存数据并清理无用页。

6. 定时重建表(兜底方案)

若上述方案无效,可定期重建表彻底清理内存:

  1. 创建临时表,插入最新10万条记录
  2. 重命名原表后删除
  3. 将临时表重命名为原表名

内容的提问来源于stack exchange,提问作者Arjun Sahoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 18:15:01