From 1558c538732a2c1873b18467f7127f2a9d9f4d5c Mon Sep 17 00:00:00 2001
From: Vladimir Davydov <vdavydov.dev@gmail.com>
Date: Tue, 15 May 2018 16:40:09 +0300
Subject: [PATCH] vinyl: do not panic if secondary index is inconsistent with
 primary

Although the bug in vy_task_dump_complete() due to which a tuple could
be lost during dump was fixed, there still may be affected deployments
as the bug was persisted on disk. To avoid occasional crashes on such
deployments, let's make vinyl_iterator_secondary_next() skip tuples that
are present in a secondary index but missing in the primary.

Closes #3393
---
 src/box/vinyl.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index 9f9b4d0296..55a681049d 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -3922,6 +3922,7 @@ vinyl_iterator_secondary_next(struct iterator *base, struct tuple **ret)
 	assert(it->index->id > 0);
 	struct tuple *tuple;
 
+next:
 	if (it->tx == NULL) {
 		diag_set(ClientError, ER_CURSOR_NO_TRANSACTION);
 		goto fail;
@@ -3931,7 +3932,6 @@ vinyl_iterator_secondary_next(struct iterator *base, struct tuple **ret)
 		goto fail;
 	}
 
-
 	if (vy_read_iterator_next(&it->iterator, &tuple) != 0)
 		goto fail;
 
@@ -3954,11 +3954,26 @@ vinyl_iterator_secondary_next(struct iterator *base, struct tuple **ret)
 	 * Note, there's no need in vy_tx_track() as the
 	 * tuple is already tracked in the secondary index.
 	 */
+	struct tuple *full_tuple;
 	if (vy_point_lookup(it->index->pk, it->tx, vy_tx_read_view(it->tx),
-			    tuple, &tuple) != 0)
+			    tuple, &full_tuple) != 0)
 		goto fail;
-	*ret = tuple_bless(tuple);
-	tuple_unref(tuple);
+	if (full_tuple == NULL) {
+		/*
+		 * All indexes of a space must be consistent, i.e.
+		 * if a tuple is present in one index, it must be
+		 * present in all other indexes as well, so we can
+		 * get here only if there's a bug somewhere in vinyl.
+		 * Don't abort as core dump won't really help us in
+		 * this case. Just warn the user and proceed to the
+		 * next tuple.
+		 */
+		say_warn("%s: key %s missing in primary index",
+			 vy_index_name(it->index), vy_stmt_str(tuple));
+		goto next;
+	}
+	*ret = tuple_bless(full_tuple);
+	tuple_unref(full_tuple);
 	if (*ret != NULL)
 		return 0;
 fail:
-- 
GitLab