From b7065d33f547038881c36c49b03ea4a9d8a7caec Mon Sep 17 00:00:00 2001 From: Aleksandr Lyapunov <alyapunov@tarantool.org> Date: Thu, 12 Aug 2021 10:36:35 +0300 Subject: [PATCH] txm: track read instead of direct conflict in clarify After the previous patch it became possible to link read trackers to in-progress stories. This patch use one read tracker instead of bunch of direct conflicts in tuple_clarify. This is a bit accurate. Is also allows to avoid unnecessary conflict when a transaction reads its own change. Part of #5999 --- src/box/memtx_tx.c | 12 ++---- test/box/tx_man.result | 81 ++++++++++++++++++++++++++++++++++++++++ test/box/tx_man.test.lua | 25 +++++++++++++ 3 files changed, 110 insertions(+), 8 deletions(-) diff --git a/src/box/memtx_tx.c b/src/box/memtx_tx.c index 08a13b7658..60f910855d 100644 --- a/src/box/memtx_tx.c +++ b/src/box/memtx_tx.c @@ -1856,6 +1856,7 @@ memtx_tx_tuple_clarify_slow(struct txn *txn, struct space *space, { assert(tuple->is_dirty); struct memtx_story *story = memtx_tx_story_get(tuple); + struct memtx_story *last_checked_story = story; bool own_change = false; struct tuple *result = NULL; @@ -1864,17 +1865,12 @@ memtx_tx_tuple_clarify_slow(struct txn *txn, struct space *space, is_prepared_ok, &own_change)) { break; } - /* - * If somebody have added a tuple that we don't see, then - * when he commits we must go to read view or conflicted. - */ - if (story->add_stmt != NULL && txn != NULL) - memtx_tx_cause_conflict(story->add_stmt->txn, txn); story = story->link[index->dense_id].older_story; if (story == NULL) break; + last_checked_story = story; } - if (!own_change && story != NULL) { + if (!own_change) { /* * If the result tuple exists (is visible) - it is visible in * every index. But if we found a story of deleted tuple - we @@ -1883,7 +1879,7 @@ memtx_tx_tuple_clarify_slow(struct txn *txn, struct space *space, */ int shift = index->dense_id & 63; uint64_t mask = result == NULL ? 1ull << shift : UINT64_MAX; - memtx_tx_track_read_story(txn, space, story, mask); + memtx_tx_track_read_story(txn, space, last_checked_story, mask); } if (mk_index != 0) { assert(false); /* TODO: multiindex */ diff --git a/test/box/tx_man.result b/test/box/tx_man.result index e3f81d8ce6..109c48bd56 100644 --- a/test/box/tx_man.result +++ b/test/box/tx_man.result @@ -3436,6 +3436,87 @@ s:drop() | --- | ... +-- A pair of test that was created during #5999 investigation. +s=box.schema.space.create("s", {engine="memtx"}) + | --- + | ... +ti=s:create_index("ti", {type="tree"}) + | --- + | ... +tx1:begin() + | --- + | - + | ... +tx2:begin() + | --- + | - + | ... +tx1('s:replace{1, 1}') + | --- + | - - [1, 1] + | ... +tx2('s:replace{1, 2}') + | --- + | - - [1, 2] + | ... +rc1 = tx1('s:select{1}') + | --- + | ... +rc2 = tx2('s:select{1}') + | --- + | ... +tx1:commit() -- Must not fail + | --- + | - + | ... +tx2:commit() -- Must not fail + | --- + | - + | ... +s:drop() + | --- + | ... + +s=box.schema.space.create("s", {engine="memtx"}) + | --- + | ... +ti=s:create_index("ti", {type="tree"}) + | --- + | ... +tx1:begin() + | --- + | - + | ... +tx2:begin() + | --- + | - + | ... +tx1('s:replace{1, 1}') + | --- + | - - [1, 1] + | ... +tx2('s:replace{1, 2}') + | --- + | - - [1, 2] + | ... +rc1 = tx1('s:select{1}') + | --- + | ... +rc2 = tx2('s:select{1}') + | --- + | ... +tx2:commit() -- Must not fail + | --- + | - + | ... +tx1:commit() -- Must not fail + | --- + | - + | ... +s:drop() + | --- + | ... + test_run:cmd("switch default") | --- | - true diff --git a/test/box/tx_man.test.lua b/test/box/tx_man.test.lua index 4ac4d8af30..972816f2d6 100644 --- a/test/box/tx_man.test.lua +++ b/test/box/tx_man.test.lua @@ -1105,6 +1105,31 @@ tx2:commit() -- MUST BE OK s:drop() +-- A pair of test that was created during #5999 investigation. +s=box.schema.space.create("s", {engine="memtx"}) +ti=s:create_index("ti", {type="tree"}) +tx1:begin() +tx2:begin() +tx1('s:replace{1, 1}') +tx2('s:replace{1, 2}') +rc1 = tx1('s:select{1}') +rc2 = tx2('s:select{1}') +tx1:commit() -- Must not fail +tx2:commit() -- Must not fail +s:drop() + +s=box.schema.space.create("s", {engine="memtx"}) +ti=s:create_index("ti", {type="tree"}) +tx1:begin() +tx2:begin() +tx1('s:replace{1, 1}') +tx2('s:replace{1, 2}') +rc1 = tx1('s:select{1}') +rc2 = tx2('s:select{1}') +tx2:commit() -- Must not fail +tx1:commit() -- Must not fail +s:drop() + test_run:cmd("switch default") test_run:cmd("stop server tx_man") test_run:cmd("cleanup server tx_man") -- GitLab