我們需要談談 「我」 在ACID(Neo4j的是ACID兼容),代表 「隔離」。隔離級別告訴你,同時運行事務的對方數據量有多少。
Neo4j中的默認隔離級別是「已讀提交」。這意味着A不會看到B寫入的數據,直到B提交。這是通過自動鎖定實現的,其工作原理如下:
Neo4j在您讀取它們(您可以獲取多個讀取鎖)時讀取鎖定節點和關係,並在修改節點和關係時對其進行寫入鎖定。存在寫入鎖定時無法獲取讀取鎖定,並且存在另一個寫入鎖定時無法獲取寫入鎖定。事務提交時會釋放鎖。
但是,在此隔離級別會發生一些異常情況,其中之一稱爲「丟失更新」。爲了說明,讓c爲您的計數器值(我瞭解原子計數器就是您最終的結果)。兩項交易都將計數器遞增1.
c=0
Tx1 reads c=0 (read locks c)
Tx2 reads c=0 (read locks c)
Tx1 writes c=1 (write locks c)
Tx1 commits (unlocks c)
Tx2 writes c=1 (because it thinks c is still 0, write locks c)
Tx2 commits (unlocks c)
Tx1所做的更新已丟失。
爲了防止出現這種情況,您需要在讀取當前值之前先寫入鎖定將要顯式修改的對象,從而將隔離級別更改爲「可重複讀取」。這樣,它們將不會被任何其他併發運行的事務修改。
c=0
Tx1 write locks c
Tx1 reads c=0
Tx2 tries to write lock c, has to wait
Tx1 writes c=1
Tx1 commits (unlocks c)
Tx2 write locks c (because it now can)
Tx2 reads c=1
Tx2 writes c=2
Tx2 commits (unlocks c)
希望讓事情更清楚。
任何人都知道如何做這個寫鎖定? (在Cypher查詢/ Neography中) – mirelon
恐怕現在不可能使用Cypher來顯式獲取鎖。唯一的方法就是核心API(Java)。 –
這有點麻煩,但是你可以使用Cypher來明確獲取節點或關係上的寫鎖。您可以通過在節點/關係上臨時設置一次性屬性來獲取一個。然後,在查詢結束之前,您可以刪除一次性屬性。 – cybersam