【问题标题】:Is it possible to perform a graph traversal in a graph database in one atomic step?是否可以在一个原子步骤中在图形数据库中执行图形遍历?
【发布时间】:2015-10-17 20:05:15
【问题描述】:

在一个附带项目中,我正在研究用于存储树的基于图形的数据库。 存储和阅读它们并不是什么大问题(不足为奇),但现在我似乎陷入了死胡同。 这些树将由网页存储和读取,因此两者可能同时发生。现在多个存储进程不会相互干扰,因为写入事务是一个共同的特性。

另一方面,如果在另一个进程遍历节点时提交了一个写事务,则结果将是错误的。

例如,假设一个人打开带有树的网页,对其进行编辑并提交更改。同时,其他人打开该页面,以便在提交发生时从数据库中读取该页面。

为了从数据库中读取树,我首先遍历节点深度并根据结果构建一个 json 对象。所以有时会发生这样的情况,如果一个节点从一个分支移动到另一个分支,它会被读取两次,因为它是在旧位置读取的,当读取过程到达新位置时,提交已经发生。

我现在正在使用 OrientDB,但还没有找到解决方案。 Java API 和 Tinkerpop Gremlin 都将遍历作为单个调用执行,因此我认为没有任何理由相信服务器会锁定数据。从我读到的同样适用于 ArrangoDb,在 Neo4j 的文档中,它明确表示:“通过遍历检索的数据不受其他事务修改的保护。” (http://neo4j.com/docs/stable/transactions.html)

这是图形数据库的普遍问题,还是我错误地使用了数据库? 对于 OrientDb,我可能会尝试使用 SQL 语法,但我认为没有任何理由相信这会解决问题。

【问题讨论】:

    标签: transactions neo4j orientdb graph-databases arangodb


    【解决方案1】:

    这里只说 Neo4j,不能评论别人:一个事务可以修改图,而另一个事务正在遍历同一区域。但是有一种方法可以防止这种情况发生:获取显式锁。

    Transaction 接口包含获取锁的方法。如果执行遍历的事务需要锁,它将阻止对这些的并发写入。

    Cypher(neo4j 查询语言)无法显式获取锁。推荐的解决方法是设置一个假属性并最终将其删除 - 作为副作用,我们将持有一个锁:

    MATCH (n:Person {name:'myself'})
    SET n._fake = 1
    WITH n
    ....  do more stuff
    REMOVE n._fake
    RETURN <whateverresult>
    

    【讨论】:

    • 有趣。因此,为了创建读锁,您改为在要访问的节点组唯一的实体上生成写锁。所以在我的情况下,我可能会在树的根节点上设置一些虚拟值,以便我的读取遍历包含在写入事务中。我看到的唯一缺点是这也不允许并发读取,对吗?再想一想 - 由于 OrientDB 和 ArangoDB 都具有 MVCC,因此启动事务并在开始时获取这样的“假”写锁就足够了,然后永远不要提交不必要的更改。我去看看。
    猜你喜欢
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多