知识库

共享与排他事务锁

本文档描述了事务视角下共享锁的含义以及共享锁与排他锁之间的区别。

“共享锁”指多个事务可以同时持有同一把锁,其中“同一把锁”是资源类型与资源 ID 的组合。对于 NODE 类型的资源,资源 ID 就是节点 ID 本身。因此多个事务可以共享这把锁。这与排他锁相反,排他锁在任意时刻只能被单个事务持有,因而是排他的。于是,共享锁可以有多个持有者,而排他锁只能有唯一的持有者。共享锁通常用于索引或约束的读取,可在查询规划阶段以及查询执行阶段获取。

当我们需要读取某些数据,并且同时阻止其他事务对该对象进行写入或其他形式的修改时,就会获取共享锁。

在下图中,Cypher 语句会产生共享锁。

MATCH (p:Person)
WHERE p.name = 'Tom Hanks'
set p.award= 'Oscar'

下面的代码可用于监视正在运行的另一个事务。

在一个窗口中

MATCH (p:Person)
WHERE p.name = 'Tom Hanks'
SET p.award = 'Oscar'
with p
call apoc.util.sleep(200000)
RETURN p.award

在另一个窗口中

call dbms.listTransactions() yield currentQueryId , currentQuery
with currentQueryId, currentQuery
WHERE currentQuery STARTS WITH "MATCH (p:Person)"
WITH currentQueryId
call dbms.listActiveLocks(`currentQueryId`) YIELD mode, resourceType
RETURN mode, resourceType

Shared Lock

上述 Cypher MATCH 语句会修改节点,因此会对该节点加上排他锁。SHARED LABEL 锁用于数据库的模式(schema),它们会阻止其他事务以涉及这些标签的方式修改模式,例如在 Actor 标签上创建新的唯一约束。

进一步说明

  • 如果节点或关系已经存在共享锁,则无法获取排他锁。

  • 尝试对节点进行排他锁修改的事务会等待所有已有的排他锁被释放后才能获取锁。因此锁的获取时间会影响超时行为,若在设定时间内未能获取锁会触发超时,这一超时可通过 dbms.lock.acquisition.timeout 在 neo4j.conf 中配置。

  • 在 neo4j.conf 中可通过 dbms.transaction.timeout 配置最大事务运行时长限制,届时可在指定时间范围内自动释放事务已经获取的排他锁和共享锁。

© . This site is unofficial and not affiliated with Neo4j, Inc.