H2数据库源码学习+debug, 数据库 sql、数据库引擎、数据库存储从此不再神秘

一、源码结构概览

H2源码采用标准Maven结构,核心模块在src/main/org/h2目录下:

├── command/ # SQL解析与执行

├── engine/ # 数据库引擎核心(会话、事务)

├── table/ # 表结构定义与操作

├── index/ # 索引实现(B-Tree、MVCC)

├── store/ # 存储引擎(页管理、日志)

├── jdbc/ # JDBC驱动实现

├── mvstore/ # MVStore存储引擎(v1.4+)

├── expression/ # SQL表达式处理

└── util/ # 工具类(缓存、字符串处理)


二、核心模块深度解析

1. SQL解析与执行(command包)
  • 解析流程 :通过手写递归下降解析器(Parser.java)将SQL语句转换为抽象语法树(AST)。

    // 示例:解析SELECT语句

    public Prepared parseQuery() {

    Prepared prep = readQuery();

    prep.prepare();

    return prep;

    }

  • 查询优化Query类处理逻辑优化,Optimizer负责选择执行计划(如索引选择)。

2. 存储引擎(store包)
  • 页式存储PageStore类管理数据页(默认4KB),支持B-Tree索引结构。

    • 页类型:数据页、索引页、空闲列表页
  • 事务日志WriteAheadLog实现WAL机制,确保ACID特性。

    // 日志写入示例

    wal.logRecord(Loggable.TRANSACTION_LOG, data);

3. MVCC与事务管理(engine包)
  • 多版本控制TransactionStore跟踪数据版本,通过Row的版本链实现快照隔离。

  • 锁机制LockManager管理行级锁,Session隔离级别控制可见性。

    // 事务提交关键代码

    session.commit(false);

4. 索引实现(index包)
  • B-Tree索引PageBtreeIndex实现范围查询优化。
  • 哈希索引NonUniqueHashIndex用于等值查询加速。
  • MVStore索引 :新版MVStore采用跳跃表结构(org.h2.mvstore)。

三、关键设计亮点

  1. 双存储引擎支持

    • 传统PageStore(兼容性优先)
    • 新版MVStore(高并发优化,K/V设计)
  2. 内存优化技术

    • 对象池化(ValuePool重用常用对象)
    • 延迟反序列化(DataPage按需加载列)
  3. 查询编译缓存

    // 缓存已编译的查询计划

    Prepared prep = cache.get(sql);

    if (prep == null) {

    prep = parse(sql);

    cache.put(sql, prep);

    }


四、调试与学习建议

  1. 入口跟踪 :从org.h2.command.Parserparse()方法开始,跟踪SQL执行全流程。
  2. 单元测试 :运行test目录下的TestAll,观察功能测试用例。
  3. 可视化工具 :结合H2 Console调试SQL执行计划(EXPLAIN ANALYZE)。

具体debug 过程如下:

下载源码:

TCP 模式启动H2 server

java 复制代码
public static void main(String[] args) {
        try {
            // 启动 H2 TCP 服务器
            Server server = Server.createTcpServer(
                    "-tcpPort", "9092",       // 默认端口 9092
                    "-tcpAllowOthers",        // 允许外部连接
                    "-ifNotExists",
                    "-tcpDaemon"              // 以守护线程方式运行
            ).start();

            System.out.println("H2 TCP 服务器已启动");
            System.out.println("连接 URL: jdbc:h2:tcp://localhost:9092/~/test");

            // 保持主线程运行(按 Ctrl+C 停止)
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                System.out.println("\n正在关闭 H2 服务器...");
                server.stop();
            }));

            Thread.currentThread().join(); // 阻塞主线程
        } catch (SQLException | InterruptedException e) {
            e.printStackTrace();
        }
    }

DBeaver 连上数据库

建表,插入数据

加断点, debug insert 过程


五、性能优化案例分析

场景 :高频写入导致锁争用
源码定位org.h2.table.RegularTableaddRow()方法
优化方案

// 调整批量提交策略

connection.setAutoCommit(false);

for (Row row : batch) {

table.addRow(session, row);

if (count++ % 1000 == 0) {

session.commit();

}

}

相关推荐
WIN赢1 小时前
【数据结构与算法_学习精华】
学习
姚远Oracle ACE1 小时前
解读Oracle AWR报告:Global Cache and Enqueue Services - Workload Characteristics
数据库·oracle
凤山老林1 小时前
新一代Java应用日志可视化与监控系统开源啦
java·后端·开源
流星白龙1 小时前
【Qt】7.信号和槽_connect函数用法(2)
java·数据库·qt
Zzz 小生3 小时前
Claude Code学习笔记(四)-助你快速搭建首个Python项目
大数据·数据库·elasticsearch
黎宇幻生5 小时前
Java全栈学习笔记39
java·笔记·学习
Aurorar0rua6 小时前
C Primer Plus Notes 09
java·c语言·算法
nongcunqq7 小时前
abap 操作 excel
java·数据库·excel
诸葛悠闲7 小时前
XCP协议在以太网上实现的配置
学习
rain bye bye7 小时前
calibre LVS 跑不起来 就将setup 的LVS Option connect下的 connect all nets by name 打开。
服务器·数据库·lvs