结果集限制行数在结果集返回给应用之前,所有记录行都已经由数据库准备好,数据库服务器目前并不支持游标,如果应用只需要结果集的前面部分行,可以通过限制结果集的尺寸提高性能,可以在查询中使用LIMIT(如:SELECT*FROMTESTLIMIT100),或者通过使用Statement.setMaxRows(max)。大结果集和外部排序大的结果集将被缓存到磁盘,阀值可以通过使用语句SETMAX_MEMORY_ROWS来设置。如果使用ORDERBY,外部排序算法将用来进行排序,在这种情况下,每块行数据使用快排序进行排序,再将其写到磁盘上,当读取数据时,块数据再被合并。大对象存储和读大对象有些数据对象可能没有存放在内存中,如CLOB(文本数据类型)和BLOB(二进制数据类型),对于这些数据类型,对象并不是被全部读入内存中,而是使用数据流(stream)。存储BLOB对象,使用PreparedStatement.setBinaryStream,存储CLOB,使用PreparedStatement.setCharacterStream,读取对象BLOB,使用ResultSet.getBinaryStream,读取CLOB对象,使用ResultSet.getCharacterStream。当使用客户端/服务器模式时,大的BLOB和CLOB对象被存储在客户端的临时文件中。使用CLOB/BLOB数据库使用单独的文件存储大对象LOB(CLOB和BLOB)。小的LOB对象就地存储,阀值通过MAX_LENGTH_INPLACE_LOB来设置,但都是通过上面的方法来使用CLOB/BLOB对象,因此BLOB和CLOB绝不要被使用在最大尺寸在200个字节以内的字段上,最好的阀值以来具体使用的案例。从就地存储的地方读取LOB比从文件要快,但是这将会使那些不包含这列的操作也会性能下降。压缩大对象CLOB和BLOB的值可以使用SETCOMPRESS_LOB来压缩。LZF算法比较快,但需要更多的磁盘空间。默认情况下,通常为了提升写操作的性能,压缩都被屏蔽掉。如果存储大量的可压缩的值,如XML、HTML、text和未压缩的二进制文件,压缩可以节省大量的存储空间(有时超过50%),甚至有时读操作也会加快。连接表数据库支持连接表,连接表就是表并不存在于当前数据库,而是存在另外一个数据库,通过一个连接名能直接访问另外一个数据库中的表。创建一张连接表,使用CREATELINKEDTABLE语句:CREATELINKEDTABLELINK('org.postgresql.Driver','jdbc:postgresql:test','sa','sa','TEST');可以按通常的方式去访问这张表,无论什么时候,被连接的表都能被访问,数据库通过JDBC发起连接表的查询,如上面的例子,如果发起查询SELECT*FROMLINKWHEREID=1,立即就发起对PostgreSQL数据库的查询:SELECT*FROMTESTWHEREID=?,同样的规则发生在插入和更新语句中,只有简单语句能使用在目标数据库,这意味这联合查询是不允许的,预编译尽可能的被使用。查询目标表上的执行语句,可以设置跟踪级别为3。如果有多个连接表指向同一个数据库(使用相同的数据库URL),数据库连接是共享的,如果要屏蔽掉,可以通过设置系统属性h2.shareLinkedConnections=false.CREATELINKEDTABLE语句支持schema名字作为一个可选的参数。事务隔离级别全部的数据库操作语句(DML)都提供了事务隔离。大多数的数据库定义语句(DDL)都是直接提交当前事务的,详细看SQL语法数据库目前支持下面的几种事务隔离级别:ReadCommitted这是默认的隔离级别,使用该级别有更好的并发性。通过使用SQL语句SETLOCK_MODE3设置该事务级别,或者通过增加;LOCK_MODE=3到数据库URL中,如:jdbc:h2:~/test;LOCK_MODE=3Serializable启用该级别,可以通过执行SQL语句SETLOCK_MODE1或者增加;LOCK_MODE=1到数据库URL中,如:jdbc:h2:~/test;LOCK_MODE=1ReadUncommitted该级别意味着事务隔离被屏蔽。启用该级别,通过执行SQL语句SETLOCK_MODE0或者增加;LOCK_MODE=0到数据库URL中,如:jdbc:h2:~/test;LOCK_MODE=0当使用隔离级别为'Serializable',脏读(DirtyReads)、不可重复读(Non-RepeatableReads)、幻影读(PhantomReads)都被禁止。DirtyReads表示一个连接能读到另一个连接未提交的数据改变可能:读到未提交的数据改变Non-RepeatableReads一个连接读了一些数据,另一个连接改变了一行数据并提交了数据,前面的那个连接重读同样的行,将得到新的结果。可能:读未提交的数据,读到后提交的数据PhantomReads一个连接根据一定的条件读到了一组数据,另一个连接插入了一行数据,这行数据恰好满足这一条件,并且该连接提交了数据,前面那个连接使用同样的查询去读数据时,将得到这个新的行。可能:读未提交的数据,读到后提交的数据表级锁数据库允许多个并发的连接访问同一个数据库,为了确保数据的一致性,默认情况下表级锁被使用。这种机制不允许搞并发性,但是却非常的快。支持共享锁和独占锁。从表读数据前,数据库将使用共享锁去锁定该表(只有该表上没有其他连接的独占锁的情况下才能锁定),如果共享锁锁定表成功,表数据就能被读,它允许其他连接在这张表上加另外的共享锁。如果一个连接要写数据到表(如更新或是删除一行),要使用独占锁去锁定这张表(只有在该表上没有其他任何锁的情况下才能锁定)。在连接提交后,所有的锁都被释放。数据库存储所有的锁在内存中。锁定超时如果连接在等待一定的时间(超时时间)后,仍然无法锁定对象,在这期间,连接持有等待锁的时间戳,在等待了一段时间后,其他连接仍然没有释放锁,该连接不能成功锁定对象,将抛出锁超时异常,锁的超时时间可以每个连接单独设置。多版本并发控制(MVCC)MVCC特性比使用锁(表级锁或行级锁)支持更高的并发,当在数据库中使用MVCC时,删除、插入和更新操作将仅适用共享锁锁定表。独占锁仍然被保留在增加、减少字段,销毁表,以及使用SELECT...FORUPDATE的情况。所有的连接仅能‘看到’已经提交的数据以及自己改变的数据,这意味着如果连接A更新了一行但是并没有提交改变,连接B只能看到老数据,仅能改变被提交后,新的值才能被其他连接可见(ReadCommitted)。如果多个连接并发的试图去更新同一行,数据库将等待直到可以应用改变,但大多数情况会锁超时。使用MVCC特性,增加;MVCC=TRUE到数据库URL中:jdbc:h2:~/test;MVCC=TRUEMVCC特性还没有完全测试,MVCC的限制为:它不能同时与MULTI_THREADED=TRUE;使用;使用MVCC时全部的UNDO日志需要设置在内存中(设置MAX_MEMORY_UNDO没有效果)。集群/高可用性数据库支持简单的集群/高可用性机制。架构是:两个数据库服务运行在两台不同的计算机上,两台计算机有同样数据库的副本,如果两个服务器都处于运行状态,每个数据库操作都被在两台计算机上执行,如果一台服务器宕机(断电、硬件故障、网络故障等),另外一台计算机仍能提供服务,从这一刻开始,数据库操作仅在一台服务器上执行,直到另外一台服务器恢复运行。集群仅能用于服务器模式(内嵌模式并不支持集群)。可以在数据库运行状态下恢复集群,但是要求在第二个数据库恢复期间没有应用在改变第一个数据库的数据,因此恢复集群是一个手工的过程。初始化集群,使用下面的步骤:创建数据库使用CreateCluster工具创建一个数据库福分到另外的地方,并且初始化集群,这样就得到了同样数据的两个数据库启动两个数据库服务(每个数据库的副本)现在可以通过应用客户端连接到数据库使用创建集群工具要了解集群如何工作,请尝试下面的例子,在这个例子里,两个数据库驻留在同一台计算机上,但通常,两个数据库在不同的计算机上。创建两个目录:server1,server2。每个目录将模拟一台计算机在第一个目录启动TCP服务,你可以运行下面的命令:javaorg.h2.tools.Server-tcp-tcpPort9101-baseDirserver1在第二个目录启动TCP服务,模拟第二个服务器(冗余运行),你能使用下面的命令:javaorg.h2.tools.Server-tcp-tcpPort9102-baseDirserver2使用CreateCluster工具初始化集群,如果数据库不存在,将创建一个新的空数据库,运行下面命令行:javaorg.h2.tools.CreateCluster-urlSourcejdbc:h2:tcp://localhost:9101/~/test-urlTargetjdbc:h2:tcp://localhost:9102/~/test-usersa-serverListlocalhost:9101,localhost:9102应用或者是H2控制台可以通过下面的JDBC的URL连接数据库:jdbc:h2:tcp://localhost:9101,localhost:9102/~/test如果你停止一个服务(通过杀进程),你注意到另一个机器继续工作,数据库仍能提供访问。恢复集群,你需要先删掉宕机的数据库,然后重启宕机的数据库的服务,再重新运行CreateCluster集群工具。检测运行状态下的集群查找哪些节点当前正在运行,通过执行下面的SQL语句:SELECTVALUEFROMINFORMATION_SCHEMA.SETTINGSWHERENAME='CLUSTER'结果返回为''(两个单引号),说明集群模式被屏蔽,否则,集群服务器列表将被单引号包括着返回,如'server1:9191,server2:9191'。集群算法和限制只读查询只在集群中的第一个节点被执行,其他操作在所有节点上都会被执行,目前为了避免事务的问题并没有使用负载均衡,下面几个方法因为处在集群中不同节点,可能执行的结果会不同:RANDOM_UUID(),SECURE_RAND(),SESSION_ID(),MEMORY_FREE(),MEMORY_USED(),CSVREAD(),CSVWRITE(),RAND()[当没有使用种子].这些方法不能直接使用在修改语句中(如INSERT,UPDATE,MERGE).然而,你能够使用它们在只读语句中,他们的结果也能用在修改语句中。两阶段提交支持两阶段提交协议,两阶段提交的工作步骤如下:自动提交需要被关闭一个事务被启动,如插入一行事务通过执行SQL语句PREPARECOMMITtransactionName被标记为准备事务可立即提交或回滚如果在事务被成功提交回滚前,一个问题发生(如网络故障),事务将被标记为‘存疑’重新连接到数据库时,存疑事务可以通过下面语句列出SELECT*FROMINFORMATION_SCHEMA.IN_DOUBT每个列出的事务在执行COMMITTRANSACTIONtransactionName或ROLLBACKTRANSACTIONtransactionName时必须被立即的提交或回滚数据库需要关闭并重新打开以应用改变兼容性数据库(更新到当前版本)兼容HSQLDB、MySQL和PostgreSQL,在一些特定的地方,H2是不兼容的。自动提交下的事务提交在H2中,在自动提交被打开的情况下,数据库引擎在结果集返回之前就已经提交了事务,也就是说,在查询中,甚至在应用扫描结果集之前,事务就已经被提交了,远在结果集被关闭之前。而在其他的数据库引擎