db4o - 线程安全、嵌入式服务器、事务...一般问题

Posted

技术标签:

【中文标题】db4o - 线程安全、嵌入式服务器、事务...一般问题【英文标题】:db4o - thread safety, embedded server, transactions...general questions 【发布时间】:2011-12-04 11:03:27 【问题描述】:

我正在努力将 db4o 集成到我的项目中,我有一些问题。我确实阅读了手册并尝试了一些示例,但我仍然不确定我是否正确理解了所有内容。请回答是/否(如果有需要这样做的问题,请选择其他答案:-))

1.) 不建议在应用程序中使用 ObjectContainer 作为 Singleton,因为如果不同的事务处理同一个对象,可能会发生冲突。

2.) 因此,对于并发事务,建议使用嵌入式服务器。

3.) 使用嵌入式服务器(本地)时,您可以根据需要打开(和关闭)任意数量的客户端,这些客户端具有自己的事务和引用缓存,以便它们可以处理相同的对象。但是 - 这仍然不是线程安全的,因为两个客户端可能在同一个对象上工作,一个客户端可能会更改它,然后另一个不会更新它。

4.) 所以 - 即使使用不同的客户端,您也需要确保客户端使用的对象始终是最新的

5.) 您可以通过回调或显式刷新来确保这一点。但是使用回调意味着大量的网络流量并且显式刷新很复杂,因为您确实需要确定何时更新哪个对象 - 那么您会推荐什么?什么时候显式刷新对象?

6.) 当我尝试为 db4o 编写 DAO 时,我将实现打开和关闭服务器以及打开和关闭客户端的方法。我猜服务器只在应用程序中打开一次,对吗? (每个应用一个服务器?)

7.) 你会推荐延迟初始化吗?这样只有第一次需要服务器时,它才会被初始化。

8.) 你会为每笔交易打开一个新客户吗?

9.) 假设我处理多个事务,但它们不能相互影响,我可以为整个项目使用一个 ObjectContainer 吗?

感谢您的回答:-)

【问题讨论】:

【参考方案1】:

    取决于应用程序。是的,每个容器都有自己的事务和引用缓存,所以对象是共享的。在一次只做一件事的桌面或移动应用程序中,这可能是所需的模型。在一个同时进行多项操作的 Web 应用程序中,这种模型很少是正确的。

    是的。你可以用container.ext().openSession()打开一个新的session container

    db4o 在对象容器/事务之间具有'read committed' 隔离。容器仅从其他事务中读取已提交的状态。但正如您所注意到的,一个容器可以看到一个过时的对象,因为他使用了该对象的本地缓存版本。你无能为力。

    是的。在这种情况下,db4o 不支持您。

    嗯,带有刷新和内容的事件不能保证您获得 100% 一致的数据视图。您无法联系到'serialized' isolation level。当涉及多个事务时,db4o 一致性模型不支持这一点。 如果您的比赛条件很少见,那么您可能只是“忽略”这个问题。它猜想在许多情况下,尝试处理/实施/接受 db4o 没有更强的隔离级别这一事实会更容易。 'refreshing' 和 'refresh on event' 之类的东西只会减少这种竞争条件的机会,但不能完全避免它们。 当您真的需要 100% 正确时,您需要一个支持“序列化”隔离的数据库。

    是的,通常您在 db4o 实例上运行,然后是多个客户端或会话容器。

    如果不是绝对必要,我不会进行延迟初始化。无论如何,当您需要数据库时,只需启动它即可。但无论如何,这真的取决于你的应用程序。

    还取决于您的应用程序。例如,在一个 web 应用程序中,我会为每个 web 会话使用一个新的会话容器。无论如何,每次你需要一个“干净”的状态时,你都应该使用一个新的对象容器。您不应该在不同的工作单元之间共享一个对象容器。并且不要跨线程共享对象容器,除非您在其之上进行了一些同步。

    每个对象容器只能有一个事务。当您同时需要多个事务时,无论如何您都需要多个容器。 当你有不同的任务一个接一个地执行时,你可以使用一个容器和同一个事务。

【讨论】:

以上是关于db4o - 线程安全、嵌入式服务器、事务...一般问题的主要内容,如果未能解决你的问题,请参考以下文章

寻找有关嵌入式 .NET 数据库(例如 db4o、NHibernate 或 RavenDB)的指导

db4o 如何保持性能

db4o 客户端/服务器似乎一次只能处理一个查询?

Sqlite 基本概念及使用概述

使用nhmicro提供的micro-datasource嵌入式的解决微服务架构中分布式事务问题

DB4O 可扩展性