Visitar URL original
Concurrent delete of a lightweight edge read through a stale edge list can be lost (follow-up of #10263) · Issue #10302 · ArcadeData/arcadedb · GitHub
Skip to content

Concurrent delete of a lightweight edge read through a stale edge list can be lost (follow-up of #10263) #10302

Closed

Description

@robfrank

Follow-up of #10263, left out of its fix on purpose.

#10263 makes an edge delete that finds no entry to remove, in the list the transaction reads, check the committed list too: when the committed list holds the entry, the transaction's view was stale (its own copy of a head chunk, or of the vertex, from before a concurrent commit appended the entry) and the delete is refused with a retryable ConcurrentModificationException instead of committing while the entry survives.

That check is skipped for lightweight edges (GraphEngine.disconnectEndpoint): a lightweight edge has no RID, it is located by (edge type bucket, neighbour), and its twins - several lightweight edges of one type to the same neighbour - are indistinguishable. An occurrence in the committed list can be one this very transaction has already removed (the striped twins case in Issue10008ParallelLightEdgeValueOpsTest.twinsOnAStripedSuperNode deletes three twins in one transaction and would be refused).

What is left: under the same window as #10263 (transaction T2 holds a stale copy of the list, T1 commits a lightweight edge into it, T2 deletes that lightweight edge), T2's removal finds nothing and T2 commits. There is no record to dangle and no RID to reuse, so the symptom is a lost delete (one lightweight edge too many), not the wrong-edge or duplicate shapes of #10263.

A fix needs to count: occurrences in the committed list versus occurrences in the transaction's list plus those the transaction removed itself, per (type bucket, neighbour).

Activity

  1. added
    concurrencyThreading / concurrency / MVCC
    engineCore engine: document/schema API
    on Oct 18, 2026
  2. added this to the 26.11.1 milestone on Oct 18, 2026
  3. self-assigned this
    on Oct 18, 2026
  4. added a commit that references this issue on Oct 18, 2026
  5. robfrank commented on Oct 18, 2026

    @robfrank
    CollaboratorAuthor

    Fixed in #10316. A transaction that deleted a lightweight edge after reading an outdated edge list could find nothing to delete and carry on, so the delete was lost. Now, when the delete finds no matching entry, the server compares how many such edges the committed list holds with how many this transaction removed itself. If the committed list holds more, the transaction fails with a retryable ConcurrentModificationException instead of losing the delete.

    Still open:


    ❤️ Thanks for helping make ArcadeDB better! ArcadeDB is free and open source, sustained by its community. If it's useful to you or your company, please consider becoming a sponsor to keep development going.

  6. removed
    in progressThe team is actively working on this issue
    on Oct 18, 2026
  7. tae898 commented on Oct 18, 2026

    @tae898
    Contributor

    Verified on the merge commit 0762d99b16 of #10316: fixed. CI-built jars, embedded, eclipse-temurin 25 (-XX:+UseCompactObjectHeaders): Repro10302.java (from my pre-verification on #10316) has delete() of the lightweight edge refused with the retryable ConcurrentModificationException, the edge kept (OUT 1 IN 1). On the same commit #10304's case stays fixed, and my #10263 workloads stay clean: EdgeListCrossDelete.java seeds 1 to 40, 0 runs with a wrong edge list; the 2-thread workload at 40 vertices, seeds 1 to 90, 0 bad runs.

  8. added a commit that references this issue on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugconcurrencyThreading / concurrency / MVCCengineCore engine: document/schema APIseverity:minorCosmetic, documentation, edge case, or a workaround exists

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions