[PATCH v2 1/3] Revert "vinyl: force read view in iterator in autocommit mode"

Vladimir Davydov vdavydov.dev at gmail.com
Wed Mar 7 15:06:31 MSK 2018


This reverts commit a31c2c10347cbd131395ebdd93d64069923f5286.

The commit reverted by this patch forces all autocommit SELECTs to open
a read view immediately, as a result they can't update tuple cache.
Turned out that one of our customers intensively uses such SELECTs, and
disabling cache for them results in performance degradation.

The reason why that commit was introduced in the first place was to
avoid read set bloating for big SELECTs (e.g. space.count()): currently
we track not only read interval boundaries, but also each tuple fetched
from the primary index if it is a secondary index that is being scanned.
However, it doesn't seem that we really need to do that - tracking an
interval read from a secondary index guarantees that if a tuple returned
by the iterator is modified the transaction will be aborted and so
there's no need to track individual tuples read from the primary index.

That said, let's revert this commit and instead remove point lookup
tracking in case it is a secondary index that is being scanned (done
later in the series).
---
 src/box/vinyl.c                  | 128 +++++++++++++++++----------------------
 src/box/vy_tx.c                  |  12 ++--
 src/box/vy_tx.h                  |  17 +++---
 test/engine/iterator.result      |  16 ++---
 test/engine/iterator.test.lua    |   8 ---
 test/vinyl/cache.result          |  22 +++----
 test/vinyl/cache.test.lua        |  12 ++--
 test/vinyl/errinj.result         |  19 +++---
 test/vinyl/errinj.test.lua       |  11 ++--
 test/vinyl/iterator.result       | 110 +++++++++++++++++++--------------
 test/vinyl/partial_dump.result   |  17 +-----
 test/vinyl/partial_dump.test.lua |  13 +---
 test/vinyl/tx_gap_lock.result    |  43 -------------
 test/vinyl/tx_gap_lock.test.lua  |  15 -----
 14 files changed, 173 insertions(+), 270 deletions(-)

diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index d30f2e49..15508fbc 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -232,25 +232,21 @@ struct vinyl_iterator {
 	struct vy_env *env;
 	/** Vinyl index this iterator is for. */
 	struct vy_index *index;
-	/** Active transaction or NULL if autocommit. */
-	struct vy_tx *tx;
 	/**
-	 * Read view to use for the iteration. Points either to
-	 * tx->read_view or to rv_autocommit if autocommit.
+	 * Points either to tx_autocommit for autocommit mode
+	 * or to a multi-statement transaction active when the
+	 * iterator was created.
 	 */
-	const struct vy_read_view **rv;
+	struct vy_tx *tx;
 	/** Search key. */
 	struct tuple *key;
 	/** Vinyl read iterator. */
 	struct vy_read_iterator iterator;
 	/**
-	 * If an iterator is open in autocommit mode, we create
-	 * a read view for it immediately so as not to waste
-	 * memory on tracking reads for conflict resolution.
-	 * The following member points to the read view used by
-	 * the iterator.
+	 * Built-in transaction created when iterator is opened
+	 * in autocommit mode.
 	 */
-	struct vy_read_view *rv_autocommit;
+	struct vy_tx tx_autocommit;
 	/** Trigger invoked when tx ends to close the iterator. */
 	struct trigger on_tx_destroy;
 };
@@ -2929,16 +2925,6 @@ vinyl_engine_end_recovery(struct engine *engine)
 		vy_gc(e, e->recovery, VY_GC_INCOMPLETE, INT64_MAX);
 		vy_recovery_delete(e->recovery);
 		e->recovery = NULL;
-		/*
-		 * During WAL recovery we skip WAL rows that have
-		 * already been dumped to disk so the LSN last seen
-		 * by the transaction manager after WAL recovery is
-		 * complete may be less than the newest LSN actually
-		 * stored on disk. Update the LSN to make sure that
-		 * the iterator sees all data when open in a read
-		 * view.
-		 */
-		e->xm->lsn = vclock_sum(e->recovery_vclock);
 		e->recovery_vclock = NULL;
 		e->status = VINYL_ONLINE;
 		vy_quota_set_limit(&e->quota, e->memory);
@@ -3833,6 +3819,15 @@ fail:
 
 /* {{{ Cursor */
 
