`
zhan8610189
  • 浏览: 75354 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

h2 sql引擎实现及其源代码学习

阅读更多

引言

在java语言里访问数据库一般是通过jdbc去访问,jdbc一般用于客户端去联接数据库,并且把相应的sql语句传给数据库服务器,服务器接收到sql请求就开始分发给sql执行引擎解析sql并执行相应任务,在服务器端执行完得到的结果(对于那些更改操作没有相关结果)传输给对应的客户端。
通常情况下,我们经常去编写jdbc客户端,看如何建立连接与服务器交互。如果我们也需要在服务端建立类似mysql一样的sql引擎,使得客户端直接采用类似jdbc的方式去与服务端提交标准sql,最后完成相应的执行任务。
在java中,已经有相关的开源产品来完成这样类似的任务的。其中就有一个sql 引擎h2 就引人注目。该项目的源代码是在sourceforge上可以下载,采用的语言是java,它已经完成了整套sql执行过程流程,只需要你去完成相应的逻辑代码,就能搭建一套完备的sql执行服务器。
同样,对于mysql的java jdbc实现有相应的jar,在开源社区也有相应的jdbc规范实现SqlLine,只需要向其提供h2的驱动客户端就能够访问h2 sql引擎。

h2代码结构

查看源码,可以看到四个重要的package,其中:

  1. org.h2.jdbc包实现java jdbc的一系列接口,并且提供相应的jdbc驱动org.h2.Driver供java客户端来使用;
  2. org.h2.server包是h2 sql引擎的服务端实现代码。接收sql请求并解析,最后执行相应DDL,DML操作;
  3. org.h2.ddl和org.h2.dml包是各种sql命令的执行逻辑实现。如果需要对某种特定的sql类型个性化,那么可以修改这两个包下面对应的执行类。
 

h2引擎分析

h2构建sql执行引擎服务器,就需要在服务器端监听相应的sql请求。h2服务器的启动类是org.h2.tools.Server,这里面会产生一个org.h2.server.TcpServer对象用于创建相应的监听线程,不断地去接收外来相关请求。
public void listen() {
        listenerThread = Thread.currentThread();
        String threadName = listenerThread.getName();
        try {
            while (!stop) {   //不断接收客户端的sql请求
                Socket s = serverSocket.accept(); //接收外来的sql请求
                TcpServerThread c = new TcpServerThread(s, this, nextThreadId++); 产生一个TcpServerThread Runnable类对象
                running.add(c);
                Thread thread = new Thread(c, threadName + " thread");  //另外创建一个线程去处理sql请求
                thread.setDaemon(isDaemon);
                c.setThread(thread);
                thread.start();   //新线程TcpServerThread正式运行,初始化客户端传过来的连接信息,及循环通过org.h2.server.TcpServerThread.process()方法根据不同的sql请求类型(例如:update,select,或其它请求类型)去处理sql语句及请求。
            }
            serverSocket = NetUtils.closeSilently(serverSocket);
        } catch (Exception e) {
            if (!stop) {
                TraceSystem.traceThrowable(e);
            }
        }
        stopManagementDb();
    }

sql主要分为两大类:1. DDL(例如create表,alter表); 2. DML(例如select表,update表)。每个大类里面也有许多较小的类型。根据不同的类型就走不同的分支代码,例如查询、更新等操作,类型代码在org.h2.engine.SessionRemote类中。最终,不同的类型会产生一个对应的org.h2.command.Command对象,进行相应的操作。因此,如果要修改某个sql类型的执行逻辑,我们只需要在对应的Command类中进行修改。把sql语句转变成Command对象,这需要一个过程,包括解析(parse)sql,最终产生一个Command的继承类org.h2.command.CommandContainer对象。

 

我们将以DDL或者DML中的create/update等操作时的代码逻辑如下:

 

            if (commit == null) {
                commit = session.prepareLocal("COMMIT");  //做好相关准备工作(包括解析sql,生成一个org.h2.command.Prepared对象,最后把他们封装成CommandContainer对象)
            }
            int old = session.getModificationId();
            commit.executeUpdate();  // 执行相应的command

 

 

其它

如果需要了解h2的运行流程及client与server端的通信协议,可以参考这篇文章:https://github.com/codefollower/H2-Research/blob/master/docs/协议实现分析/H2数据库client-server协议全解.java
 
  • 大小: 36.5 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics