在Neo4j数据库中,“transaction”是什么意思?

5
我对“事务”这个术语有点困惑。 假设在事务A中,我们有两个命令C1和C2,在事务B中也是如此。 现在两个事务同时到达,那么以下观察结果是否正确?
1. 假设A先进入,则事务A的所有命令C1和C2将首先执行,然后才会执行事务B的命令。 2. 可以执行事务A或B的任何命令,但要确保如果任何一个事务的命令失败,则该事务将回滚。 3. 如果第二种情况为真,则默认情况下事务不锁定任何资源,直到完成。 4. 如果第一种情况为真,则默认情况下事务将锁定资源,直到它们完成。
谢谢
阿米特·阿加尔瓦尔
1个回答

9
我们需要谈论ACID中的"I"(Neo4j符合ACID标准),其中"I"代表"隔离性"。隔离级别告诉您,同时运行的事务中有多少数据是互相可见的。
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
1
很抱歉,目前无法使用Cypher来显式获取锁。唯一的方法是使用核心API(Java)。 - Michal Bachman
2
有点麻烦,但是您 可以 使用Cypher明确地在节点或关系上获取写锁。您可以通过在节点/关系上临时设置一个可抛弃属性来获取该锁。然后,在查询结束之前,您可以删除该可抛弃属性。 - cybersam
@mirelon,受欢迎的 Neo4j APOC 插件有一系列显式锁定过程,可以通过 Cypher 调用,如call apoc.lock.nodes([nodes])。了解更多信息,请访问 neo4j-contrib.github.io/neo4j-apoc-procedures/#_locking。 - John

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接