2013-04-24 66 views
1

我開始使用Neo4j,並且在更新我正在閱讀的節點上的屬性時發現了一個非常糟糕的行爲。 Clojure的代碼,我寫了使用新保守派庫Neo4j的溝通:Cypher QL不會執行原子查詢

(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子句計數器的值被更改,但密碼不能捕捉它!

兩個問題在這裏:

  • 我是不是做錯了什麼?
  • Neo4j中有沒有可行的獨特的計數器休息生成算法?

Neo4j版本是1.9RC1,在此先感謝!

+1

我不懂clojure,所以忍受着我。這些多次調用'update-counter'並行發生?或者更重要的是,這些密碼查詢是否會在(大約)同時發送到服務器,而不同步等待以前的呼叫完成? – ean5533 2013-04-24 16:11:31

回答

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

這裏就是有時會發生:

  1. 查詢1開始
  2. 查詢2開始
  3. 查詢1讀取counter值3
  4. 查詢2讀取counter值3
  5. 查詢1套counter值到3 + 1 = 4
  6. 查詢2將counter值設置爲3 + 1 = 4

在讀取鎖定數據庫(像大多數SQL服務器)情況#2不會發生。查詢2將開始,然後阻塞,直到查詢1提交或回滾。

可能有一種方法可以顯式設置讀取鎖定,但不是通過REST API來設置transaction API看起來很有前途,但我不完全確定它可以給你想要的東西,而且它不再支持REST。

+0

是的,pcalls驅動並行執行功能。您已經確認了我擔心Neo4J中的默認讀取鎖定行爲。關於事務API,不幸的是我只想使用REST API(正如我在問題中所述),它不會讓用戶指定鎖和併發行爲AFAIK。你能修改答案,以便我可以接受嗎? (順便說一句,無論如何,我明顯喜歡它!) – 2013-04-29 09:16:37

+0

@VincenzoMaggio完成。對不起,你的遊行雨:( – ean5533 2013-04-29 15:13:00

+0

沒問題!我已經找到了一種可能的解決方法,用一種CAS隨機算法,我只是想知道問題是否確實沒有讀鎖系統,如果一個標準方法存在,感謝您的幫助! – 2013-04-30 11:50:25