2014-10-01 32 views
21

TL; DR:我要麼失去了我的想法,要麼neo4j的交易略有破裂。看起來好像未提交的節點在提交的事務之外可用,並且缺少屬性 - 或者同樣奇怪的東西。neo4j的密碼交易是否被破壞?

我們的node.js應用程序使用neo4j。它的一部分必須生成唯一的ID。我們有以下密碼查詢,用於查找最後的:Id類型節點,並嘗試提交一個新的:Id節點和last_uuid+1

MATCH (i:Id) WITH i ORDER BY i.uuid DESC LIMIT 1 #with it like a sub-return, will "run" the rest with the last i at read-time 
CREATE (n:Id {label:"Test"}) 
SET n.uuid = i.uuid + 1 
RETURN n 

還有一個約束:

neo4j-sh (?)$ schema 
Indexes 
    ON :Id(uuid) ONLINE (for uniqueness constraint) 

Constraints 
    ON (id:Id) ASSERT id.uuid IS UNIQUE 

和DB與一個(:Id{uuid:1})初始化來啓動這個喜悅。

應用程序代碼基本上重試上述查詢,直到它成功。如果同時創建兩個或更多個ID創建請求,則只有其中一個會通過,剩下的會失敗並被應用程序代碼重試。

這工作,直到我們並行地嘗試它。

代碼開始返回沒有uuid的數據。經過大量調查後,事實證明,查詢的寫入部分(CREATE ...)以某種方式從MATCH接收到一個ID,它沒有.uuid(或其他)屬性。這應該是不可能的。這是在這些節點上運行的唯一代碼。

最奇怪的(也許)的事情是,如果我救inodeid,以找到在數據庫節點,它確實存在有.uuid屬性。

爲了隔離這種行爲,我寫了一個PoC:neo4j-transaction-test使用nodejs運行應該非常簡單。

它基本上比上面的代碼稍微有點 - 嘗試創建Id,將prev_label,prev_nodeidprev_uuid設置爲之前的Node(i)值。它運行的每一個查詢GET請求接收到在localhost:9339和輸出:

> node server.js 
* 1412125626667 Listening on 9339 
Req Id | Datetime | -> $uuid $nodeid 
1 1412125631677 'GET'  # When it first receives the GET request 
1 1412125631710 '->' 9 60 # When neo4j returns; numbers are $uuid $node_id) 

時,事情開始變得併發,查詢可能會失敗:

3 1412125777096 '(retry) (0)' 'Node 64 already exists with label Id and property "uuid"=[13]' 
4 1412125777098 '(retry) (0)' 'Node 64 already exists with label Id and property "uuid"=[13]' 
de[] 

這是可以預料的,他們是重試。如果我們「SLAM」一對夫婦每秒(ab -n 1000 -c 10 http://localhost:9339/)REQ的服務器,我們最終會看到:

... 
59 1412127103011 'GET' 
23 1412127103024 'ERROR - EMPTY UUID' '{"this_nodeid":22,"prev_nodeid":20,"label":"Test"}' 

Error: Empty UUID received 

(和最終,我的意思是幾乎瞬間)節點回來,沒有UUID,prev_uuid或prev_label。 this_nodeid和prev_nodeid是指neo4j的內部ID。如果我們看一下這些了,從以前的(i)標識節點(由NODEID - 20):

neo4j-sh (?)$ match (i) where id(i)=20 return i; 
+--------------------------------------------------------------------------------------------+ 
| i                       | 
+--------------------------------------------------------------------------------------------+ 
| Node[20]{uuid:10,label:"Test",prev_label:"Test",prev_uuid:9,prev_nodeid:17,this_nodeid:20} | 
+--------------------------------------------------------------------------------------------+ 
1 row 
19 ms 

正是因爲它應該是。 .uuid和所有。新的確實就像上面返回的那樣創建:

neo4j-sh (?)$ match (i) where id(i)=22 return i; 
+------------------------------------------------------+ 
| i             | 
+------------------------------------------------------+ 
| Node[22]{label:"Test",prev_nodeid:20,this_nodeid:22} | 
+------------------------------------------------------+ 
1 row 
17 ms 

沒有prev_label或prev_uuid。這怎麼可能?我錯過了什麼?是不完整的:Id節點泄漏到我的查詢中?

我已經嘗試重新啓動,擦除數據目錄,擦除數據目錄後重新啓動,清除日誌(沒有什麼有趣的,甚至無聊,但在正確的時間 - 當上述情況發生時)。我現在正在質疑我對如何工作的理解。

這是在12.04與neo4j 2.1.1。 More Version InfoNeo4j startup/shutdown logs

我知道這不是創建UUID的最佳方式。這個問題是關於如果neo4j的交易如預期那樣工作,那麼這些結果是可能的。

+0

我明白這一點。如果我們堅持使用neo4j(不太可能),那麼ID生成代碼將被移出數據庫。我仍然想知道我是如何看到這個結果的 - 它表明有些事情被打斷了。 – 2014-10-01 15:00:50

+3

而不是創建你有使用合併(上鎖)?你是否也可以將Neo4J Node.js代碼取出並嘗試直接敲擊事務端點來排除該問題(http://docs.neo4j.org/chunked/stable/rest-api-transactional.html),因爲我認爲這是特別的(非官方)節點庫擊中傳統端點(您的Neo是新的,您的節點不是)。您也可以看到原始響應。 – JohnMark13 2014-10-03 20:18:15

+0

@TasosBitsios有沒有解決這個問題? – JohnMark13 2014-10-10 09:08:34

回答

1

在併發事務寫入期間,我們注意到了Neo4J中的類似問題,並且在Neo4J 2.2.5中引入了一個解決此問題的解決方案(我們有企業支持並提出了一張解決此問題的方案)。你可能沒有完全相同的問題,但可能值得再次嘗試使用2.2.5來查看它是否仍然是一個問題。

就像你說的,有更好的方法來生成id。此外,你應該使用MAX獲取最新的,而不是LIMITORDER BY,但除此之外,還;-)。

祝你好運。