在我的項目中,我使用基於AspectJ的「高級映射」模式使用Spring Data Neo4j(3.4.2.RELEASE),使用嵌入式數據庫。 我也使用基於AspectJ的事務管理通過@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
Spring Data Neo4j:無限期等待RWLock而不發生DeadlockDetectedException
在我的應用程序中遇到死鎖情況下應該發生數據庫的併發讀取/寫入。雖然我沒有收到DeadlockDetectedException
,但卻看到一個線程無限期地等待RWLock
。不久之後,所有剩餘的線程將在第一個線程上等待並且應用程序停止響應,而不會恢復。其他線程也可能已經獲得了鎖定,但是因爲我看不到我不確定它。
堆棧跟蹤鎖定螺紋:
Thread [Processing-XXX] (Suspended)
owns: SeasonOfCompetitionRepositoryImpl (id=134)
waiting for: RWLock (id=174)
Object.wait(long) line: not available [native method]
RWLock(Object).wait() line: 502 [local variables unavailable]
RWLock.acquireWriteLock(Object) line: 388
LockManagerImpl.getWriteLock(Object, Object) line: 66
CommunityLockClient.acquireExclusive(Locks$ResourceType, long) line: 116
LockingStatementOperations.relationshipCreate(KernelStatement, int, long, long) line: 287
OperationsFacade.relationshipCreate(int, long, long) line: 866
NodeProxy.createRelationshipTo(Node, RelationshipType) line: 559
DelegatingGraphDatabase.getOrCreateRelationship(Node, Node, RelationshipType, Direction, Map<String,Object>) line: 298
Neo4jTemplate.getOrCreateRelationship(Node, Node, RelationshipType, Direction, Map<String,Object>) line: 772
RelationshipHelper.createSingleRelationship(Node, Node) line: 198
RelationshipHelper.createAddedRelationships(Node, Set<Node>) line: 154
RelatedToSingleFieldAccessorFactory$RelatedToSingleFieldAccessor(RelatedToFieldAccessor).createAddedRelationships(Node, Set<Node>) line: 78
RelatedToSingleFieldAccessorFactory$RelatedToSingleFieldAccessor.setValue(Object, Object, MappingPolicy) line: 68
NodeEntityState(DefaultEntityState<STATE>).setValue(Neo4jPersistentProperty, Object, MappingPolicy) line: 113
DetachedEntityState<STATE>.setValue(Neo4jPersistentProperty, Object, MappingPolicy) line: 181
DetachedEntityState<STATE>.setValue(Field, Object, MappingPolicy) line: 145
SeasonOfCompetition.season_aroundBody21$advice(SeasonOfCompetition, SeasonOfCompetition, Season, JoinPoint, Neo4jNodeBacking, NodeBacked, Object, AroundClosure, JoinPoint) line: 266
SeasonOfCompetition.setSeason_aroundBody22(SeasonOfCompetition, Season) line: 108
SeasonOfCompetition$AjcClosure23.run(Object[]) line: 1
AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(Object, AroundClosure) line: 66
AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation() line: 72
AnnotationTransactionAspect(TransactionAspectSupport).invokeWithinTransaction(Method, Class<?>, InvocationCallback) line: 281
AnnotationTransactionAspect(AbstractTransactionAspect).ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(Object, AroundClosure, JoinPoint$StaticPart) line: 70
SeasonOfCompetition.setSeason(Season) line: 95
SeasonOfCompetitionRepositoryImpl.getOrCreate_aroundBody0(SeasonOfCompetitionRepositoryImpl, Season, Competition) line: 32
SeasonOfCompetitionRepositoryImpl$AjcClosure1.run(Object[]) line: 1
AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(Object, AroundClosure) line: 66
AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation() line: 72
AnnotationTransactionAspect(TransactionAspectSupport).invokeWithinTransaction(Method, Class<?>, InvocationCallback) line: 281
AnnotationTransactionAspect(AbstractTransactionAspect).ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(Object, AroundClosure, JoinPoint$StaticPart) line: 70
SeasonOfCompetitionRepositoryImpl.getOrCreate(Season, Competition) line: 26
這是應該給定參數創建獨特SeasonOfCompetition
個自定義RepositoryExtension部分:
@Override
@Transactional
public synchronized SeasonOfCompetition getOrCreate(Season season, Competition competition)
{
String uri = buildUri(season, competition);
SeasonOfCompetition soc = getOrCreateByUri(uri);
if(soc.getSeason() == null)
{
soc.setSeason(season);
}
if(soc.getCompetition() == null)
{
soc.setCompetition(competition);
}
return soc;
}
請注意,我已經與@Transactional
和sychronized
- 這兩個我最初沒有使用,因爲我認爲(但不確定),他們不需要在這裏玩了一下。
這是一個選擇域實體SeasonOfCompetition
,其中螺紋卡:
@NodeEntity
public class SeasonOfCompetition extends UriEntity
{
@RelatedTo(type = "inSeason", direction = Direction.OUTGOING)
private Season season;
@Transactional
public void setSeason(Season season)
{
this.season = season;
}
}
什麼我錯在這裏做什麼?我假設通過SDN訪問圖數據庫是線程安全的,除了使用事務之外,我不需要任何特殊處理。 在這種情況下,如何調試或如何使其拋出DeadlockDetectedException
的建議也是受歡迎的。
我以前也有其他併發相關的問題(意味着是唯一的,重複的關係等重複實體),並沒有完全承認,我還需要如何處理這個問題。有關如何爲NodeEntities和Relationships實現線程安全的#getOrCreate的輸入,我們感激不盡。
編輯: 我試圖實現#getOrCreate的MERGE
-query基於版本,不使用任何自定義同步通過@cybersam的建議:
@Override
@Transactional
@SuppressWarnings("deprecation")
public T getOrCreateByUri(String uri)
{
checkArgument(!StringUtils.isEmpty(uri));
Class<T> clazz = getEntityType();
String queryString = "MERGE (n:" + clazz.getSimpleName() + " {uri: {uri}}) RETURN n";
Map<String, Object> parameters = new HashMap<>();
parameters.put("uri", uri);
Node node = (Node) template.getGraphDatabase().queryEngine().query(queryString, parameters).single().get("n");
template.postEntityCreation(node, clazz);
T result = (T) template.convert(node, clazz);
return result.persist();
}
然而,這未能創造出獨特的節點。創建100個線程並對其並行調用的簡單測試失敗,因爲創建了多個節點。 這可能與result.persist()
有關,但是如果沒有返回的實體沒有附加到圖表並且缺少一些信息。
但是,Spring Data Neo4j如何適合圖片?這是Neo4j上的一個附加層。如何在那裏實例化獨特的實體? – geld0r
請參閱本文檔的這一部分:neo4j.com/docs/stable/transactions-unique-nodes.html。 – cybersam