Cypher QL不执行原子查询

时间:2013-04-24 13:24:22

标签: clojure transactions neo4j cypher

我开始使用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,但是你在这里遇到了问题:在STARTSET子句之间,计数器的值发生了变化,但是cypher没有抓住它! / p>

这里有两个问题:

  • 我做错了吗?
  • Neo4j中是否有任何可行的独特计数器休息生成算法?

Neo4j版本是1.9RC1,提前感谢!

1 个答案:

答案 0 :(得分:4)

您遇到的问题是neo4j没有隐式读锁定。所以有时会发生这种情况:

  1. 查询1开始
  2. 查询1将counter值读为3
  3. 查询1将counter值设置为3 + 1 = 4
  4. 查询2开始
  5. 查询2将counter值读为4
  6. 查询2将counter值设置为4 + 1 = 5
  7. 以下是有时会发生的事情:

    1. 查询1开始
    2. 查询2开始
    3. 查询1将counter值读为3
    4. 查询2将counter值读为3
    5. 查询1将counter值设置为3 + 1 = 4
    6. 查询2将counter值设置为3 + 1 = 4
    7. 在读锁定数据库(如大多数SQL服务器)中,情况#2不可能发生。查询2将启动,然后将阻塞,直到查询1提交或回滚。

      可能有一种方法可以显式设置读锁,但不能通过REST API transaction API看起来很有希望,虽然我不完全确定它可以给你你想要的东西,但是再次,它不是通过REST支持的。