+static void
+vinyl_iterator_on_tx_destroy(struct trigger *trigger, void *event)
+{
+	(void)event;
+	struct vinyl_iterator *it = container_of(trigger,
+			struct vinyl_iterator, on_tx_destroy);
+	it->tx = NULL;
+}
+
 static int
 vinyl_iterator_last(struct iterator *base, struct tuple **ret)
 {
@@ -3849,11 +3844,18 @@ vinyl_iterator_close(struct vinyl_iterator *it)
 	it->index = NULL;
 	tuple_unref(it->key);
 	it->key = NULL;
+	if (it->tx == &it->tx_autocommit) {
+		/*
+		 * Rollback the automatic transaction.
+		 * Use vy_tx_destroy() so as not to spoil
+		 * the statistics of rollbacks issued by
+		 * user transactions.
+		 */
+		vy_tx_destroy(it->tx);
+	} else {
+		trigger_clear(&it->on_tx_destroy);
+	}
 	it->tx = NULL;
-	it->rv = NULL;
-	trigger_clear(&it->on_tx_destroy);
-	if (it->rv_autocommit != NULL)
-		tx_manager_destroy_read_view(it->env->xm, it->rv_autocommit);
 	it->base.next = vinyl_iterator_last;
 }
 
@@ -3865,8 +3867,12 @@ vinyl_iterator_primary_next(struct iterator *base, struct tuple **ret)
 	assert(it->index->id == 0);
 	struct tuple *tuple;
 
