Skip to content

vinyl: fix handling of duplicate multikey entries in transaction write set#10871

Merged
sergos merged 1 commit intotarantool:masterfrom
locker:vy-tx-stmt-overwrite-multikey-fix
Dec 3, 2024
Merged

vinyl: fix handling of duplicate multikey entries in transaction write set#10871
sergos merged 1 commit intotarantool:masterfrom
locker:vy-tx-stmt-overwrite-multikey-fix

Conversation

@locker
Copy link
Member

@locker locker commented Nov 28, 2024

A multikey index stores a tuple once per each entry of the indexed array field, excluding duplicates. For example, if the array field equals {1, 3, 2, 3}, the tuple will be stored three times. Currently, when a tuple with duplicate multikey entries is inserted into a transaction write set, duplicates are overwritten as if they belonged to different statements. Actually, this is pointless: we could just as well skip them without trying to add to the write set. Besides, this may break the assumptions taken by various optimizations, resulting in anomalies. Consider the following example:

local s = box.schema.space.create('test', {engine = 'vinyl'})
s:create_index('primary')
s:create_index('secondary', {parts = {{'[2][*]', 'unsigned'}}})
s:replace({1, {10, 10}})
s:update({1}, {{'=', 2, {10}}})

It will insert the following entries to the transaction write set of the secondary index:

  1. REPLACE {10, 1} [overwritten by no.2]
  2. REPLACE {10, 1} [overwritten by no.3]
  3. DELETE {10, 1} [turned into no-op as REPLACE + DELETE]
  4. DELETE {10, 1} [overwritten by no.5]
  5. REPLACE {10, 1} [turned into no-op as DELETE + REPLACE]

(1-2 correspond to replace() and 3-5 to delete())

As a result, tuple {1, {10}} will be lost forever.

Let's fix this issue by silently skipping duplicate multikey entries added to a transaction write set. After the fix, the example above will produce the following write set entries:

  1. REPLACE{10, 1} [overwritten by no.2]
  2. DELETE{10, 1} [turned into no-op as REPLACE + DELETE]
  3. REPLACE{10, 1} [committed]

(1 corresponds to replace() and 2-3 to delete())

Closes #10869
Closes #10870

…e set

A multikey index stores a tuple once per each entry of the indexed
array field, excluding duplicates. For example, if the array field
equals {1, 3, 2, 3}, the tuple will be stored three times. Currently,
when a tuple with duplicate multikey entries is inserted into a
transaction write set, duplicates are overwritten as if they belonged
to different statements. Actually, this is pointless: we could just as
well skip them without trying to add to the write set. Besides, this
may break the assumptions taken by various optimizations, resulting in
anomalies. Consider the following example:

```lua
local s = box.schema.space.create('test', {engine = 'vinyl'})
s:create_index('primary')
s:create_index('secondary', {parts = {{'[2][*]', 'unsigned'}}})
s:replace({1, {10, 10}})
s:update({1}, {{'=', 2, {10}}})
```

It will insert the following entries to the transaction write set
of the secondary index:

 1. REPLACE {10, 1} [overwritten by no.2]
 2. REPLACE {10, 1} [overwritten by no.3]
 3. DELETE {10, 1} [turned into no-op as REPLACE + DELETE]
 4. DELETE {10, 1} [overwritten by no.5]
 5. REPLACE {10, 1} [turned into no-op as DELETE + REPLACE]

(1-2 correspond to `replace()` and 3-5 to `delete()`)

As a result, tuple {1, {10}} will be lost forever.

Let's fix this issue by silently skipping duplicate multikey entries
added to a transaction write set. After the fix, the example above
will produce the following write set entries:

 1. REPLACE{10, 1} [overwritten by no.2]
 2. DELETE{10, 1} [turned into no-op as REPLACE + DELETE]
 3. REPLACE{10, 1} [committed]

(1 corresponds to `replace()` and 2-3 to `delete()`)

Closes tarantool#10869
Closes tarantool#10870

NO_DOC=bug fix
@locker locker requested a review from a team as a code owner November 28, 2024 13:46
@coveralls
Copy link

Coverage Status

coverage: 87.33% (-0.006%) from 87.336%
when pulling 8bec478 on locker:vy-tx-stmt-overwrite-multikey-fix
into 174f7b3
on tarantool:master
.

@locker locker requested a review from nshy November 28, 2024 14:10
Copy link
Contributor

@nshy nshy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@nshy nshy assigned locker and unassigned nshy Nov 29, 2024
@sergos sergos merged commit 1869dce into tarantool:master Dec 3, 2024
@locker locker deleted the vy-tx-stmt-overwrite-multikey-fix branch December 3, 2024 10:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

5 participants