btr0cur.h, btr0btr.h, btr0btr.c, btr0cur.c, row0purge.c:

  Fix a hang associated with an index tree of height 1 and purging of BLOB fields from it
parent 40689f64
...@@ -135,7 +135,7 @@ btr_page_insert_fits( ...@@ -135,7 +135,7 @@ btr_page_insert_fits(
/****************************************************************** /******************************************************************
Gets the root node of a tree and x-latches it. */ Gets the root node of a tree and x-latches it. */
static
page_t* page_t*
btr_root_get( btr_root_get(
/*=========*/ /*=========*/
...@@ -146,9 +146,6 @@ btr_root_get( ...@@ -146,9 +146,6 @@ btr_root_get(
ulint space; ulint space;
ulint root_page_no; ulint root_page_no;
page_t* root; page_t* root;
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)
|| mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_S_LOCK));
space = dict_tree_get_space(tree); space = dict_tree_get_space(tree);
root_page_no = dict_tree_get_page(tree); root_page_no = dict_tree_get_page(tree);
...@@ -334,8 +331,6 @@ btr_page_alloc( ...@@ -334,8 +331,6 @@ btr_page_alloc(
page_t* new_page; page_t* new_page;
ulint new_page_no; ulint new_page_no;
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
if (tree->type & DICT_IBUF) { if (tree->type & DICT_IBUF) {
return(btr_page_alloc_for_ibuf(tree, mtr)); return(btr_page_alloc_for_ibuf(tree, mtr));
......
...@@ -3180,7 +3180,7 @@ btr_store_big_rec_extern_fields( ...@@ -3180,7 +3180,7 @@ btr_store_big_rec_extern_fields(
ut_ad(mtr_memo_contains(local_mtr, dict_tree_get_lock(index->tree), ut_ad(mtr_memo_contains(local_mtr, dict_tree_get_lock(index->tree),
MTR_MEMO_X_LOCK)); MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(local_mtr, buf_block_align(data), ut_ad(mtr_memo_contains(local_mtr, buf_block_align(rec),
MTR_MEMO_PAGE_X_FIX)); MTR_MEMO_PAGE_X_FIX));
ut_a(index->type & DICT_CLUSTERED); ut_a(index->type & DICT_CLUSTERED);
...@@ -3315,7 +3315,13 @@ void ...@@ -3315,7 +3315,13 @@ void
btr_free_externally_stored_field( btr_free_externally_stored_field(
/*=============================*/ /*=============================*/
dict_index_t* index, /* in: index of the data, the index dict_index_t* index, /* in: index of the data, the index
tree MUST be X-latched */ tree MUST be X-latched; if the tree
height is 1, then also the root page
must be X-latched! (this is relevant
in the case this function is called
from purge where 'data' is located on
an undo log page, not an index
page) */
byte* data, /* in: internally stored data byte* data, /* in: internally stored data
+ reference to the externally + reference to the externally
stored part */ stored part */
......
...@@ -55,6 +55,15 @@ UNIQUE definition on secondary indexes when we decide if we can use the ...@@ -55,6 +55,15 @@ UNIQUE definition on secondary indexes when we decide if we can use the
insert buffer to speed up inserts */ insert buffer to speed up inserts */
#define BTR_IGNORE_SEC_UNIQUE 2048 #define BTR_IGNORE_SEC_UNIQUE 2048
/******************************************************************
Gets the root node of a tree and x-latches it. */
page_t*
btr_root_get(
/*=========*/
/* out: root page, x-latched */
dict_tree_t* tree, /* in: index tree */
mtr_t* mtr); /* in: mtr */
/****************************************************************** /******************************************************************
Gets a buffer page and declares its latching order level. */ Gets a buffer page and declares its latching order level. */
UNIV_INLINE UNIV_INLINE
......
...@@ -507,7 +507,13 @@ void ...@@ -507,7 +507,13 @@ void
btr_free_externally_stored_field( btr_free_externally_stored_field(
/*=============================*/ /*=============================*/
dict_index_t* index, /* in: index of the data, the index dict_index_t* index, /* in: index of the data, the index
tree MUST be X-latched */ tree MUST be X-latched; if the tree
height is 1, then also the root page
must be X-latched! (this is relevant
in the case this function is called
from purge where 'data' is located on
an undo log page, not an index
page) */
byte* data, /* in: internally stored data byte* data, /* in: internally stored data
+ reference to the externally + reference to the externally
stored part */ stored part */
......
...@@ -429,7 +429,18 @@ skip_secondaries: ...@@ -429,7 +429,18 @@ skip_secondaries:
index = dict_table_get_first_index(node->table); index = dict_table_get_first_index(node->table);
mtr_x_lock(dict_tree_get_lock(index->tree), &mtr); mtr_x_lock(dict_tree_get_lock(index->tree), &mtr);
/* NOTE: we must also acquire an X-latch to the
root page of the tree. We will need it when we
free pages from the tree. If the tree is of height 1,
the tree X-latch does NOT protect the root page,
because it is also a leaf page. Since we will have a
latch on an undo log page, we would break the
latching order if we would only later latch the
root page of such a tree! */
btr_root_get(index->tree, &mtr);
/* We assume in purge of externally stored fields /* We assume in purge of externally stored fields
that the space id of the undo log record is 0! */ that the space id of the undo log record is 0! */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment