前面有人问到 H2是否支持多进程的方式, 我的回答是可以的,所以心急的小鸟同学马上就动手了,呵呵,结果自然是失败。

在h2的文档里其实明确提到多进程方式应该使用server 的模式来处理,那么我怎么还可以肯定的说h2是可以支持嵌入方式多进程的?

呵呵,其实我在看到文档里的FileLock的时候提到这个FileLock有几种模式,其中一种是No,你自己来实现文件保护。 那么也就是说在你熟悉H2的FileLock的协议以后,完全可以搞出不做fileLock的方式,这样应该就可以支持多进程了同时打开文件。 此种推断其实yy的成分比较大,因为实现难度颇大,如何做到一个进程支持写,多个进程支持读,还是很考一点功夫的。

但是,要支持多进程的读是非常简单的, h2以及h2的祖父hsqldb都支持只读模式,此种模式允许在光盘介质上运行 h2. 所以只要简单的把数据库文件的属性设置为只读就允许多个进程同时访问 h2 了。

来段测试代码

 

public static void main(String[] args) throws IOException, InterruptedException {
  String userId 
= "402880ED166CAED101166CB7032B0004";
  String tt 
= "" + System.currentTimeMillis()/1000;
  
for (int i = 0; i < 100; i++{
     UserInfo user 
= DAOUtil.getUserInfoDAO().selectByPrimaryKey(userId);
     System.out.println(tt 
+ "|" + user.getName());
     Thread.sleep(
2000);
  }

 }


把这段程序同时运行2份, 就可以看到2个进程交替的输出查询结果了。

接着继续琢磨能否做到1个读写,多个只读。
如果直接把FileLock=NO 打开,是否就可以提供多个进程的访问了? 答案是否, 因为h2采用了类似oracle那样日志机制,使用日志文件来记录数据的变化,延迟提交以提高系统性能, 如果能找到方式允许关闭日志文件(从h2提供的参数来看,是有可能做轻微修改实现这个机制的), 就有可能实现一个读写,多个只读了。

至于要做到多个读写支持,那么还要解决一个FileLock协议的问题,即如何做到即写即锁。这对不能直接操作底层的java可能有太高难度了。
 
至于SQLite的多进程模式是否也是只读的, 还是更nb的支持每个进程都做读写操作,这个我就不知道了。 但是我想后者实现难道实在太大,而且对于桌面应用来说罕有实际意义了,有空我会研究一下。


报着无聊到底的态度跑去sqlite的网站上看了一下, SQLite的多进程模式颇有点意思, 支持进程的同时读,但是同一时间只支持一个写, 使用文件系统提供的读写锁来实现。
Multiple processes can be doing a SELECT at the same time. But only one process can be making changes to the database at any moment in time, however.

不过也正如他后面指出的,这种模式效率并不高, 而且在NFS文件系统并不稳定,在WIN XP之前的win32系统更是只能使用模拟方式实现。 我看也是好玩的成分居多。

Under Win95/98/ME which lacks support for reader/writer locks, a probabilistic simulation is used instead. this locking mechanism might not work correctly if the database file is kept on an NFS filesystem

另外产生了一个怀疑, 这种读写排队操作其实是用interface来控制的, 对于都是c/c++或者tcl的进程我可以理解,但是如果是一个java进程和一个c进程的话能有效保证么? 因为java毕竟不是直接操作底层的语言,第三方实现的SQLite的jdbc能提供这种有效锁么?

SQLite实现这种奇怪模式的原因,是为了保证少量并发操作时的效率,又能保证资源占用的足够轻量,据说实际应用少并发的情况比较多。 


其实以h2 的高性能和轻量实现,对于桌面应用,这种多进程模式意义已经不大了。h2的server模式和其他轻量数据库比其实相当灵活,甚至可以在一个进程里关闭另外一个进程的服务,所以这个问题其实也没多少意义。