在一个辅助项目中,我正在研究用于存储树木的基于图形的数据库。 存储和阅读它们并不是一个大问题(并不奇怪),但现在看来我已陷入死胡同。 树将由网页存储和读取,因此两者可能同时发生。现在,由于写入事务是一种常见功能,因此几个存储过程不会相互干扰。
另一方面,如果在另一个进程遍历节点时提交了写事务,则结果将是错误的。
例如,让我们说一个人用树打开网页,编辑它并提交更改。与此同时,其他人打开页面,以便在提交过程中从数据库中读取它。
为了从数据库中读取树,我首先遍历节点深度,然后从结果中构建一个json对象。所以有时会发生这样的情况:如果一个节点从一个分支移动到另一个分支,它会被读取两次,因为它是在旧位置读取的,并且当读取进程到达新位置时,提交已经发生。
我现在正在使用OrientDB,但尚未找到解决方案。 Java API和Tinkerpop Gremlin都是单次调用执行遍历,因此我没有理由相信服务器会锁定数据。从我读到的内容同样适用于ArrangoDb,并且在Neo4j的文档中它明确地说:"遍历检索的数据不受其他事务的修改保护。" (http://neo4j.com/docs/stable/transactions.html)
这是图形数据库的一般问题还是我错误地使用了数据库? 对于OrientDb,我可能会尝试使用SQL语法,但我没有理由相信这会解决问题。
答案 0 :(得分:2)
在这里只谈到Neo4j,不能对其他人发表评论:一个事务可以在另一个事务遍历同一区域时修改图形。但有一种方法可以防止这种情况:抓住明确的锁定。
Transaction
接口包含获取锁的方法。如果执行遍历的事务采用锁定,则会阻止对这些事务的并发写入。
Cypher(neo4j查询语言)无法明确获取锁定。建议的解决方法是设置一个假的属性并最终将其删除 - 作为副作用,我们将保持锁定:
MATCH (n:Person {name:'myself'})
SET n._fake = 1
WITH n
.... do more stuff
REMOVE n._fake
RETURN <whateverresult>