diff --git a/src/box/key_def.c b/src/box/key_def.c
index ee758eefa066ee141c3e1b09172b63efc533c0bf..a842ef1ecb4d21e91507c3a3ee686abdfdfc42a2 100644
--- a/src/box/key_def.c
+++ b/src/box/key_def.c
@@ -81,18 +81,26 @@ const struct opt_def part_def_reg[] = {
 	OPT_END,
 };
 
-struct key_def *
-key_def_dup(const struct key_def *src)
+/**
+ * Return the size of memory occupied by the given key definition.
+ */
+static inline size_t
+key_def_copy_size(const struct key_def *def)
 {
 	size_t sz = 0;
-	for (uint32_t i = 0; i < src->part_count; i++)
-		sz += src->parts[i].path_len;
-	sz = key_def_sizeof(src->part_count, sz);
-	struct key_def *res = (struct key_def *)malloc(sz);
-	if (res == NULL) {
-		diag_set(OutOfMemory, sz, "malloc", "res");
-		return NULL;
-	}
+	for (uint32_t i = 0; i < def->part_count; i++)
+		sz += def->parts[i].path_len;
+	return key_def_sizeof(def->part_count, sz);
+}
+
+/**
+ * A helper function for key_def_copy() and key_def_dup() that
+ * copies key definition src of size sz to res without checking
+ * that the two key definitions have the same allocation size.
+ */
+static struct key_def *
+key_def_copy_impl(struct key_def *res, const struct key_def *src, size_t sz)
+{
 	memcpy(res, src, sz);
 	/*
 	 * Update the paths pointers so that they refer to the
@@ -112,20 +120,24 @@ key_def_dup(const struct key_def *src)
 }
 
 void
-key_def_swap(struct key_def *old_def, struct key_def *new_def)
+key_def_copy(struct key_def *dest, const struct key_def *src)
 {
-	assert(old_def->part_count == new_def->part_count);
-	for (uint32_t i = 0; i < new_def->part_count; i++) {
-		SWAP(old_def->parts[i], new_def->parts[i]);
-		/*
-		 * Paths are allocated as a part of key_def so
-		 * we need to swap path pointers back - it's OK
-		 * as paths aren't supposed to change.
-		 */
-		assert(old_def->parts[i].path_len == new_def->parts[i].path_len);
-		SWAP(old_def->parts[i].path, new_def->parts[i].path);
+	size_t sz = key_def_copy_size(src);
+	assert(sz = key_def_copy_size(dest));
+	key_def_copy_impl(dest, src, sz);
+}
+
+struct key_def *
+key_def_dup(const struct key_def *src)
+{
+	size_t sz = key_def_copy_size(src);
+	struct key_def *res = malloc(sz);
+	if (res == NULL) {
+		diag_set(OutOfMemory, sz, "malloc", "res");
+		return NULL;
 	}
-	SWAP(*old_def, *new_def);
+	key_def_copy_impl(res, src, sz);
+	return res;
 }
 
 void
diff --git a/src/box/key_def.h b/src/box/key_def.h
index df83d055cfae430eb8c7f21a508453f07ee8fbd9..73aefb9a729084efb7eb629e7232f46bf8060eff 100644
--- a/src/box/key_def.h
+++ b/src/box/key_def.h
@@ -250,11 +250,11 @@ struct key_def *
 key_def_dup(const struct key_def *src);
 
 /**
- * Swap content of two key definitions in memory.
+ * Copy content of key definition src to dest.
  * The two key definitions must have the same size.
  */
 void
-key_def_swap(struct key_def *old_def, struct key_def *new_def);
+key_def_copy(struct key_def *dest, const struct key_def *src);
 
 /**
  * Delete @a key_def.
diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index cf7af26b75ce256aa8834ad121f7ebe5485edc25..4ac541388c4af53b0dc41a2f125772e0e8037078 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -963,6 +963,15 @@ vinyl_index_commit_drop(struct index *index, int64_t lsn)
 	vy_log_tx_try_commit();
 }
 
+static void
+vinyl_index_update_def(struct index *index)
+{
+	struct vy_lsm *lsm = vy_lsm(index);
+	lsm->opts = index->def->opts;
+	key_def_copy(lsm->key_def, index->def->key_def);
+	key_def_copy(lsm->cmp_def, index->def->cmp_def);
+}
+
 static bool
 vinyl_index_depends_on_pk(struct index *index)
 {
@@ -1200,9 +1209,6 @@ vinyl_space_swap_index(struct space *old_space, struct space *new_space,
 	SWAP(old_lsm->check_is_unique, new_lsm->check_is_unique);
 	SWAP(old_lsm->mem_format, new_lsm->mem_format);
 	SWAP(old_lsm->disk_format, new_lsm->disk_format);
-	SWAP(old_lsm->opts, new_lsm->opts);
-	key_def_swap(old_lsm->key_def, new_lsm->key_def);
-	key_def_swap(old_lsm->cmp_def, new_lsm->cmp_def);
 
 	/* Update pointer to the primary key. */
 	vy_lsm_update_pk(old_lsm, vy_lsm(old_space->index_map[0]));
@@ -4741,7 +4747,7 @@ static const struct index_vtab vinyl_index_vtab = {
 	/* .abort_create = */ vinyl_index_abort_create,
 	/* .commit_modify = */ vinyl_index_commit_modify,
 	/* .commit_drop = */ vinyl_index_commit_drop,
-	/* .update_def = */ generic_index_update_def,
+	/* .update_def = */ vinyl_index_update_def,
 	/* .depends_on_pk = */ vinyl_index_depends_on_pk,
 	/* .def_change_requires_rebuild = */
 		vinyl_index_def_change_requires_rebuild,