You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Anton Laletin (Jira)" <ji...@apache.org> on 2026/04/15 05:52:00 UTC
[jira] [Comment Edited] (IGNITE-28192) Phantom reads in RW scans
[ https://issues.apache.org/jira/browse/IGNITE-28192?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18073656#comment-18073656 ]
Anton Laletin edited comment on IGNITE-28192 at 4/15/26 5:51 AM:
-----------------------------------------------------------------
It was decided to convert this bug into a task, close it and then investigate different options to fix the issue in other tasks.
https://issues.apache.org/jira/browse/IGNITE-28547
was (Author: JIRAUSER311845):
It was decided to convert this bug into a task, close it and then investigate different options to fix the issue in other tasks.
> Phantom reads in RW scans
> -------------------------
>
> Key: IGNITE-28192
> URL: https://issues.apache.org/jira/browse/IGNITE-28192
> Project: Ignite
> Issue Type: Bug
> Reporter: Ivan Bessonov
> Assignee: Anton Laletin
> Priority: Major
> Labels: ignite-3
> Attachments: IGNITE-28192.patch
>
> Time Spent: 40m
> Remaining Estimate: 0h
>
> {{ItTableScanTest#testPhantomReads}} is flaky, with a rate of about 1% locally. I'm providing no TC link because I didn't check its state. Here I will describe how it happens:
> * Initially we have following rows in an index: {{10, 40}}.
> * Read-Write scan is started. It acquires a lock to {{10}}.
> * We do a {{"PUT 30"}} operation, let's call it {{TX_A}}.
> ** It successfully acquires a "next" side of a gap lock first. it's currently a {{40}}.
> ** It successfully acquires a "current" side of a gap lock, which is {{30}}. The gap lock is {{[40, 30]}}
> ** There's no data insertion yet.
> * Another thread does a {{"PUT 20"}} operation, let's call it {{TX_B}}.
> ** It reads the "next" side of a gap lock candidate from the index. It's {{40}}.
> * {{TX_A}} finishes.
> ** {{30}} is inserted into the index.
> ** Gap lock {{[40, 30]}} is released.
> * Scan acquires a lock {{30}}, which gives a gap lock {{[10, 30]}}.
> * {{TX_B}} acquires a lock {{40}} that it previously read.
> ** Then it acquires a lock for its own key {{20}}, forming a {{[40, 20]}} gap lock. _It does NOT re-read "next" key and doesn't reacquire a proper "next" side_ (which is {{30}}, not {{40}}).
> ** Then {{TX_B}} inserts {{20}} into the index and finishes, releasing a {{[40, 20]}} gap lock.
> * Scan finishes with acquiring a {{[30, 40]}} gap lock. Data that it has read is {{10, 30, 40}}. And {{20}} is inserted into index concurrently.
> * Second scan of the same index will return {{10, 20, 30, 40}}, giving us a phantom read of {{20}}.
> UPDATE: I don't think that {{if (!rowIdMatches(peekedRow, peekedRowAfterLock))}} is correct either, we may need to compare the payload. Let's check the design document and use common sense here.
> UPDATE 2: Information here is not 100% accurate. Insertions do release short-term locks before commit, this is not reflected in the scenario, but it should not change the outcome.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)