From dade56acffb3df816cf5a2da4cd0c7b696dd9105 Mon Sep 17 00:00:00 2001 From: Aleksandr Lyapunov <alyapunov@tarantool.org> Date: Mon, 26 Jul 2021 16:10:43 +0300 Subject: [PATCH] txm: track deleted stories In order to preserve repeated reads transactional manager tracks read of each transactions. Generally reads can be of two types - those that have read a tuple or that have found nothing. The first are stored in tuple story, the second - in special gap and hole structures. The problem was that reads that found a dirty tuple that was invisible to this transaction (the story says that it is deleted) was not stored neither in story nor in gap/holes. This patch fixes that. Part of #6206 --- src/box/memtx_tx.c | 14 ++++++--- test/box/tx_man.result | 61 ++++++++++++++++++++++++++++++++++++++++ test/box/tx_man.test.lua | 20 +++++++++++++ 3 files changed, 91 insertions(+), 4 deletions(-) diff --git a/src/box/memtx_tx.c b/src/box/memtx_tx.c index 8c4bc242f7..669640d344 100644 --- a/src/box/memtx_tx.c +++ b/src/box/memtx_tx.c @@ -1264,8 +1264,10 @@ memtx_tx_handle_gap_write(struct txn *txn, struct space *space, struct key_def *def = index->def->key_def; hint_t oh = def->key_hint(item->key, item->part_count, def); hint_t kh = def->tuple_hint(tuple, def); - int cmp = def->tuple_compare_with_key(tuple, kh, item->key, - def->part_count, oh, def); + int cmp = def->tuple_compare_with_key(tuple, kh, + item->key, + item->part_count, + oh, def); int dir = iterator_direction(item->type); if (cmp == 0 && (item->type == ITER_EQ || item->type == ITER_REQ || @@ -1785,6 +1787,10 @@ memtx_tx_history_commit_stmt(struct txn_stmt *stmt) return res; } +static int +memtx_tx_track_read_story(struct txn *txn, struct space *space, + struct memtx_story *story); + struct tuple * memtx_tx_tuple_clarify_slow(struct txn *txn, struct space *space, struct tuple *tuple, struct index *index, @@ -1810,8 +1816,8 @@ memtx_tx_tuple_clarify_slow(struct txn *txn, struct space *space, if (story == NULL) break; } - if (!own_change && result != NULL) - memtx_tx_track_read(txn, space, result); + if (!own_change && story != NULL) + memtx_tx_track_read_story(txn, space, story); if (mk_index != 0) { assert(false); /* TODO: multiindex */ panic("multikey indexes are not supported int TX manager"); diff --git a/test/box/tx_man.result b/test/box/tx_man.result index 49c53f0971..e6a83ada27 100644 --- a/test/box/tx_man.result +++ b/test/box/tx_man.result @@ -3098,6 +3098,67 @@ s:drop() | --- | ... +--https://github.com/tarantool/tarantool/issues/6206 +spc = box.schema.space.create('test') + | --- + | ... +_ = spc:create_index('test', {type='tree'}) + | --- + | ... + +tx1:begin() + | --- + | - + | ... +tx1('spc:select{}') + | --- + | - - [] + | ... +spc:replace{1, 1} + | --- + | - [1, 1] + | ... +tx1('spc:select{}') + | --- + | - - [] + | ... +tx1:commit() + | --- + | - + | ... + +spc:delete{1} + | --- + | - [1, 1] + | ... +tx2 = txn_proxy.new() + | --- + | ... +tx2:begin() + | --- + | - + | ... +tx2('spc:select{}') + | --- + | - - [] + | ... +spc:replace{1, 1} + | --- + | - [1, 1] + | ... +tx2('spc:select{}') + | --- + | - - [] + | ... +tx2:commit() + | --- + | - + | ... + +spc:drop() + | --- + | ... + test_run:cmd("switch default") | --- | - true diff --git a/test/box/tx_man.test.lua b/test/box/tx_man.test.lua index 5c9765bd2b..9e1827884b 100644 --- a/test/box/tx_man.test.lua +++ b/test/box/tx_man.test.lua @@ -984,6 +984,26 @@ s:replace{0, 1, 0} s:drop() +--https://github.com/tarantool/tarantool/issues/6206 +spc = box.schema.space.create('test') +_ = spc:create_index('test', {type='tree'}) + +tx1:begin() +tx1('spc:select{}') +spc:replace{1, 1} +tx1('spc:select{}') +tx1:commit() + +spc:delete{1} +tx2 = txn_proxy.new() +tx2:begin() +tx2('spc:select{}') +spc:replace{1, 1} +tx2('spc:select{}') +tx2:commit() + +spc:drop() + test_run:cmd("switch default") test_run:cmd("stop server tx_man") test_run:cmd("cleanup server tx_man") -- GitLab