我开始使用Neo4j,我注意到在同一时刻更新我正在阅读的节点上的属性时出现了非常糟糕的行为。我编写的clojure代码使用Neocons库与Neo4j进行通信:
(ns ams.utils.t.test-cypher-error
(:require [clojurewerkz.neocons.rest :as rest]
[clojurewerkz.neocons.rest.nodes :as nodes]
[clojurewerkz.neocons.rest.cypher :as cypher]))
(rest/connect! "http://192.168.0.101:7474/db/data")
(def counter-id (:id (nodes/create {:counter 0})))
(defn update-counter [] (cypher/query "START c = node({id}) SET c.counter = c.counter + 1 RETURN c.counter as counter" {"id" counter-id}))
(doall (apply pcalls (repeat 10 update-counter)))
(println "Counter:" ((comp :counter :data) (nodes/get counter-id)))
(nodes/destroy counter-id)
猜猜结果:
Counter: 4
有时是5,有时是4,但是你在这里遇到了问题:在START
和SET
子句之间,计数器的值发生了变化,但是cypher没有抓住它! / p>
这里有两个问题:
Neo4j版本是1.9RC1,提前感谢!
答案 0 :(得分:4)
您遇到的问题是neo4j没有隐式读锁定。所以有时会发生这种情况:
counter
值读为3 counter
值设置为3 + 1 = 4 counter
值读为4 counter
值设置为4 + 1 = 5 以下是有时会发生的事情:
counter
值读为3 counter
值读为3 counter
值设置为3 + 1 = 4 counter
值设置为3 + 1 = 4 在读锁定数据库(如大多数SQL服务器)中,情况#2不可能发生。查询2将启动,然后将阻塞,直到查询1提交或回滚。
可能有一种方法可以显式设置读锁,但不能通过REST API 。 transaction API看起来很有希望,虽然我不完全确定它可以给你你想要的东西,但是再次,它不是通过REST支持的。