本篇开始讲解BerkeleyDB的事务管理
显然,作为一个成熟的数据库产品,都必须提供事务机制来保证数据的ACID特性。我们之前讲的BerkeleyDB都没有在事务环境中进行操作。现在我们开始讲解如何使用事务,以及配置事务的各种特性。
实现一个最简单的事务系统,有几个步骤:
1.配置Environment环境支持事务
2.获取一个事务句柄
3.提交或回滚事务
File envHome = new File("E:\je");
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setTransactional(true);
Environment environment = new Environment(envHome, envConfig);
Transaction txn = null;
try {
txn = environment.beginTransaction(null, null);
doTransactionWork(txn);
txn.commit();
} catch (LockConflictException lockConflict) {
txn.abort();
}
以上是一个很简单的框架代码,你在doTransactionWork方法中的操作现在都在一个事务中了。
当然BerkeleyDB中的事务远不止这么简单,它提供了非常的属性来给你配置一个定制的事务。最重要的两个是持久性和一致性的设置
1.持久性
持久性指的是一旦事务提交给了数据库,所有的变化都应该是持久化的,即使应用程序或操作系统发生了错误。
在介绍持久性之前,我们首先讲下在默认情况下当事务提交的时候都发生了什么:
- 把提交的记录写到日志文件中。
- 把内存中的日志文件信息写到磁盘上。
- 释放这个事务所持有的锁。
这里要注意的一点是,JE中的数据时B树结构的,而事务提交的时候,只有位于B树节点的数据才会被写到日志文件中去。其他由事务引起的B树结构改变的数据时不会马上写到日志中的。这个改变只有当以下两种情况时才会写入日志:
1.Environment启动时执行正常恢复(normal recovery)
2.JE有个后台线程会周期性的进行检查点,当然你也可以手动运行检查点。
回过头来说持久性,就像之前讲的,当事务提交的时候改变被同步写到了磁盘日志上,这就保证了数据的持久性。但是有时你可能想降低这个持久性,比如说你为了性能方面的考虑,我们都知道IO操作是很慢的。这可以通过同步策略来进行设置。JE中提供了几种同步策略:
- Durability.SyncPolicy.SYNC
这是默认的,就是我们上面所讲的,提供了最高的持久性保证。
- Durability.SyncPolicy.NO_SYNC
这种策略不会让改变写到磁盘中,事务里面所发生的改变全部在JVM中,一旦JVM,应用程序或操作系统发生了错误,改变就找不到了。该策略提供的持久性保证最低,但是却能有非常好的性能。
- Durability.SyncPolicy.WRITE_NO_SYNC
这种策略会在事务提交的时候把改变写到OS文件缓存中,至于什么时候写到磁盘,是有操作系统决定的。这种策略能保证在JVM发生错误的情况下找到所有已提交的数据,但是操作系统发生错误则数据就找不到了。
持久性策略你可以在Environment级别设置,也可以在事务级别设置,在事务级别设置的策略会覆盖Environment级别的设置。
EnvironmentConfig envConfig = new EnvironmentConfig();
//设置持久性策略
Durability durability = new Durability(SyncPolicy.WRITE_NO_SYNC, null, null);
envConfig.setDurability(durability);
environment = new Environment(envHome, envConfig);
...
TransactionConfig txnConfig = new TransactionConfig();
Durability durability = new Durability(SyncPolicy.NO_SYNC, null, null);
txnConfig.setDurability(durability);
Transaction txn = null;
try {
txn = environment.beginTransaction(null, txnConfig);
doTransactionWork(txn);
txn.commit();
} catch (LockConflictException lockConflict) {
txn.abort();
}
也许有人会注意到Durability构造函数的后两个参数都为null,实际上那两个参数是在复制环境下才有用的。我们等讲到复制环境的那一节时会再次讲解它。
二.隔离性
隔离性保证了在一个事务中处理的数据不会被另外一个事务所修改。隔离性一般是与多线程有关的。JE跟其他的数据库产品一样,也提供了一系列的隔离级别,到时候我们直接选择一种用久可以了,要注意的是,隔离级别越高,所提供的隔离性越强,性能就越差。
在介绍JE中的隔离级别之前,先介绍一些术语
- 更新丢失(Lost update):两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来。
- 脏读(Dirty Reads):一个事务开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险的,因为很可能所有的操作都被回滚。
- 不可重复读(Non-repeatable Reads):一个事务对同一行数据重复读取两次,但是却得到了不同的结果。例如,在两次读取的中途,有另外一个事务对该行数据进行了修改,并提交。
- 两次更新问题(Second lost updates problem):无法重复读取的特例。有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成第一次写操作失效。
- 幻读(Phantom Reads):事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据(这里并不要求两次查询的SQL语句相同)。这是因为在两次查询过程中有另外一个事务插入数据造成的。
为了解决以上的问题,引入隔离级别的概念
级别 | 术语 | 描述 |
1 | 读未提交(Read Uncommitted) | 允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写操作,但允许其他事务读此行数据。 |
2 | 读提交(Read Committed) | 允许不可重复读取,但不允许脏读取。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。 |
(undefined) | 可重复读取(Repeatable Read) | 禁止不可重复读取和脏读取,但是有时可能出现幻影数据。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。 |
3 | 序列化(Serializable) | 提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。 |
默认情况下,JE事务是提供了可重复读取(Repeatable Read)的级别,你可以降低或提高事务的隔离级别。这些隔离级别可以在TransactionConfig中进行设置:
TransactionConfig txnConfig = new TransactionConfig();
txnConfig.setReadUncommitted(true);
txnConfig.setReadCommitted(true);
txnConfig.setSerializableIsolation(true);
其中序列化的隔离级别你还可以在Environment中设置,这样会是所有的事务默认使用序列化的级别:
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setTxnSerializableIsolation(true);
接下去我们讲一些小技巧。
自动提交
自动提交可以为你简化代码,只要你设置了事务环境,如果你没有显示的获取Transaction Handle,在你调用Database或者EntityStore进行一个单独的写操作的时候,会自动的被一个事务给包围起来并且为你执行提交或回滚。
Database myDatabase = null;
Environment myEnv = null;
try {
EnvironmentConfig myEnvConfig = new EnvironmentConfig();
myEnvConfig.setTransactional(true);
myEnv = new Environment(new File("/my/env/home"),
myEnvConfig);
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setTransactional(true);
myDatabase = myEnv.openDatabase(null,
"sampleDatabase",
dbConfig);
String keyString = "thekey";
String dataString = "thedata";
DatabaseEntry key =
new DatabaseEntry(keyString.getBytes("UTF-8"));
DatabaseEntry data =
new DatabaseEntry(dataString.getBytes("UTF-8"));
myDatabase.put(null, key, data);
} catch (DatabaseException de) {
}
要注意的是在一个时间内,你的处理线程只能有一个活动的事务,如果你混淆了显示的事务和自动提交的事务,有可能会引起死锁。
还有一点,游标是不能自动提交的。
带事务的游标
如果你使用了默认的隔离级别,那么当你使用游标每读取一条记录的时候,都会把它锁住,直到整个事务结束。这增加了锁竞争的机会,所以建议降低隔离级别,比如使用read committed。你可以设置整个事务或者事务下某个游标的隔离级别,这样可以把隔离级别应用于事务下的全部游标或者是某个游标。
//打开一个事务,使用默认的隔离级别REPEATABLE READ
Transaction txn = myEnv.beginTransaction(null, null);
Cursor cursor = null;
try {
//打开一个带有事务的游标,
//同时设置该游标使用低级的隔离级别READ UNCOMMITTED
CursorConfig cconfig = new CursorConfig();
cconfig.setReadUncommitted(true);
cursor = db.openCursor(txn, cconfig);
...
}catch (DatabaseException de) {
}
分享到:
相关推荐
在版本7.0.6中,Berkeley DB JE提供了对Java应用程序的强大支持,实现了高效的数据存储、检索以及事务处理。 **1. 关键特性** - **内存管理**:Berkeley DB JE将数据存储在内存中,可以实现极快的读写速度。同时,...
在Je-3.1.0版本中,BerkeleyDB使用特定的数据库文件格式,这些文件可以在不同平台上进行迁移,确保了跨平台的兼容性。 **7. 性能优化** BerkeleyDB提供了多种性能调优选项,如缓存大小设置、日志文件管理等,...
3. **示例和文档**:可能包含演示如何使用BerkeleyDB Java API的示例代码,以及详细说明如何配置、操作和管理数据库的文档。 4. **依赖库**:BerkeleyDB可能依赖于其他的Java库,这些库也可能包含在jar文件中或者...
伯克利数据库(Berkeley DB,简称BDB)是由Oracle公司开发的一款开源、嵌入式、键值对存储的数据库管理系统。在这个“berkeley db je-6.4.9.gz”压缩包中,包含了BDB Java Edition(JE)的6.4.9版本。这个版本的发布...
Berkeley DB je是其增强版,专为Java环境设计,提供了更高效的数据存储和管理能力。在Berkeley DB je3.3版中,我们看到了对性能、稳定性和功能的持续优化。 1. **嵌入式数据库** Berkeley DB je是一款嵌入式数据库...
Berkeley DB Java Edition (JE)是一个完全用JAVA写的,它适合于管理海量的,简单的数据。 能够高效率的处理1到1百万条记录,制约JE数据库的往往是硬件系统,而不是JE本身。 多线程支持,JE使用超时的方式来处理...
Oracle Berkeley DB Java 版是一个开源的、可嵌入的事务存储引擎,是完全用 Java 编写的。与 Oracle Berkeley DB 类似,Oracle Berkeley DB Java 版在应用程序的地址空间中执行,没有客户端/服务器通信的开销,从而...
Berkeley DB Java Edition JE 是一个完全用JAVA写的 它适合于管理海量的 简单的数据 能够高效率的处理1到1百万条记录 制约JE数据库的往往是硬件系统 而不是JE本身 多线程支持 JE使用超时的方式来处理线程间的死琐...
Berkeley DB Java Edition (JE) 是一款开源的嵌入式数据库管理系统,由Sleepycat Software开发,现归Oracle公司所有。这款数据库系统以其键值(K/V)存储模型为特色,适用于需要高性能、可伸缩性及事务处理能力的应用...
1. **事务管理**:Berkeley DB JE支持ACID(原子性、一致性、隔离性和持久性)事务,确保数据的一致性和完整性。 2. **数据复制**:通过复制功能,可以实现数据的冗余,提高系统的可用性和容错性。 3. **内存管理**...
Berkeley DB Java Edition(简称BDB JE)是一款由Oracle公司开发的高性能、轻量级的NoSQL数据库系统。它以其高效能、可扩展性和可靠性在处理大规模数据存储时受到广泛欢迎,尤其是在Google这样的大型互联网公司中,...
#### 一、Berkeley DB Java Edition (JE) 概述 Berkeley DB Java Edition (简称 JE) 是一款高性能、轻量级的NoSQL数据库解决方案,完全基于Java语言开发。它特别适用于需要高效管理大量简单数据的应用场景。 **...
Berkeley DB Java Edition(简称BDB JE)是Oracle公司推出的一款强大的、高度可定制的嵌入式数据库系统,尤其适用于Java应用程序。这款数据库引擎以其轻量级、高性能和易用性在Java企业开发领域广受欢迎。本文将深入...
**Berkeley DB Java Edition**,简称BDBJE,是由Oracle公司开发的一款高度可移植的、基于文件系统的数据存储解决方案,特别适用于需要高效、可靠且无服务器的数据管理的应用场景。这款数据库系统采用B+树作为其核心...
Berkeley DB Java Edition(简称BDB JE)是一种高性能、轻量级的嵌入式数据库系统,由Oracle公司开发,广泛应用于需要快速数据存储和检索的应用场景。它并非传统的关系型数据库管理系统(RDBMS),而是一种键值对...
Berkeley DB Java Edition (简称 BDB JE) 是专门为 Java 平台设计的版本,提供了一套完整的 Java API 来操作数据库。该版本具有以下特性: - **跨平台性**:能够在多种操作系统上运行。 - **高性能**:利用内存映射...
Berkeley DB Java Edition (JE) 是一款由Oracle公司开发的全Java实现的轻量级数据库管理系统,特别适用于处理大量简单数据。其主要特点包括: 1. **高效性能**:JE能有效处理从1到100万条记录,性能瓶颈通常在于...