From: Konstantin Osipov <kostja@tarantool.org>
To: tarantool-patches@freelists.org
Subject: [tarantool-patches] Re: [PATCH 2/3] vinyl: don't produce deferred DELETE on commit if key isn't updated
Date: Sat, 25 May 2019 09:13:39 +0300 [thread overview]
Message-ID: <20190525061339.GC14501@atlas> (raw)
In-Reply-To: <c2c12e54f231c028717b73eb8d5ea1f6772bc0f4.1558733444.git.vdavydov.dev@gmail.com>
* Vladimir Davydov <vdavydov.dev@gmail.com> [19/05/25 06:41]:
this one is basically lgtm
> Consider the following example:
>
> s = box.schema.space.create('test', {engine = 'vinyl'})
> s:create_index('primary')
> s:create_index('secondary', {parts = {2, 'unsigned'}})
>
> s:insert{1, 1, 1}
> s:replace{1, 1, 2}
>
> When REPLACE{1,1} is committed to the secondary index, the overwritten
> tuple, i.e. INSERT{1,1}, is found in the primary index memory, and so
> deferred DELETE{1,1} is generated right away and committed along with
> REPLACE{1,1}. However, there's no need to commit anything to the
> secondary index in this case, because its key isn't updated. Apart from
> eating memory and loading disk, this also breaks index stats, as vy_tx
> implementation doesn't expect two statements committed for the same key
> in a single transaction.
>
> Fix this by checking if there's a statement in the log for the deleted
> key and if there's skipping them both as we do in the regular case, see
> the comment in vy_tx_set.
>
> Closes #3693
> ---
> src/box/vy_tx.c | 18 +++++++++
> test/vinyl/deferred_delete.result | 78 +++++++++++++++++++++++++++++++++++++
> test/vinyl/deferred_delete.test.lua | 26 +++++++++++++
> test/vinyl/quota.result | 2 +-
> test/vinyl/stat.result | 6 +--
> test/vinyl/stat.test.lua | 2 +-
> test/vinyl/write_iterator.result | 2 +-
> test/vinyl/write_iterator.test.lua | 2 +-
> 8 files changed, 129 insertions(+), 7 deletions(-)
>
> diff --git a/src/box/vy_tx.c b/src/box/vy_tx.c
> index aedd0610..119d975b 100644
> --- a/src/box/vy_tx.c
> +++ b/src/box/vy_tx.c
> @@ -629,6 +629,23 @@ vy_tx_handle_deferred_delete(struct vy_tx *tx, struct txv *v)
> struct vy_lsm *lsm = vy_lsm(space->index[i]);
> struct vy_entry entry;
> vy_stmt_foreach_entry(entry, delete_stmt, lsm->cmp_def) {
> + struct txv *other = write_set_search_key(&tx->write_set,
> + lsm, entry);
> + if (other != NULL && !other->is_overwritten) {
> + /*
> + * The write set contains a statement
> + * for the key to be deleted. This can
> + * only occur if it's a REPLACE that
> + * happens not to update the secondary
> + * index key parts. It's safe to skip it,
> + * see vy_tx_set_entry().
> + */
> + assert(vy_stmt_type(stmt) == IPROTO_REPLACE);
> + assert(vy_stmt_type(other->entry.stmt) ==
> + IPROTO_REPLACE);
> + other->is_nop = true;
> + continue;
> + }
> struct txv *delete_txv = txv_new(tx, lsm, entry);
> if (delete_txv == NULL) {
> rc = -1;
> @@ -717,6 +734,7 @@ vy_tx_prepare(struct vy_tx *tx)
> * to the primary index LSM tree. So we must
> * skip it for secondary indexes as well.
> */
> + v->is_overwritten = true;
> continue;
> }
>
> diff --git a/test/vinyl/deferred_delete.result b/test/vinyl/deferred_delete.result
> index 422f2fe0..3f187a5b 100644
> --- a/test/vinyl/deferred_delete.result
> +++ b/test/vinyl/deferred_delete.result
> @@ -726,6 +726,84 @@ sk:select() -- ditto
> s:drop()
> ---
> ...
> +--
> +-- gh-3693 If a REPLACE doesn't update secondary index key parts,
> +-- we must not generate a deferred DELETE for it on commit.
> +-- Moreover, we must skip it as it has no effect.
> +--
> +s = box.schema.space.create('test', {engine = 'vinyl'})
> +---
> +...
> +pk = s:create_index('pk')
> +---
> +...
> +sk = s:create_index('sk', {parts = {2, 'unsigned'}})
> +---
> +...
> +s:insert{1, 1, 1}
> +---
> +- [1, 1, 1]
> +...
> +s:insert{2, 2, 2}
> +---
> +- [2, 2, 2]
> +...
> +s:replace{2, 2, 3}
> +---
> +- [2, 2, 3]
> +...
> +pk:stat().rows -- 3: INSERT{1,1,1} + INSERT{2,2,2} + REPLACE{2,2,3}
> +---
> +- 3
> +...
> +sk:stat().rows -- 2: INSERT{1,1} + INSERT{2,2}
> +---
> +- 2
> +...
> +box.begin()
> +---
> +...
> +s:replace{1, 1, 2}
> +---
> +- [1, 1, 2]
> +...
> +s:delete{1}
> +---
> +...
> +box.commit()
> +---
> +...
> +pk:stat().rows -- 4: INSERT{1,1,1} + INSERT{2,2,2} + REPLACE{2,2,3} + DELETE{1}
> +---
> +- 4
> +...
> +sk:stat().rows -- 3: INSERT{1,1} + INSERT{2,2} + DELETE{1,1}
> +---
> +- 3
> +...
> +box.snapshot()
> +---
> +- ok
> +...
> +pk:stat().rows -- 1: INSERT{2,2,3}
> +---
> +- 1
> +...
> +sk:stat().rows -- 1: INSERT{2,2}
> +---
> +- 1
> +...
> +pk:select()
> +---
> +- - [2, 2, 3]
> +...
> +sk:select()
> +---
> +- - [2, 2, 3]
> +...
> +s:drop()
> +---
> +...
> box.cfg{vinyl_cache = vinyl_cache}
> ---
> ...
> diff --git a/test/vinyl/deferred_delete.test.lua b/test/vinyl/deferred_delete.test.lua
> index 6dfcbde5..689c8f93 100644
> --- a/test/vinyl/deferred_delete.test.lua
> +++ b/test/vinyl/deferred_delete.test.lua
> @@ -265,6 +265,32 @@ box.snapshot()
> sk:select() -- ditto
> s:drop()
>
> +--
> +-- gh-3693 If a REPLACE doesn't update secondary index key parts,
> +-- we must not generate a deferred DELETE for it on commit.
> +-- Moreover, we must skip it as it has no effect.
> +--
> +s = box.schema.space.create('test', {engine = 'vinyl'})
> +pk = s:create_index('pk')
> +sk = s:create_index('sk', {parts = {2, 'unsigned'}})
> +s:insert{1, 1, 1}
> +s:insert{2, 2, 2}
> +s:replace{2, 2, 3}
> +pk:stat().rows -- 3: INSERT{1,1,1} + INSERT{2,2,2} + REPLACE{2,2,3}
> +sk:stat().rows -- 2: INSERT{1,1} + INSERT{2,2}
> +box.begin()
> +s:replace{1, 1, 2}
> +s:delete{1}
> +box.commit()
> +pk:stat().rows -- 4: INSERT{1,1,1} + INSERT{2,2,2} + REPLACE{2,2,3} + DELETE{1}
> +sk:stat().rows -- 3: INSERT{1,1} + INSERT{2,2} + DELETE{1,1}
> +box.snapshot()
> +pk:stat().rows -- 1: INSERT{2,2,3}
> +sk:stat().rows -- 1: INSERT{2,2}
> +pk:select()
> +sk:select()
> +s:drop()
> +
> box.cfg{vinyl_cache = vinyl_cache}
>
> --
> diff --git a/test/vinyl/quota.result b/test/vinyl/quota.result
> index 1a0842f9..d1b28ee5 100644
> --- a/test/vinyl/quota.result
> +++ b/test/vinyl/quota.result
> @@ -89,7 +89,7 @@ _ = space:replace{1, 1, string.rep('a', 1024 * 1024 * 5)}
> ...
> box.stat.vinyl().memory.level0
> ---
> -- 5341267
> +- 5292076
> ...
> space:drop()
> ---
> diff --git a/test/vinyl/stat.result b/test/vinyl/stat.result
> index aa47a7be..e2991d53 100644
> --- a/test/vinyl/stat.result
> +++ b/test/vinyl/stat.result
> @@ -1158,7 +1158,7 @@ s = box.schema.space.create('test', {engine = 'vinyl'})
> i1 = s:create_index('i1', {parts = {1, 'unsigned'}})
> ---
> ...
> -i2 = s:create_index('i2', {parts = {2, 'unsigned'}})
> +i2 = s:create_index('i2', {parts = {2, 'unsigned'}, unique = false})
> ---
> ...
> for i = 1, 100 do s:replace{i, i, string.rep('x', 1000)} end
> @@ -1191,7 +1191,7 @@ box.snapshot()
> stat_diff(gstat(), st, 'scheduler')
> ---
> - dump_input: 10420
> - dump_output: 10371
> + dump_output: 10411
> tasks_completed: 2
> dump_count: 1
> ...
> @@ -1206,7 +1206,7 @@ while i1:stat().disk.compaction.count == 0 do fiber.sleep(0.01) end
> ...
> stat_diff(gstat(), st, 'scheduler')
> ---
> -- compaction_input: 112188
> +- compaction_input: 112228
> tasks_completed: 1
> compaction_output: 101984
> ...
> diff --git a/test/vinyl/stat.test.lua b/test/vinyl/stat.test.lua
> index 4a360f33..4c751aad 100644
> --- a/test/vinyl/stat.test.lua
> +++ b/test/vinyl/stat.test.lua
> @@ -333,7 +333,7 @@ s:drop()
> -- sched stats
> s = box.schema.space.create('test', {engine = 'vinyl'})
> i1 = s:create_index('i1', {parts = {1, 'unsigned'}})
> -i2 = s:create_index('i2', {parts = {2, 'unsigned'}})
> +i2 = s:create_index('i2', {parts = {2, 'unsigned'}, unique = false})
>
> for i = 1, 100 do s:replace{i, i, string.rep('x', 1000)} end
> st = gstat()
> diff --git a/test/vinyl/write_iterator.result b/test/vinyl/write_iterator.result
> index 5c5200b8..f0244113 100644
> --- a/test/vinyl/write_iterator.result
> +++ b/test/vinyl/write_iterator.result
> @@ -931,7 +931,7 @@ box.snapshot()
> - ok
> ...
> -- Some padding to trigger minor compaction.
> -for i = 1001, 1000 + PAD2 do s:replace{i, i} end
> +for i = 1001, 1000 + PAD2 do s:delete{i} end
> ---
> ...
> box.snapshot()
> diff --git a/test/vinyl/write_iterator.test.lua b/test/vinyl/write_iterator.test.lua
> index fa44961a..0de21f21 100644
> --- a/test/vinyl/write_iterator.test.lua
> +++ b/test/vinyl/write_iterator.test.lua
> @@ -389,7 +389,7 @@ _ = s:insert{7, 7}
> _ = s:insert{8, 8}
> box.snapshot()
> -- Some padding to trigger minor compaction.
> -for i = 1001, 1000 + PAD2 do s:replace{i, i} end
> +for i = 1001, 1000 + PAD2 do s:delete{i} end
> box.snapshot()
> -- Generate DELETE+INSERT statements and write them to disk.
> s:delete{1} s:insert{1, 100}
> --
> 2.11.0
>
--
Konstantin Osipov, Moscow, Russia
next prev parent reply other threads:[~2019-05-25 6:13 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-24 21:53 [PATCH 0/3] Fixes of a few Vinyl transaction manager issues Vladimir Davydov
2019-05-24 21:53 ` [PATCH 1/3] vinyl: fix secondary index divergence on update Vladimir Davydov
2019-05-25 6:11 ` [tarantool-patches] " Konstantin Osipov
2019-05-25 19:51 ` Vladimir Davydov
2019-05-25 20:28 ` Konstantin Osipov
2019-05-26 14:36 ` Vladimir Davydov
[not found] ` <CAPZPwLoP+SEO2WbTavgtR3feWN4tX81GAYw5ZYp4_pC5JkyS_A@mail.gmail.com>
2019-05-27 8:28 ` Vladimir Davydov
2019-05-24 21:53 ` [PATCH 2/3] vinyl: don't produce deferred DELETE on commit if key isn't updated Vladimir Davydov
2019-05-25 6:13 ` Konstantin Osipov [this message]
2019-05-24 21:53 ` [PATCH 3/3] vinyl: fix deferred DELETE statement lost on commit Vladimir Davydov
2019-05-25 6:15 ` [tarantool-patches] " Konstantin Osipov
2019-05-27 8:29 ` Vladimir Davydov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190525061339.GC14501@atlas \
--to=kostja@tarantool.org \
--cc=tarantool-patches@freelists.org \
--subject='[tarantool-patches] Re: [PATCH 2/3] vinyl: don'\''t produce deferred DELETE on commit if key isn'\''t updated' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox