diff --git a/changelogs/unreleased/gh-10094-vy-index-drop-crash-fix.md b/changelogs/unreleased/gh-10094-vy-index-drop-crash-fix.md
new file mode 100644
index 0000000000000000000000000000000000000000..f02db6f5fc393f90b730fdb9bed953855a2ebd85
--- /dev/null
+++ b/changelogs/unreleased/gh-10094-vy-index-drop-crash-fix.md
@@ -0,0 +1,4 @@
+## bugfix/vinyl
+
+* Fixed a bug when a DDL operation dropping a unique index could crash
+  if performed concurrently with DML requests (gh-10094).
diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index 135b3e030debb9c7df7b00b0e5edc49b2604fb26..cd76d065aa2711dfd95211ca9197ec2a9e4a82c6 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -1410,6 +1410,11 @@ vy_get(struct vy_lsm *lsm, struct vy_tx *tx,
 	 * space.index.get({key}).
 	 */
 	assert(tx == NULL || tx->state == VINYL_TX_READY);
+	/*
+	 * Make sure the LSM tree isn't deleted while we are
+	 * reading from it.
+	 */
+	vy_lsm_ref(lsm);
 
 	int rc;
 	struct vy_entry partial, entry;
@@ -1425,15 +1430,15 @@ vy_get(struct vy_lsm *lsm, struct vy_tx *tx,
 		 * Use point lookup for a full key.
 		 */
 		if (tx != NULL && vy_tx_track_point(tx, lsm, key) != 0)
-			return -1;
+			goto fail;
 		if (vy_point_lookup(lsm, tx, rv, key, &partial) != 0)
-			return -1;
+			goto fail;
 		if (lsm->index_id > 0 && partial.stmt != NULL) {
 			rc = vy_get_by_secondary_tuple(lsm, tx, rv,
 						       partial, &entry);
 			tuple_unref(partial.stmt);
 			if (rc != 0)
-				return -1;
+				goto fail;
 		} else {
 			entry = partial;
 		}
@@ -1459,7 +1464,7 @@ vy_get(struct vy_lsm *lsm, struct vy_tx *tx,
 		vy_read_iterator_cache_add(&itr, entry);
 	vy_read_iterator_close(&itr);
 	if (rc != 0)
-		return -1;
+		goto fail;
 out:
 	*result = entry.stmt;
 
@@ -1474,7 +1479,11 @@ vy_get(struct vy_lsm *lsm, struct vy_tx *tx,
 	}
 	if (*result != NULL)
 		vy_stmt_counter_acct_tuple(&lsm->stat.get, *result);
+	vy_lsm_unref(lsm);
 	return 0;
+fail:
+	vy_lsm_unref(lsm);
+	return -1;
 }
 
 /**
@@ -3856,14 +3865,8 @@ vinyl_index_get(struct index *index, const char *key,
 		tx = &tx_autocommit;
 		vy_tx_create(env->xm, tx);
 	}
-	/*
-	 * Make sure the LSM tree isn't deleted while we are
-	 * reading from it.
-	 */
-	vy_lsm_ref(lsm);
 	int rc = vy_get_by_raw_key(lsm, tx, vy_tx_read_view(tx),
 				   key, part_count, ret);
-	vy_lsm_unref(lsm);
 	if (tx == &tx_autocommit)
 		vy_tx_destroy(tx);
 	if (rc != 0)
diff --git a/src/box/vy_lsm.c b/src/box/vy_lsm.c
index 51150e45fbd1f54c47c4b7460e4d4623483641c5..82631f2c32f8cd3a5a7e52699a2b5b26968e05a3 100644
--- a/src/box/vy_lsm.c
+++ b/src/box/vy_lsm.c
@@ -256,7 +256,7 @@ vy_range_tree_free_cb(vy_range_tree_t *t, struct vy_range *range, void *arg)
 	(void)arg;
 	struct vy_slice *slice;
 	rlist_foreach_entry(slice, &range->slices, in_range)
-		vy_slice_wait_pinned(slice);
+		assert(slice->pin_count == 0);
 	vy_range_delete(range);
 	return NULL;
 }
diff --git a/test/vinyl-luatest/gh_10094_index_drop_test.lua b/test/vinyl-luatest/gh_10094_index_drop_test.lua
new file mode 100644
index 0000000000000000000000000000000000000000..8e260148db453869772419890d5710d7c5a9636d
--- /dev/null
+++ b/test/vinyl-luatest/gh_10094_index_drop_test.lua
@@ -0,0 +1,44 @@
+local server = require('luatest.server')
+local t = require('luatest')
+
+local g = t.group()
+
+g.before_all(function(cg)
+    t.tarantool.skip_if_not_debug()
+    cg.server = server:new()
+    cg.server:start()
+    cg.server:exec(function()
+        box.cfg{vinyl_cache = 0}
+    end)
+end)
+
+g.after_all(function(cg)
+    cg.server:drop()
+end)
+
+g.after_each(function(cg)
+    cg.server:exec(function()
+        if box.space.test ~= nil then
+            box.space.test:drop()
+        end
+        box.error.injection.set('ERRINJ_VY_READ_PAGE_DELAY', false)
+    end)
+end)
+
+g.test_index_drop = function(cg)
+    cg.server:exec(function()
+        local fiber = require('fiber')
+        local s = box.schema.create_space('test', {engine = 'vinyl'})
+        s:create_index('pk')
+        s:create_index('sk', {parts = {{2, 'unsigned'}}})
+        s:insert{1, 10}
+        box.snapshot()
+        box.error.injection.set('ERRINJ_VY_READ_PAGE_DELAY', true)
+        fiber.create(function()
+            s:insert{2, 10}
+        end)
+        s.index.sk:drop()
+        box.error.injection.set('ERRINJ_VY_READ_PAGE_DELAY', false)
+        t.assert_equals(s:select({}, {fullscan = true}), {{1, 10}})
+    end)
+end