[ 
https://issues.apache.org/jira/browse/CASSANDRA-21854?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Caleb Rackliffe updated CASSANDRA-21854:
----------------------------------------
     Bug Category: Parent values: Correctness(12982)Level 1 values: 
Unrecoverable Corruption / Loss(13161)
       Complexity: Normal
    Discovered By: Code Inspection
    Fix Version/s: 5.0.x
                   6.0.x
                   7.x
         Severity: Critical
           Status: Open  (was: Triage Needed)

> SAI vector index corruption when an insert is interrupted at the new 
> graph-insert permit wait
> ---------------------------------------------------------------------------------------------
>
>                 Key: CASSANDRA-21854
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-21854
>             Project: Apache Cassandra
>          Issue Type: Bug
>          Components: Feature/SAI, Feature/Vector Search
>            Reporter: Caleb Rackliffe
>            Assignee: Sunil Ramchandra Pawar
>            Priority: Normal
>             Fix For: 5.0.x, 6.0.x, 7.x
>
>
> h2. Summary
> Commit 
> [{{bf06dbd}}|https://github.com/cscotta/cassandra/commit/bf06dbdd9aafb6b1d4ef17f1e06ec2b720d40d2b]
>  bounds concurrent SAI graph inserts with a semaphore. {{OnHeapGraph.add}} 
> now registers the vector and ordinal before it waits for a permit. An 
> interrupt during that wait corrupts the memtable index permanently.
> {{{}postingsMap.putIfAbsent{}}}, the ordinal assignment, 
> {{{}vectorValues.add{}}}, and {{postingsByOrdinal.put}} all run before 
> {{{}graphInsertPermits.acquireThrowUncheckedOnInterrupt(1){}}}. The thrown 
> {{UncheckedInterruptedException}} lands before the {{{}try{}}}block. No 
> rollback runs, so the vector stays registered and the graph node never gets 
> linked.
> h2. Trigger conditions
>  # A table has a Storage-Attached Index vector index on a memtable-backed 
> index.
>  # Concurrent inserts exceed {{{}MAX_CONCURRENT_GRAPH_INSERTS{}}}, or the 
> memtable reports {{{}limitsConcurrentWritesTo{}}}.
>  # A writer thread receives an interrupt while it waits for a graph-insert 
> permit.
> h2. Failure scenario
> The interrupted writer throws {{UncheckedInterruptedException}} and abandons 
> the insert. {{vectorValues}} and {{{}postingsByOrdinal{}}}keep the ordinal. 
> {{graph.size()}} stays 0. A retry of the same row only updates the postings 
> list. It never calls {{{}builder.addGraphNode{}}}, so nothing repairs the 
> graph.
> At flush time, {{OnHeapGraph.writeData}} asserts {{nextOrdinal == 
> builder.getGraph().size()}} and fails. With assertions disabled, the index 
> stays silent and vector searches return no results for that vector.
> h2. Reproducer
> Path: 
> {{~/.local/share/cassandra-watch/reports/reproducers/bf06dbdd9aaf/InterruptPermitUnlinkedNodeRepro.java}}
>  (executed against a full patched build with {{{}-ea{}}}).
> Observed output on 
> [{{bf06dbd}}|https://github.com/cscotta/cassandra/commit/bf06dbdd9aafb6b1d4ef17f1e06ec2b720d40d2b]:
>  the interrupted {{add()}} throws. {{{}vectorValues.size()==1{}}}. 
> {{{}graph.size()==0{}}}. The retry succeeds but does not link the node. 
> Vector search returns 0 results. The flush invariant fails.
> On parent 
> [{{b40e292}}|https://github.com/cscotta/cassandra/commit/b40e29225c50c96f10c4836d68d37174204cddd6]
>  the same interrupt path cannot occur. The parent has no blocking wait 
> between registration and {{{}addGraphNode{}}}.
> h2. Proposed resolution
> Acquire the permit before the ordinal assignment and registration, or roll 
> back the registration when {{acquireThrowUncheckedOnInterrupt}} throws. 
> Alternatively, add a failure path that unregisters the ordinal and the 
> postings entry.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to