Wrong page type (expected 7 found N) error [CORE2936] #3319
Labels
affect-version: 1.5.4
affect-version: 1.5.5
affect-version: 1.5.6
affect-version: 2.0.0
affect-version: 2.0.1
affect-version: 2.0.2
affect-version: 2.0.3
affect-version: 2.0.4
affect-version: 2.0.5
affect-version: 2.1.0
affect-version: 2.1.1
affect-version: 2.1.2
affect-version: 2.1.3
affect-version: 2.5 Alpha 1
affect-version: 2.5 Beta 1
affect-version: 2.5 Beta 2
affect-version: 2.5 RC1
affect-version: 2.5 RC2
component: engine
fix-version: 2.0.6
fix-version: 2.1.4
fix-version: 2.5 RC3
fix-version: 3.0 Alpha 1
priority: major
qa: cannot be tested
type: bug
Submitted by: @hvlad
If two consecutive leaf index pages are removed from index (garbage collected) by two different connections at the same time, then linked list of sibling pages could became broken and sibling pointer at other index page could point to the freed index page. When freed page is allocated again index corruption will be reported. Below is more detailed explanation.
BTR\garbage_collect() should remove some index page from b-tree. This is not simple process as we should be careful about deadlocks and lock pages in special order.
The order is : parent page, left sibling, page to be removed (gc_page) and right sibling. Parent page number supplied as input parameter of garbage_collect() and left sibling page number we took from initially locked gc_page and store in local variable.
As said above, we should take page locks in order, therefore at first we do release gc_page. Then we fetch parent page. Parent page could be changed or even re-allocated since we last visit it. Therefore care is taken to ensure that page still is index page and belongs to the same index at the same level :
// fetch the parent page, but we have to be careful, because it could have
// been garbage-collected when we released it--make checks so that we know it
// is the parent page; there is a minute possibility that it could have been
// released and reused already as another page on this level, but if so, it
// won't really matter because we won't find the node on it
WIN parent_window(pageSpaceID, parent_number);
btree_page* parent_page = (btree_page*) CCH_FETCH(tdbb, &parent_window, LCK_write, pag_undefined);
if ((parent_page->btr_header.pag_type != pag_index) ||
(parent_page->btr_relation != relation_number) ||
(parent_page->btr_id != (UCHAR)(index_id % 256)) ||
(parent_page->btr_level != index_level + 1))
{
CCH_RELEASE(tdbb, &parent_window);
return contents_above_threshold;
}
Commits: b86cb83 dba4d51 0615f7a 85f4524
The text was updated successfully, but these errors were encountered: