ObjectBox[十一] 事务

ObjectBox[一] 特性

ObjectBox[二] 教程:如何开始使用ObjectBox

ObjectBox[三] 教程:安装和基础

ObjectBox[四] 数据库持久化之实体注解

ObjectBox[五] 基本操作:查询

ObjectBox[六] 数据监听和RX(Data Observers and Reactive Extensions)

ObjectBox[七] 支持LiveData(Android体系结构组件)

ObjectBox[八] 关系

ObjectBox[九] 数据模型变更

ObjectBox[十] 自定义类型

ObjectBox[十一] 事务

ObjectBox[十二] Meta Model, IDs, and UIDs

ObjectBox[十三] 数据调试

ObjectBox是事务完全满足ACID属性的数据库。一个事务可以把几个操作分成一个单独的工作单元,要么一起执行,要么全不执行。如果您正在寻找更详细的事务资料,请参考Wikipedia on database transactions.。对于ObjectBox事务,请继续阅读:

您可能没有注意到,几乎所有ObjectBox的操作都涉及事务。如果你调用put方法,会使用一个写事务。另外,如果您调用getQuery,则会使用读事务。所有这些都是在底层封装,对你来说是透明的。完全忽略事务,也不会遇到问题。然而,对于更复杂的应用,通常值得学习事务的知识,以使您的应用程序更加的高效。

显式事务

现在我们知道ObjectBox操作都在隐式事务中运行,除非你使用显式事务。在后一种情况下,多个操作共享(显式)事务。换句话说,可以通过显式事务来控制事务边界。这样做可以大大提高您的应用程序的效率和一致性。

BoxStore类 提供以下方法来执行显式事务:

  • runInTx:在事务内运行runnable
  • runInReadTx:在只读事务中运行runnable 。与写入事务不同,多个读取事务可以同时运行。
  • runInTxAsync将给定的Runnable作为单独线程中的事务运行。一旦事务完成,给定的callback 被调用(回调可能为空)。
  • callInTx: 类似runInTx, 支持一个返回值和异常抛出。

显式交易相对于批量put 操作的优点是,您可以使用多个Box执行任意数量的操作,并且在事务处理过程中,您可以获得一致的(事务处理)的数据。

写入事务的示例:

boxStore.runInTx(() -> {
   for(User user: allUsers) {
     if(modify(user)) box.put(user);
     else box.remove(user);
   }
});
事务成本

了解事务对于掌握数据库性能至关重要。如果你只记得关于这个话题的一句话,那就应该是这样的:写事务是有代价的。
提交事务包括将数据同步到物理存储,这对于数据库来说是相对昂贵的操作。只有当文件系统确认所有的数据已经以持久的方式存储(不仅仅是内存缓存)时,交易才算成功。事务所需的文件同步可能需要几毫秒。记住这一点,并尝试将若干个操作(例如 多次put )运行在一个事务中。

看看这段代码:

for(User user: allUsers) {
   modify(user); // modifies properties of given user
   box.put(user);
}

这段代码有什么问题吗?对每个用户来说都有一个隐含的事务,对于大量的对象来说效率非常低。使用put重载来同时存储所有的用户会更高效:

for(User user: allUsers) {
   modify(user); // modifies properties of given user
}
box.put(allUsers);

好多了!如果您有1,000个用户,则后一个示例使用单个事务来存储所有用户。第一个代码示例使用1,000个隐式事务,导致速度非常慢。

读事务

在ObjectBox中,读取操作速度很快。与写入事务相反,没有提交,因此不会对文件系统进行昂贵的同步。像getcountqueries 这样的操作 ,如果它们不是在一个显式事务(读或写)中的话,那就会在隐式读事务中运行。请注意, 在读事务中调用put 是非法的 :将抛出异常。

虽然读事务比写事务快得多,但是开始读事务还是有一些开销。因此,对于大量读取(例如循环中的数百个),可以通过将这些读取分组在单个读取事务中来提高性能(参见下面的显式事务)。

多版本并发

ObjectBox为开发人员提供 Multiversion并发控制(MVCC) 语义。这允许多个并发读取器(读取事务),其可以立即执行而不会阻塞或等待。这是通过MVCC保证的。即使正在进行写入事务,读取事务也可以立即读取上次一致的状态。写事务按顺序执行以确保一致的状态。因此,建议尽量减少写入操作,以避免阻塞其他未完成的写入操作。例如,在写事务内部进行联网或复杂的计算通常是一个糟糕的主意。所以,复杂的操作需要在写事务之前进行。

写事务内部锁

尽量避免在写事务中使用同步锁(e.g. via synchronized or java.util.concurrent.locks)
由于写事务在单独的线程,因此它们在内部有效地获取写锁
(Because write transactions run exclusively, they effectively acquire a write lock internally)。
与所有的锁一样,当涉及多个锁时,您需要密切关注。始终以相同的顺序获取锁以避免死锁。如果您在事务内部获得锁定X”,则必须确保您的代码“X”锁时不会启动另一个写入事务。


原文:http://objectbox.io/documentation/transactions/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值