-	if ((*it->rv)->is_aborted ||
-	    (it->tx != NULL && it->tx->state == VINYL_TX_ABORT)) {
+	if (it->tx == NULL) {
+		diag_set(ClientError, ER_CURSOR_NO_TRANSACTION);
+		goto fail;
+	}
+	if (it->tx->state == VINYL_TX_ABORT || it->tx->read_view->is_aborted) {
+		diag_set(ClientError, ER_READ_VIEW_ABORTED);
 		goto fail;
 	}
 
@@ -3895,10 +3901,15 @@ vinyl_iterator_secondary_next(struct iterator *base, struct tuple **ret)
 	assert(it->index->id > 0);
 	struct tuple *tuple;
 
-	if ((*it->rv)->is_aborted ||
-	    (it->tx != NULL && it->tx->state == VINYL_TX_ABORT)) {
+	if (it->tx == NULL) {
+		diag_set(ClientError, ER_CURSOR_NO_TRANSACTION);
 		goto fail;
 	}
+	if (it->tx->state == VINYL_TX_ABORT || it->tx->read_view->is_aborted) {
+		diag_set(ClientError, ER_READ_VIEW_ABORTED);
+		goto fail;
+	}
+
 
 	if (vy_read_iterator_next(&it->iterator, &tuple) != 0)
 		goto fail;
@@ -3918,7 +3929,7 @@ vinyl_iterator_secondary_next(struct iterator *base, struct tuple **ret)
 	}
 #endif
 	/* Get the full tuple from the primary index. */
-	if (vy_index_get(it->index->pk, it->tx, it->rv,
+	if (vy_index_get(it->index->pk, it->tx, vy_tx_read_view(it->tx),
 			 tuple, &tuple) != 0)
 		goto fail;
 	*ret = tuple_bless(tuple);
@@ -3935,30 +3946,11 @@ vinyl_iterator_free(struct iterator *base)
 {
 	assert(base->free == vinyl_iterator_free);
 	struct vinyl_iterator *it = (struct vinyl_iterator *)base;
-	if (it->index != NULL)
+	if (base->next != vinyl_iterator_last)
 		vinyl_iterator_close(it);
 	mempool_free(&it->env->iterator_pool, it);
 }
 
-static int
-vinyl_iterator_no_tx(struct iterator *base, struct tuple **ret)
-{
-	(void)base;
-	(void)ret;
-	diag_set(ClientError, ER_CURSOR_NO_TRANSACTION);
-	return -1;
-}
-
-static void
-vinyl_iterator_on_tx_destroy(struct trigger *trigger, void *event)
-{
-	(void)event;
-	struct vinyl_iterator *it = container_of(trigger,
-			struct vinyl_iterator, on_tx_destroy);
-	vinyl_iterator_close(it);
-	it->base.next = vinyl_iterator_no_tx;
-}
-
 static struct iterator *
 vinyl_index_create_iterator(struct index *base, enum iterator_type type,
 			    const char *key, uint32_t part_count)
@@ -3969,18 +3961,20 @@ vinyl_index_create_iterator(struct index *base, enum iterator_type type,
 	if (type > ITER_GT) {
 		diag_set(UnsupportedIndexFeature, base->def,
 			 "requested iterator type");
-		goto err;
+		return NULL;
 	}
 
 	struct vinyl_iterator *it = mempool_alloc(&env->iterator_pool);
 	if (it == NULL) {
 	        diag_set(OutOfMemory, sizeof(struct vinyl_iterator),
 			 "mempool", "struct vinyl_iterator");
-		goto err;
+		return NULL;
 	}
 	it->key = vy_stmt_new_select(index->env->key_format, key, part_count);
-	if (it->key == NULL)
-		goto err_key;
+	if (it->key == NULL) {
+		mempool_free(&env->iterator_pool, it);
+		return NULL;
+	}
 
 	iterator_create(&it->base, base);
 	if (index->id == 0)
@@ -3993,11 +3987,6 @@ vinyl_index_create_iterator(struct index *base, enum iterator_type type,
 	it->index = index;
 	vy_index_ref(index);
 
-	it->rv_autocommit = NULL;
-	trigger_create(&it->on_tx_destroy,
-		       vinyl_iterator_on_tx_destroy, NULL, NULL);
-
-	const struct vy_read_view **rv;
 	struct vy_tx *tx = in_txn() ? in_txn()->engine_tx : NULL;
 	assert(tx == NULL || tx->state == VINYL_TX_READY);
 	if (tx != NULL) {
@@ -4005,27 +3994,18 @@ vinyl_index_create_iterator(struct index *base, enum iterator_type type,
 		 * Register a trigger that will abort this iterator
 		 * when the transaction ends.
 		 */
+		trigger_create(&it->on_tx_destroy,
+			       vinyl_iterator_on_tx_destroy, NULL, NULL);
 		trigger_add(&tx->on_destroy, &it->on_tx_destroy);
-		rv = (const struct vy_read_view **)&tx->read_view;
 	} else {
-		it->rv_autocommit = tx_manager_read_view(env->xm);
-		if (it->rv_autocommit == NULL)
-			goto err_rv;
-		rv = (const struct vy_read_view **)&it->rv_autocommit;
+		tx = &it->tx_autocommit;
+		vy_tx_create(env->xm, tx);
 	}
 	it->tx = tx;
-	it->rv = rv;
 
-	vy_read_iterator_open(&it->iterator, index, tx, type, it->key, rv);
+	vy_read_iterator_open(&it->iterator, index, tx, type, it->key,
+			      (const struct vy_read_view **)&tx->read_view);
 	return (struct iterator *)it;
-
-err_rv:
-	vy_index_unref(index);
-	tuple_unref(it->key);
-err_key:
-	mempool_free(&env->iterator_pool, it);
-err:
-	return NULL;
 }
 
 static int
diff --git a/src/box/vy_tx.c b/src/box/vy_tx.c
index 4f9b1e42..01130020 100644
--- a/src/box/vy_tx.c
+++ b/src/box/vy_tx.c
@@ -133,7 +133,8 @@ tx_manager_delete(struct tx_manager *xm)
 	free(xm);
 }
 
-struct vy_read_view *
+/** Create or reuse an instance of a read view. */
+static struct vy_read_view *
 tx_manager_read_view(struct tx_manager *xm)
 {
 	struct vy_read_view *rv;
@@ -176,7 +177,8 @@ tx_manager_read_view(struct tx_manager *xm)
 	return rv;
 }
 
-void
+/** Dereference and possibly destroy a read view. */
+static void
 tx_manager_destroy_read_view(struct tx_manager *xm,
 			     const struct vy_read_view *read_view)
 {
@@ -287,8 +289,7 @@ vy_tx_read_set_free_cb(vy_tx_read_set_t *read_set,
 	return NULL;
 }
 
-/** Initialize a tx object. */
-static void
+void
 vy_tx_create(struct tx_manager *xm, struct vy_tx *tx)
 {
 	stailq_create(&tx->log);
@@ -303,8 +304,7 @@ vy_tx_create(struct tx_manager *xm, struct vy_tx *tx)
 	rlist_create(&tx->on_destroy);
 }
 
-/** Destroy a tx object. */
-static void
+void
 vy_tx_destroy(struct vy_tx *tx)
 {
 	trigger_run(&tx->on_destroy, NULL);
diff --git a/src/box/vy_tx.h b/src/box/vy_tx.h
index 80fed256..33238ed7 100644
--- a/src/box/vy_tx.h
+++ b/src/box/vy_tx.h
@@ -261,15 +261,6 @@ tx_manager_new(void);
 void
 tx_manager_delete(struct tx_manager *xm);
 
-/** Create or reuse an instance of a read view. */
-struct vy_read_view *
-tx_manager_read_view(struct tx_manager *xm);
-
-/** Dereference and possibly destroy a read view. */
-void
-tx_manager_destroy_read_view(struct tx_manager *xm,
-			     const struct vy_read_view *read_view);
-
 /*
  * Determine the lowest possible vlsn, i.e. the level below
  * which the history could be compacted.
@@ -282,6 +273,14 @@ tx_manager_destroy_read_view(struct tx_manager *xm,
 int64_t
 tx_manager_vlsn(struct tx_manager *xm);
 
+/** Initialize a tx object. */
+void
+vy_tx_create(struct tx_manager *xm, struct vy_tx *tx);
+
+/** Destroy a tx object. */
+void
+vy_tx_destroy(struct vy_tx *tx);
+
 /** Begin a new transaction. */
 struct vy_tx *
 vy_tx_begin(struct tx_manager *xm);
diff --git a/test/engine/iterator.result b/test/engine/iterator.result
index 9cedc6a5..a5fc9d73 100644
--- a/test/engine/iterator.result
+++ b/test/engine/iterator.result
@@ -4016,21 +4016,17 @@ r
   - [3, 2]
   - [3, 3]
 ...
--- In memtx an iterator opened in autocommit mode works in
--- the read-committed isolation level while in vinyl it
--- creates a read view. To make sure the result is the same
--- for both engines, start a transaction.
-inspector:cmd("setopt delimiter ';'")
+itr1,itr2,itr3 = s:pairs({2}, {iterator = 'REQ'})
 ---
-- true
 ...
-box.begin()
-itr1,itr2,itr3 = s:pairs({2}, {iterator = 'REQ'})
 s:replace{2, 4}
+---
+- [2, 4]
+...
 r = {}
+---
+...
 for k,v in itr1,itr2,itr3 do table.insert(r, v) end
-box.commit()
-inspector:cmd("setopt delimiter ''");
 ---
 ...
 r
diff --git a/test/engine/iterator.test.lua b/test/engine/iterator.test.lua
index 69e2dee0..905173ad 100644
--- a/test/engine/iterator.test.lua
+++ b/test/engine/iterator.test.lua
@@ -337,18 +337,10 @@ r = {}
 for k,v in itr1,itr2,itr3 do table.insert(r, v) end
 r
 
--- In memtx an iterator opened in autocommit mode works in
--- the read-committed isolation level while in vinyl it
--- creates a read view. To make sure the result is the same
--- for both engines, start a transaction.
-inspector:cmd("setopt delimiter ';'")
-box.begin()
 itr1,itr2,itr3 = s:pairs({2}, {iterator = 'REQ'})
 s:replace{2, 4}
 r = {}
 for k,v in itr1,itr2,itr3 do table.insert(r, v) end
-box.commit()
-inspector:cmd("setopt delimiter ''");
 r
 
 r = nil
diff --git a/test/vinyl/cache.result b/test/vinyl/cache.result
index b4812297..3ec28a12 100644
--- a/test/vinyl/cache.result
+++ b/test/vinyl/cache.result
@@ -460,8 +460,6 @@ s:drop()
 ---
 ...
 -- Same test w/o begin/end
---
--- Note, select() does not update cache in autcommit mode, see gh-2534.
 s = box.schema.space.create('test', {engine = 'vinyl'})
 ---
 ...
@@ -587,9 +585,9 @@ s:select{1}
   - [1, 3, 1, '']
   - [1, 4, 1, '']
 ...
-stat_changed() -- cache miss, true
+stat_changed() -- cache hit, false
 ---
-- true
+- false
 ...
 s:select{}
 ---
@@ -621,9 +619,9 @@ s:select{}
   - [2, 4, 2, '']
   - [3, 3, 4]
 ...
-stat_changed() -- cache miss, true
+stat_changed() -- cache hit, false
 ---
-- true
+- false
 ...
 s:drop()
 ---
@@ -705,9 +703,9 @@ s:get{1, 2}
 ---
 - [1, 2, 1, '']
 ...
-stat_changed() -- cache miss, true
+stat_changed() -- cache hit, false
 ---
-- true
+- false
 ...
 s:select{1}
 ---
@@ -716,9 +714,9 @@ s:select{1}
   - [1, 3, 1, '']
   - [1, 4, 1, '']
 ...
-stat_changed() -- cache miss, true
+stat_changed() -- cache hit, false
 ---
-- true
+- false
 ...
 s:select{}
 ---
@@ -733,9 +731,9 @@ s:select{}
   - [2, 4, 2, '']
   - [3, 3, 4]
 ...
-stat_changed() -- cache miss, true
+stat_changed() -- cache hit, false
 ---
-- true
+- false
 ...
 s:drop()
 ---
diff --git a/test/vinyl/cache.test.lua b/test/vinyl/cache.test.lua
index 9ff77cbb..2d56152b 100644
--- a/test/vinyl/cache.test.lua
+++ b/test/vinyl/cache.test.lua
@@ -166,8 +166,6 @@ pk:max()
 s:drop()
 
 -- Same test w/o begin/end
---
--- Note, select() does not update cache in autcommit mode, see gh-2534.
 
 s = box.schema.space.create('test', {engine = 'vinyl'})
 pk = s:create_index('pk')
@@ -218,13 +216,13 @@ s:select{1}
 stat_changed()  -- cache miss, true
 
 s:select{1}
-stat_changed() -- cache miss, true
+stat_changed() -- cache hit, false
 
 s:select{}
 stat_changed()  -- cache miss, true
 
 s:select{}
-stat_changed() -- cache miss, true
+stat_changed() -- cache hit, false
 
 s:drop()
 
@@ -251,13 +249,13 @@ s:select{}
 stat_changed()  -- cache miss, true
 
 s:get{1, 2}
-stat_changed() -- cache miss, true
+stat_changed() -- cache hit, false
 
 s:select{1}
-stat_changed() -- cache miss, true
+stat_changed() -- cache hit, false
 
 s:select{}
-stat_changed() -- cache miss, true
+stat_changed() -- cache hit, false
 
 s:drop()
 
diff --git a/test/vinyl/errinj.result b/test/vinyl/errinj.result
index 9adffd96..db0f1d0d 100644
--- a/test/vinyl/errinj.result
+++ b/test/vinyl/errinj.result
@@ -158,6 +158,14 @@ test_run:cmd("setopt delimiter ''");
 ---
 - true
 ...
+-- Disable the cache so that we can check that disk errors
+-- are handled properly.
+vinyl_cache = box.cfg.vinyl_cache
+---
+...
+box.cfg{vinyl_cache = 0}
+---
+...
 s = box.schema.space.create('test', {engine='vinyl'})
 ---
 ...
@@ -285,6 +293,9 @@ s:select()
 s:drop()
 ---
 ...
+box.cfg{vinyl_cache = vinyl_cache}
+---
+...
 -- gh-2871: check that long reads are logged
 s = box.schema.space.create('test', {engine = 'vinyl'})
 ---
@@ -791,12 +802,10 @@ end;
 ---
 ...
 function iterate_in_read_view()
-    box.begin()
     local i = create_iterator(space)
     last_read = i.next()
     fiber.sleep(100000)
     last_read = i.next()
-    box.commit()
 end;
 ---
 ...
@@ -1191,9 +1200,6 @@ s:select{0}
 ---
 - - [0, 0]
 ...
-box.begin()
----
-...
 errinj.set("ERRINJ_WAL_DELAY", true)
 ---
 - ok
@@ -1228,9 +1234,6 @@ value
 ---
 - [2, 0]
 ...
-box.commit()
----
-...
 s:drop()
 ---
 ...
diff --git a/test/vinyl/errinj.test.lua b/test/vinyl/errinj.test.lua
index b4dc3734..59271673 100644
--- a/test/vinyl/errinj.test.lua
+++ b/test/vinyl/errinj.test.lua
@@ -67,6 +67,11 @@ end;
 s:drop();
 test_run:cmd("setopt delimiter ''");
 
+-- Disable the cache so that we can check that disk errors
+-- are handled properly.
+vinyl_cache = box.cfg.vinyl_cache
+box.cfg{vinyl_cache = 0}
+
 s = box.schema.space.create('test', {engine='vinyl'})
 _ = s:create_index('pk')
 for i = 1, 10 do s:insert({i, 'test str' .. tostring(i)}) end
@@ -97,6 +102,7 @@ errinj.set("ERRINJ_VY_READ_PAGE", false);
 s:select()
 
 s:drop()
+box.cfg{vinyl_cache = vinyl_cache}
 
 -- gh-2871: check that long reads are logged
 s = box.schema.space.create('test', {engine = 'vinyl'})
@@ -309,12 +315,10 @@ function fill_space()
 end;
 
 function iterate_in_read_view()
-    box.begin()
     local i = create_iterator(space)
     last_read = i.next()
     fiber.sleep(100000)
     last_read = i.next()
-    box.commit()
 end;
 
 test_run:cmd("setopt delimiter ''");
@@ -468,7 +472,6 @@ box.snapshot()
 s:replace{0, 0}
 s:select{0}
 
-box.begin()
 errinj.set("ERRINJ_WAL_DELAY", true)
 wait_replace = true
 _ = fiber.create(function() s:replace{1, 1} wait_replace = false end)
@@ -479,8 +482,6 @@ errinj.set("ERRINJ_WAL_DELAY", false)
 while wait_replace do fiber.sleep(0.01) end
 state, value = gen(param, state)
 value
-box.commit()
-
 s:drop()
 
 --
diff --git a/test/vinyl/iterator.result b/test/vinyl/iterator.result
index ceb59f10..4798f5f2 100644
--- a/test/vinyl/iterator.result
+++ b/test/vinyl/iterator.result
@@ -126,9 +126,7 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [1]
-  1: [2]
-  2: [3]
+- []
 ...
 --   3) create iterator within test case
 space:insert({1})
@@ -176,9 +174,7 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [1, 1]
-  1: [2, 2]
-  2: [3, 3]
+- []
 ...
 --
 -- UPSERT followed by DELETE
@@ -241,9 +237,7 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [1]
-  1: [2]
-  2: [3]
+- []
 ...
 --   3) create iterator within test case
 space:upsert({1}, {{'!', 2, 1}})
@@ -273,7 +267,7 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [3]
+- []
 ...
 --
 -- UPSERT followed by UPSERT
@@ -308,7 +302,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- []
+- 0: [1, 1]
+  1: [2, 2]
+  2: [3, 3]
 ...
 space:truncate()
 ---
@@ -343,9 +339,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [1]
-  1: [2]
-  2: [3]
+- 0: [1, 1]
+  1: [2, 2]
+  2: [3, 3]
 ...
 space:truncate()
 ---
@@ -381,8 +377,8 @@ space:select{}
 iterate_over(iter_obj)
 ---
 - 0: [1, 1]
-  1: [2]
-  2: [3]
+  1: [2, 2]
+  2: [3, 3]
 ...
 space:truncate()
 ---
@@ -423,7 +419,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- []
+- 0: [1, 10]
+  1: [2, 20]
+  2: [3, 30]
 ...
 space:truncate()
 ---
@@ -461,9 +459,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [1]
-  1: [2]
-  2: [3]
+- 0: [1, 10]
+  1: [2, 20]
+  2: [3, 30]
 ...
 space:truncate()
 ---
@@ -503,7 +501,7 @@ iterate_over(iter_obj)
 ---
 - 0: [1, 10]
   1: [2, 20]
-  2: [3]
+  2: [3, 30]
 ...
 space:truncate()
 ---
@@ -544,7 +542,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- []
+- 0: [1, 1, 10]
+  1: [2, 2, 20]
+  2: [3, 3, 30]
 ...
 space:truncate()
 ---
@@ -582,9 +582,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [1, 10]
-  1: [2, 20]
-  2: [3, 30]
+- 0: [1, 1, 10]
+  1: [2, 2, 20]
+  2: [3, 3, 30]
 ...
 space:truncate()
 ---
@@ -623,8 +623,8 @@ space:select{}
 iterate_over(iter_obj)
 ---
 - 0: [1, 1, 10]
-  1: [2, 20]
-  2: [3, 30]
+  1: [2, 2, 20]
+  2: [3, 3, 30]
 ...
 space:truncate()
 ---
@@ -696,9 +696,7 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [1, 10]
-  1: [2, 20]
-  2: [3, 30]
+- []
 ...
 --   3) create iterator within test case
 space:replace({1, 10})
@@ -731,7 +729,7 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [3, 30]
+- []
 ...
 --
 -- DELETE followed by REPLACE
@@ -781,9 +779,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [1, 10]
-  1: [2, 20]
-  2: [3, 30]
+- 0: [1]
+  1: [2]
+  2: [3]
 ...
 space:truncate()
 ---
@@ -833,7 +831,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- []
+- 0: [1]
+  1: [2]
+  2: [3]
 ...
 space:truncate()
 ---
@@ -885,6 +885,7 @@ iterate_over(iter_obj)
 ---
 - 0: [1]
   1: [2]
+  2: [3]
 ...
 space:truncate()
 ---
@@ -928,7 +929,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- []
+- 0: [1, 10]
+  1: [2, 20]
+  2: [3, 30]
 ...
 space:truncate()
 ---
@@ -969,9 +972,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- 0: [1]
-  1: [2]
-  2: [3]
+- 0: [1, 10]
+  1: [2, 20]
+  2: [3, 30]
 ...
 space:truncate()
 ---
@@ -1014,7 +1017,7 @@ iterate_over(iter_obj)
 ---
 - 0: [1, 10]
   1: [2, 20]
-  2: [3]
+  2: [3, 30]
 ...
 space:truncate()
 ---
@@ -1043,7 +1046,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- []
+- 0: [1]
+  1: [2]
+  2: [3]
 ...
 space:truncate()
 ---
@@ -1070,6 +1075,8 @@ space:select{}
 iterate_over(iter_obj)
 ---
 - 0: [1]
+  1: [2]
+  2: [3]
 ...
 space:truncate()
 ---
@@ -1129,7 +1136,9 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- []
+- 0: [1]
+  1: [2]
+  2: [3]
 ...
 space:truncate()
 ---
@@ -1160,6 +1169,7 @@ iterate_over(iter_obj)
 ---
 - 0: [1]
   1: [2]
+  2: [3]
 ...
 space:truncate()
 ---
@@ -1437,6 +1447,8 @@ box.snapshot()
 iterate_over(iter_obj_sp2)
 ---
 - 0: [5]
+  1: [6]
+  2: [8]
 ...
 space2:truncate()
 ---
@@ -1449,6 +1461,8 @@ iterate_over(iter_obj_sp3)
 ---
 - 0: [4]
   1: [5]
+  2: [6]
+  3: [8]
 ...
 space3:truncate()
 ---
@@ -1515,7 +1529,7 @@ space:select{}
 ...
 iterate_over(iter_obj)
 ---
-- []
+- 0: [1, 2, 3]
 ...
 iter_obj2 = create_iterator(idx2, 2, {iterator = 'EQ'})
 ---
@@ -1525,7 +1539,7 @@ space:delete({1})
 ...
 iterate_over(iter_obj2)
 ---
-- 0: [1, 2, 3]
+- []
 ...
 space:truncate()
 ---
@@ -1590,11 +1604,15 @@ space:select{}
 iterate_over(iter_obj)
 ---
 - 0: [3, 8, 1]
+  1: [4, 16, -1]
+  2: [5, 32, -10]
+  3: [6, 64, -10]
 ...
 iterate_over(iter_obj2)
 ---
 - 0: [4, 16, -1]
-  1: [5, 32, -10]
+  1: [6, 64, -10]
+  2: [5, 32, -10]
 ...
 iterate_over(iter_obj3)
 ---
@@ -1708,10 +1726,12 @@ iterate_over(iter_obj)
 ---
 - 0: [1, 1, 1]
   1: [2, 2, 2]
+  2: [3, 3, 3]
 ...
 iterate_over(iter_obj2)
 ---
 - 0: [2, 2, 2]
+  1: [3, 3, 3]
 ...
 box.commit()
 ---
diff --git a/test/vinyl/partial_dump.result b/test/vinyl/partial_dump.result
index b35335d1..4f8fce22 100644
--- a/test/vinyl/partial_dump.result
+++ b/test/vinyl/partial_dump.result
@@ -61,20 +61,6 @@ box.error.injection.set('ERRINJ_VY_INDEX_DUMP', -1)
 - ok
 ...
 test_run:cmd('restart server default')
-test_run:cmd("setopt delimiter ';'")
----
-- true
-...
-function tuple_equal(t1, t2)
-    if #t1 ~= #t2 then return false end
-    for i = 1, #t1 do
-        if t1[i] ~= t2[i] then return false end
-    end
-    return true
-end
-test_run:cmd("setopt delimiter ''");
----
-...
 INDEX_COUNT = box.cfg.vinyl_write_threads * 3
 ---
 ...
@@ -105,8 +91,7 @@ for i = 1, INDEX_COUNT - 1 do
         bad_index = i
     end
     for _, v in s.index[i]:pairs() do
-        local v2 = s:get(v[1])
-        if not v2 or not tuple_equal(v, v2) then
+        if v ~= s:get(v[1]) then
             bad_index = i
         end
     end
diff --git a/test/vinyl/partial_dump.test.lua b/test/vinyl/partial_dump.test.lua
index 87be8701..393f531f 100644
--- a/test/vinyl/partial_dump.test.lua
+++ b/test/vinyl/partial_dump.test.lua
@@ -37,16 +37,6 @@ box.error.injection.set('ERRINJ_VY_INDEX_DUMP', -1)
 
 test_run:cmd('restart server default')
 
-test_run:cmd("setopt delimiter ';'")
-function tuple_equal(t1, t2)
-    if #t1 ~= #t2 then return false end
-    for i = 1, #t1 do
-        if t1[i] ~= t2[i] then return false end
-    end
-    return true
-end
-test_run:cmd("setopt delimiter ''");
-
 INDEX_COUNT = box.cfg.vinyl_write_threads * 3
 assert(INDEX_COUNT < 100)
 
@@ -60,8 +50,7 @@ for i = 1, INDEX_COUNT - 1 do
         bad_index = i
     end
     for _, v in s.index[i]:pairs() do
-        local v2 = s:get(v[1])
-        if not v2 or not tuple_equal(v, v2) then
+        if v ~= s:get(v[1]) then
             bad_index = i
         end
     end
diff --git a/test/vinyl/tx_gap_lock.result b/test/vinyl/tx_gap_lock.result
index 425203c4..2a5087bf 100644
--- a/test/vinyl/tx_gap_lock.result
+++ b/test/vinyl/tx_gap_lock.result
@@ -1362,49 +1362,6 @@ test_run:cmd("setopt delimiter ''");
 - true
 ...
 ----------------------------------------------------------------
--- gh-2534: Iterator doesn't track reads in autocommit mode.
-----------------------------------------------------------------
-s = box.schema.space.create('test', {engine = 'vinyl'})
----
-...
-_ = s:create_index('pk', {parts = {1, 'unsigned'}})
----
-...
-_ = s:create_index('sk', {parts = {2, 'unsigned'}})
----
-...
-for i = 1, 100 do s:insert{i, i} end
----
-...
-gen, param, state = s.index.sk:pairs()
----
-...
-for i = 1, 100 do state, value = gen(param, state) end
----
-...
-value
----
-- [100, 100]
-...
-stat = box.info.vinyl()
----
-...
-stat.tx.transactions -- 0
----
-- 0
-...
-stat.tx.read_views -- 1
----
-- 1
-...
-stat.tx.gap_locks -- 0
----
-- 0
-...
-s:drop()
----
-...
-----------------------------------------------------------------
 c = nil
 ---
 ...
diff --git a/test/vinyl/tx_gap_lock.test.lua b/test/vinyl/tx_gap_lock.test.lua
index b1b551d0..2343a719 100644
--- a/test/vinyl/tx_gap_lock.test.lua
+++ b/test/vinyl/tx_gap_lock.test.lua
@@ -507,21 +507,6 @@ s:drop();
 
 test_run:cmd("setopt delimiter ''");
 ----------------------------------------------------------------
--- gh-2534: Iterator doesn't track reads in autocommit mode.
-----------------------------------------------------------------
-s = box.schema.space.create('test', {engine = 'vinyl'})
-_ = s:create_index('pk', {parts = {1, 'unsigned'}})
-_ = s:create_index('sk', {parts = {2, 'unsigned'}})
-for i = 1, 100 do s:insert{i, i} end
-gen, param, state = s.index.sk:pairs()
-for i = 1, 100 do state, value = gen(param, state) end
-value
-stat = box.info.vinyl()
-stat.tx.transactions -- 0
-stat.tx.read_views -- 1
-stat.tx.gap_locks -- 0
-s:drop()
-----------------------------------------------------------------
 
 c = nil
 c1 = nil
-- 
2.11.0




More information about the Tarantool-patches mailing list