diff --git a/src/box/vy_log.c b/src/box/vy_log.c index 06ab72472f9c57fbad656fc9f4c1e288a546f541..85b61a84cb0b659913a64a6cc9e52ee05682c2f1 100644 --- a/src/box/vy_log.c +++ b/src/box/vy_log.c @@ -2141,9 +2141,10 @@ vy_recovery_build_index_id_hash(struct vy_recovery *recovery) /* * If there's no LSM tree for these space_id/index_id * or it was dropped, simply replace it with the latest - * LSM tree version. + * committed LSM tree version. */ - if (hashed_lsm == NULL || hashed_lsm->drop_lsn >= 0) { + if (hashed_lsm == NULL || + (hashed_lsm->drop_lsn >= 0 && lsm->create_lsn >= 0)) { struct mh_i64ptr_node_t node; node.key = vy_recovery_index_id_hash(space_id, index_id); node.val = lsm; diff --git a/test/vinyl/errinj_vylog.result b/test/vinyl/errinj_vylog.result index 0e3b79c4a00643c848656f4e70e2ccbadf7b3dac..06cc68188d7013fe2060e235977434712dde2d0e 100644 --- a/test/vinyl/errinj_vylog.result +++ b/test/vinyl/errinj_vylog.result @@ -368,3 +368,58 @@ s.index.sk:select() s:drop() --- ... +-- +-- gh-4066: recovery error if an instance is restarted while +-- building an index and there's an index with the same id in +-- the snapshot. +-- +fiber = require('fiber') +--- +... +s = box.schema.space.create('test', {engine = 'vinyl'}) +--- +... +_ = s:create_index('pk') +--- +... +_ = s:create_index('sk', {parts = {2, 'unsigned'}}) +--- +... +s.index[1] ~= nil +--- +- true +... +s:replace{1, 2} +--- +- [1, 2] +... +box.snapshot() +--- +- ok +... +s.index.sk:drop() +--- +... +-- Log index creation, but never finish building it due to an error injection. +box.error.injection.set('ERRINJ_VY_READ_PAGE_TIMEOUT', 9000) +--- +- ok +... +_ = fiber.create(function() s:create_index('sk', {parts = {2, 'unsigned'}}) end) +--- +... +fiber.sleep(0.01) +--- +... +-- Should ignore the incomplete index on recovery. +test_run:cmd('restart server default') +s = box.space.test +--- +... +s.index[1] == nil +--- +- true +... +s:drop() +--- +... diff --git a/test/vinyl/errinj_vylog.test.lua b/test/vinyl/errinj_vylog.test.lua index ce9e12e5d9a169b98286f0d424fe0f662cea11fd..2936f879c8df64cde54a9771dbd58363a0a904da 100644 --- a/test/vinyl/errinj_vylog.test.lua +++ b/test/vinyl/errinj_vylog.test.lua @@ -177,3 +177,31 @@ s.index.pk:select() s.index.sk:select() s:drop() + +-- +-- gh-4066: recovery error if an instance is restarted while +-- building an index and there's an index with the same id in +-- the snapshot. +-- +fiber = require('fiber') + +s = box.schema.space.create('test', {engine = 'vinyl'}) +_ = s:create_index('pk') +_ = s:create_index('sk', {parts = {2, 'unsigned'}}) +s.index[1] ~= nil +s:replace{1, 2} +box.snapshot() + +s.index.sk:drop() + +-- Log index creation, but never finish building it due to an error injection. +box.error.injection.set('ERRINJ_VY_READ_PAGE_TIMEOUT', 9000) +_ = fiber.create(function() s:create_index('sk', {parts = {2, 'unsigned'}}) end) +fiber.sleep(0.01) + +-- Should ignore the incomplete index on recovery. +test_run:cmd('restart server default') + +s = box.space.test +s.index[1] == nil +s:drop()