mirror of
https://github.com/MariaDB/server.git
synced 2026-05-06 23:25:34 +02:00
MDEV-32175: Reduce page_align(), page_offset() calls
When srv_page_size and innodb_page_size were introduced, the functions page_align() and page_offset() got more expensive. Let us try to replace such calls with simpler pointer arithmetics with respect to the buffer page frame. page_rec_get_next_non_del_marked(): Add a page frame as a parameter, and template<bool comp>. page_rec_next_get(): A more efficient variant of page_rec_get_next(), with template<bool comp> and const page_t* parameters. lock_get_heap_no(): Replaces page_rec_get_heap_no() outside debug checks. fseg_free_step(), fseg_free_step_not_header(): Take the header block as a parameter. Reviewed by: Vladislav Lesin
This commit is contained in:
parent
df3855a471
commit
895cd553a3
35 changed files with 744 additions and 566 deletions
|
|
@ -908,26 +908,31 @@ btr_page_get_father_block(
|
||||||
mtr_t* mtr, /*!< in: mtr */
|
mtr_t* mtr, /*!< in: mtr */
|
||||||
btr_cur_t* cursor) /*!< out: cursor on node pointer record,
|
btr_cur_t* cursor) /*!< out: cursor on node pointer record,
|
||||||
its page x-latched */
|
its page x-latched */
|
||||||
|
noexcept
|
||||||
{
|
{
|
||||||
rec_t *rec=
|
const page_t *page= btr_cur_get_page(cursor);
|
||||||
page_rec_get_next(page_get_infimum_rec(cursor->block()->page.frame));
|
const rec_t *rec= page_is_comp(page)
|
||||||
|
? page_rec_next_get<true>(page, page + PAGE_NEW_INFIMUM)
|
||||||
|
: page_rec_next_get<false>(page, page + PAGE_OLD_INFIMUM);
|
||||||
if (UNIV_UNLIKELY(!rec))
|
if (UNIV_UNLIKELY(!rec))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
cursor->page_cur.rec= rec;
|
cursor->page_cur.rec= const_cast<rec_t*>(rec);
|
||||||
return btr_page_get_parent(offsets, heap, cursor, mtr);
|
return btr_page_get_parent(offsets, heap, cursor, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Seek to the parent page of a B-tree page.
|
/** Seek to the parent page of a B-tree page.
|
||||||
@param[in,out] mtr mini-transaction
|
@param mtr mini-transaction
|
||||||
@param[in,out] cursor cursor pointing to the x-latched parent page
|
@param cursor cursor pointing to the x-latched parent page
|
||||||
@return whether the cursor was successfully positioned */
|
@return whether the cursor was successfully positioned */
|
||||||
bool btr_page_get_father(mtr_t* mtr, btr_cur_t* cursor)
|
bool btr_page_get_father(mtr_t *mtr, btr_cur_t *cursor) noexcept
|
||||||
{
|
{
|
||||||
rec_t *rec=
|
page_t *page= btr_cur_get_page(cursor);
|
||||||
page_rec_get_next(page_get_infimum_rec(cursor->block()->page.frame));
|
const rec_t *rec= page_is_comp(page)
|
||||||
|
? page_rec_next_get<true>(page, page + PAGE_NEW_INFIMUM)
|
||||||
|
: page_rec_next_get<false>(page, page + PAGE_OLD_INFIMUM);
|
||||||
if (UNIV_UNLIKELY(!rec))
|
if (UNIV_UNLIKELY(!rec))
|
||||||
return false;
|
return false;
|
||||||
cursor->page_cur.rec= rec;
|
cursor->page_cur.rec= const_cast<rec_t*>(rec);
|
||||||
mem_heap_t *heap= mem_heap_create(100);
|
mem_heap_t *heap= mem_heap_create(100);
|
||||||
const bool got= btr_page_get_parent(nullptr, heap, cursor, mtr);
|
const bool got= btr_page_get_parent(nullptr, heap, cursor, mtr);
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
@ -957,8 +962,7 @@ static void btr_free_root(buf_block_t *block, const fil_space_t &space,
|
||||||
{
|
{
|
||||||
/* Free the entire segment in small steps. */
|
/* Free the entire segment in small steps. */
|
||||||
ut_d(mtr->freeing_tree());
|
ut_d(mtr->freeing_tree());
|
||||||
while (!fseg_free_step(PAGE_HEADER + PAGE_BTR_SEG_TOP +
|
while (!fseg_free_step(block, PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr));
|
||||||
block->page.frame, mtr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1164,8 +1168,8 @@ leaf_loop:
|
||||||
/* NOTE: page hash indexes are dropped when a page is freed inside
|
/* NOTE: page hash indexes are dropped when a page is freed inside
|
||||||
fsp0fsp. */
|
fsp0fsp. */
|
||||||
|
|
||||||
bool finished = fseg_free_step(PAGE_HEADER + PAGE_BTR_SEG_LEAF
|
bool finished = fseg_free_step(block, PAGE_HEADER + PAGE_BTR_SEG_LEAF,
|
||||||
+ block->page.frame, &mtr
|
&mtr
|
||||||
#ifdef BTR_CUR_HASH_ADAPT
|
#ifdef BTR_CUR_HASH_ADAPT
|
||||||
, ahi
|
, ahi
|
||||||
#endif /* BTR_CUR_HASH_ADAPT */
|
#endif /* BTR_CUR_HASH_ADAPT */
|
||||||
|
|
@ -1183,8 +1187,9 @@ top_loop:
|
||||||
|
|
||||||
finished = !btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP,
|
finished = !btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP,
|
||||||
*block, *space)
|
*block, *space)
|
||||||
|| fseg_free_step_not_header(PAGE_HEADER + PAGE_BTR_SEG_TOP
|
|| fseg_free_step_not_header(block,
|
||||||
+ block->page.frame, &mtr
|
PAGE_HEADER + PAGE_BTR_SEG_TOP,
|
||||||
|
&mtr
|
||||||
#ifdef BTR_CUR_HASH_ADAPT
|
#ifdef BTR_CUR_HASH_ADAPT
|
||||||
,ahi
|
,ahi
|
||||||
#endif /* BTR_CUR_HASH_ADAPT */
|
#endif /* BTR_CUR_HASH_ADAPT */
|
||||||
|
|
@ -1925,7 +1930,6 @@ btr_root_raise_and_insert(
|
||||||
dberr_t* err) /*!< out: error code */
|
dberr_t* err) /*!< out: error code */
|
||||||
{
|
{
|
||||||
dict_index_t* index;
|
dict_index_t* index;
|
||||||
rec_t* rec;
|
|
||||||
dtuple_t* node_ptr;
|
dtuple_t* node_ptr;
|
||||||
ulint level;
|
ulint level;
|
||||||
rec_t* node_ptr_rec;
|
rec_t* node_ptr_rec;
|
||||||
|
|
@ -2082,7 +2086,13 @@ btr_root_raise_and_insert(
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t new_page_no = new_block->page.id().page_no();
|
const uint32_t new_page_no = new_block->page.id().page_no();
|
||||||
rec = page_rec_get_next(page_get_infimum_rec(new_block->page.frame));
|
const rec_t* rec= page_is_comp(new_block->page.frame)
|
||||||
|
? page_rec_next_get<true>(new_block->page.frame,
|
||||||
|
new_block->page.frame
|
||||||
|
+ PAGE_NEW_INFIMUM)
|
||||||
|
: page_rec_next_get<false>(new_block->page.frame,
|
||||||
|
new_block->page.frame
|
||||||
|
+ PAGE_OLD_INFIMUM);
|
||||||
ut_ad(rec); /* We just created the page. */
|
ut_ad(rec); /* We just created the page. */
|
||||||
|
|
||||||
/* Build the node pointer (= node key and page address) for the
|
/* Build the node pointer (= node key and page address) for the
|
||||||
|
|
@ -2157,90 +2167,109 @@ btr_root_raise_and_insert(
|
||||||
|
|
||||||
/** Decide if the page should be split at the convergence point of inserts
|
/** Decide if the page should be split at the convergence point of inserts
|
||||||
converging to the left.
|
converging to the left.
|
||||||
@param[in] cursor insert position
|
@param cursor insert position
|
||||||
@return the first record to be moved to the right half page
|
@return the first record to be moved to the right half page
|
||||||
@retval NULL if no split is recommended */
|
@retval nullptr if no split is recommended */
|
||||||
rec_t* btr_page_get_split_rec_to_left(const btr_cur_t* cursor)
|
rec_t *btr_page_get_split_rec_to_left(const btr_cur_t *cursor) noexcept
|
||||||
{
|
{
|
||||||
rec_t* split_rec = btr_cur_get_rec(cursor);
|
const rec_t *split_rec= btr_cur_get_rec(cursor);
|
||||||
const page_t* page = page_align(split_rec);
|
const page_t *page= btr_cur_get_page(cursor);
|
||||||
|
const rec_t *const last= page + page_header_get_offs(page, PAGE_LAST_INSERT);
|
||||||
|
|
||||||
if (page_header_get_ptr(page, PAGE_LAST_INSERT)
|
if (page_is_comp(page))
|
||||||
!= page_rec_get_next(split_rec)) {
|
{
|
||||||
return NULL;
|
if (last != page_rec_next_get<true>(page, split_rec))
|
||||||
}
|
return nullptr;
|
||||||
|
/* The metadata record must be present in the leftmost leaf page
|
||||||
|
of the clustered index, if and only if index->is_instant().
|
||||||
|
However, during innobase_instant_try(), index->is_instant() would
|
||||||
|
already hold when row_ins_clust_index_entry_low() is being invoked
|
||||||
|
to insert the the metadata record. So, we can only assert that
|
||||||
|
when the metadata record exists, index->is_instant() must hold. */
|
||||||
|
const rec_t *const infimum= page + PAGE_NEW_INFIMUM;
|
||||||
|
ut_ad(!page_is_leaf(page) || page_has_prev(page) ||
|
||||||
|
cursor->index()->is_instant() ||
|
||||||
|
!(rec_get_info_bits(page_rec_next_get<true>(page, infimum), true) &
|
||||||
|
REC_INFO_MIN_REC_FLAG));
|
||||||
|
/* If the convergence is in the middle of a page, include also the
|
||||||
|
record immediately before the new insert to the upper page.
|
||||||
|
Otherwise, we could repeatedly move from page to page lots of
|
||||||
|
records smaller than the convergence point. */
|
||||||
|
if (split_rec == infimum ||
|
||||||
|
split_rec == page_rec_next_get<true>(page, infimum))
|
||||||
|
split_rec= page_rec_next_get<true>(page, split_rec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (last != page_rec_next_get<false>(page, split_rec))
|
||||||
|
return nullptr;
|
||||||
|
const rec_t *const infimum= page + PAGE_OLD_INFIMUM;
|
||||||
|
ut_ad(!page_is_leaf(page) || page_has_prev(page) ||
|
||||||
|
cursor->index()->is_instant() ||
|
||||||
|
!(rec_get_info_bits(page_rec_next_get<false>(page, infimum), false) &
|
||||||
|
REC_INFO_MIN_REC_FLAG));
|
||||||
|
if (split_rec == infimum ||
|
||||||
|
split_rec == page_rec_next_get<false>(page, infimum))
|
||||||
|
split_rec= page_rec_next_get<false>(page, split_rec);
|
||||||
|
}
|
||||||
|
|
||||||
/* The metadata record must be present in the leftmost leaf page
|
return const_cast<rec_t*>(split_rec);
|
||||||
of the clustered index, if and only if index->is_instant().
|
|
||||||
However, during innobase_instant_try(), index->is_instant()
|
|
||||||
would already hold when row_ins_clust_index_entry_low()
|
|
||||||
is being invoked to insert the the metadata record.
|
|
||||||
So, we can only assert that when the metadata record exists,
|
|
||||||
index->is_instant() must hold. */
|
|
||||||
ut_ad(!page_is_leaf(page) || page_has_prev(page)
|
|
||||||
|| cursor->index()->is_instant()
|
|
||||||
|| !(rec_get_info_bits(page_rec_get_next_const(
|
|
||||||
page_get_infimum_rec(page)),
|
|
||||||
cursor->index()->table->not_redundant())
|
|
||||||
& REC_INFO_MIN_REC_FLAG));
|
|
||||||
|
|
||||||
const rec_t* infimum = page_get_infimum_rec(page);
|
|
||||||
|
|
||||||
/* If the convergence is in the middle of a page, include also
|
|
||||||
the record immediately before the new insert to the upper
|
|
||||||
page. Otherwise, we could repeatedly move from page to page
|
|
||||||
lots of records smaller than the convergence point. */
|
|
||||||
|
|
||||||
if (split_rec == infimum
|
|
||||||
|| split_rec == page_rec_get_next_const(infimum)) {
|
|
||||||
split_rec = page_rec_get_next(split_rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
return split_rec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Decide if the page should be split at the convergence point of inserts
|
/** Decide if the page should be split at the convergence point of inserts
|
||||||
converging to the right.
|
converging to the right.
|
||||||
@param[in] cursor insert position
|
@param cursor insert position
|
||||||
@param[out] split_rec if split recommended, the first record
|
@param split_rec if split recommended, the first record on the right
|
||||||
on the right half page, or
|
half page, or nullptr if the to-be-inserted record should be first
|
||||||
NULL if the to-be-inserted record
|
|
||||||
should be first
|
|
||||||
@return whether split is recommended */
|
@return whether split is recommended */
|
||||||
bool
|
bool
|
||||||
btr_page_get_split_rec_to_right(const btr_cur_t* cursor, rec_t** split_rec)
|
btr_page_get_split_rec_to_right(const btr_cur_t *cursor, rec_t **split_rec)
|
||||||
|
noexcept
|
||||||
{
|
{
|
||||||
rec_t* insert_point = btr_cur_get_rec(cursor);
|
const rec_t *insert_point= btr_cur_get_rec(cursor);
|
||||||
const page_t* page = page_align(insert_point);
|
const page_t *page= btr_cur_get_page(cursor);
|
||||||
|
|
||||||
/* We use eager heuristics: if the new insert would be right after
|
/* We use eager heuristics: if the new insert would be right after
|
||||||
the previous insert on the same page, we assume that there is a
|
the previous insert on the same page, we assume that there is a
|
||||||
pattern of sequential inserts here. */
|
pattern of sequential inserts here. */
|
||||||
|
if (page + page_header_get_offs(page, PAGE_LAST_INSERT) != insert_point)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (page_header_get_ptr(page, PAGE_LAST_INSERT) != insert_point) {
|
if (page_is_comp(page))
|
||||||
return false;
|
{
|
||||||
}
|
const rec_t *const supremum= page + PAGE_NEW_SUPREMUM;
|
||||||
|
insert_point= page_rec_next_get<true>(page, insert_point);
|
||||||
|
if (!insert_point);
|
||||||
|
else if (insert_point == supremum)
|
||||||
|
insert_point= nullptr;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
insert_point= page_rec_next_get<true>(page, insert_point);
|
||||||
|
if (insert_point == supremum)
|
||||||
|
insert_point= nullptr;
|
||||||
|
/* If there are >= 2 user records up from the insert point,
|
||||||
|
split all but 1 off. We want to keep one because then sequential
|
||||||
|
inserts can do the necessary checks of the right search position
|
||||||
|
just by looking at the records on this page. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const rec_t *const supremum= page + PAGE_OLD_SUPREMUM;
|
||||||
|
insert_point= page_rec_next_get<false>(page, insert_point);
|
||||||
|
if (!insert_point);
|
||||||
|
else if (insert_point == supremum)
|
||||||
|
insert_point= nullptr;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
insert_point= page_rec_next_get<false>(page, insert_point);
|
||||||
|
if (insert_point == supremum)
|
||||||
|
insert_point= nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
insert_point = page_rec_get_next(insert_point);
|
*split_rec= const_cast<rec_t*>(insert_point);
|
||||||
|
return true;
|
||||||
if (!insert_point || page_rec_is_supremum(insert_point)) {
|
|
||||||
insert_point = NULL;
|
|
||||||
} else {
|
|
||||||
insert_point = page_rec_get_next(insert_point);
|
|
||||||
if (page_rec_is_supremum(insert_point)) {
|
|
||||||
insert_point = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there are >= 2 user records up from the insert
|
|
||||||
point, split all but 1 off. We want to keep one because
|
|
||||||
then sequential inserts can use the adaptive hash
|
|
||||||
index, as they can do the necessary checks of the right
|
|
||||||
search position just by looking at the records on this
|
|
||||||
page. */
|
|
||||||
}
|
|
||||||
|
|
||||||
*split_rec = insert_point;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************//**
|
/*************************************************************//**
|
||||||
|
|
@ -4695,31 +4724,31 @@ btr_index_rec_validate_report(
|
||||||
<< " of table " << index->table->name
|
<< " of table " << index->table->name
|
||||||
<< ", page " << page_id_t(page_get_space_id(page),
|
<< ", page " << page_id_t(page_get_space_id(page),
|
||||||
page_get_page_no(page))
|
page_get_page_no(page))
|
||||||
<< ", at offset " << page_offset(rec);
|
<< ", at offset " << rec - page;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
Checks the size and number of fields in a record based on the definition of
|
Checks the size and number of fields in a record based on the definition of
|
||||||
the index.
|
the index.
|
||||||
@return TRUE if ok */
|
@return TRUE if ok */
|
||||||
ibool
|
bool
|
||||||
btr_index_rec_validate(
|
btr_index_rec_validate(
|
||||||
/*===================*/
|
/*===================*/
|
||||||
const rec_t* rec, /*!< in: index record */
|
const page_cur_t& cur, /*!< in: cursor to index record */
|
||||||
const dict_index_t* index, /*!< in: index */
|
const dict_index_t* index, /*!< in: index */
|
||||||
ibool dump_on_error) /*!< in: TRUE if the function
|
bool dump_on_error) /*!< in: true if the function
|
||||||
should print hex dump of record
|
should print hex dump of record
|
||||||
and page on error */
|
and page on error */
|
||||||
|
noexcept
|
||||||
{
|
{
|
||||||
ulint len;
|
ulint len;
|
||||||
const page_t* page;
|
const rec_t* rec = page_cur_get_rec(&cur);
|
||||||
|
const page_t* page = cur.block->page.frame;
|
||||||
mem_heap_t* heap = NULL;
|
mem_heap_t* heap = NULL;
|
||||||
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
|
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
|
||||||
rec_offs* offsets = offsets_;
|
rec_offs* offsets = offsets_;
|
||||||
rec_offs_init(offsets_);
|
rec_offs_init(offsets_);
|
||||||
|
|
||||||
page = page_align(rec);
|
|
||||||
|
|
||||||
ut_ad(index->n_core_fields);
|
ut_ad(index->n_core_fields);
|
||||||
|
|
||||||
if (index->is_ibuf()) {
|
if (index->is_ibuf()) {
|
||||||
|
|
@ -4900,7 +4929,7 @@ btr_index_page_validate(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!btr_index_rec_validate(cur.rec, index, TRUE)) {
|
if (!btr_index_rec_validate(cur, index, TRUE)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,8 @@ inline void PageBulk::insertPage(rec_t *rec, rec_offs *offsets)
|
||||||
const ulint rec_size= rec_offs_size(offsets);
|
const ulint rec_size= rec_offs_size(offsets);
|
||||||
const ulint extra_size= rec_offs_extra_size(offsets);
|
const ulint extra_size= rec_offs_extra_size(offsets);
|
||||||
ut_ad(page_align(m_heap_top + rec_size) == m_page);
|
ut_ad(page_align(m_heap_top + rec_size) == m_page);
|
||||||
ut_d(const bool is_leaf= page_rec_is_leaf(m_cur_rec));
|
ut_ad(page_align(m_cur_rec) == m_page);
|
||||||
|
ut_d(const bool is_leaf= page_is_leaf(m_page));
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
/* Check whether records are in order. */
|
/* Check whether records are in order. */
|
||||||
|
|
@ -180,8 +181,8 @@ inline void PageBulk::insertPage(rec_t *rec, rec_offs *offsets)
|
||||||
/* Insert the record in the linked list. */
|
/* Insert the record in the linked list. */
|
||||||
if (fmt != REDUNDANT)
|
if (fmt != REDUNDANT)
|
||||||
{
|
{
|
||||||
const rec_t *next_rec= m_page +
|
const rec_t *next_rec=
|
||||||
page_offset(m_cur_rec + mach_read_from_2(m_cur_rec - REC_NEXT));
|
m_cur_rec + int16_t(mach_read_from_2(m_cur_rec - REC_NEXT));
|
||||||
if (fmt != COMPRESSED)
|
if (fmt != COMPRESSED)
|
||||||
m_mtr.write<2>(*m_block, m_cur_rec - REC_NEXT,
|
m_mtr.write<2>(*m_block, m_cur_rec - REC_NEXT,
|
||||||
static_cast<uint16_t>(insert_rec - m_cur_rec));
|
static_cast<uint16_t>(insert_rec - m_cur_rec));
|
||||||
|
|
@ -204,7 +205,8 @@ inline void PageBulk::insertPage(rec_t *rec, rec_offs *offsets)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(const_cast<rec_t*>(rec) - REC_NEXT, m_cur_rec - REC_NEXT, 2);
|
memcpy(const_cast<rec_t*>(rec) - REC_NEXT, m_cur_rec - REC_NEXT, 2);
|
||||||
m_mtr.write<2>(*m_block, m_cur_rec - REC_NEXT, page_offset(insert_rec));
|
m_mtr.write<2>(*m_block, m_cur_rec - REC_NEXT,
|
||||||
|
uintptr_t(insert_rec - m_page));
|
||||||
rec_set_bit_field_1(const_cast<rec_t*>(rec), 0,
|
rec_set_bit_field_1(const_cast<rec_t*>(rec), 0,
|
||||||
REC_OLD_N_OWNED, REC_N_OWNED_MASK, REC_N_OWNED_SHIFT);
|
REC_OLD_N_OWNED, REC_N_OWNED_MASK, REC_N_OWNED_SHIFT);
|
||||||
rec_set_bit_field_2(const_cast<rec_t*>(rec),
|
rec_set_bit_field_2(const_cast<rec_t*>(rec),
|
||||||
|
|
@ -214,7 +216,7 @@ inline void PageBulk::insertPage(rec_t *rec, rec_offs *offsets)
|
||||||
|
|
||||||
if (fmt == COMPRESSED)
|
if (fmt == COMPRESSED)
|
||||||
/* We already wrote the record. Log is written in PageBulk::compress(). */;
|
/* We already wrote the record. Log is written in PageBulk::compress(). */;
|
||||||
else if (page_offset(m_cur_rec) ==
|
else if (m_cur_rec - m_page ==
|
||||||
(fmt == REDUNDANT ? PAGE_OLD_INFIMUM : PAGE_NEW_INFIMUM))
|
(fmt == REDUNDANT ? PAGE_OLD_INFIMUM : PAGE_NEW_INFIMUM))
|
||||||
m_mtr.memcpy(*m_block, m_heap_top, rec - extra_size, rec_size);
|
m_mtr.memcpy(*m_block, m_heap_top, rec - extra_size, rec_size);
|
||||||
else
|
else
|
||||||
|
|
@ -246,7 +248,7 @@ inline void PageBulk::insertPage(rec_t *rec, rec_offs *offsets)
|
||||||
if (len > 2)
|
if (len > 2)
|
||||||
{
|
{
|
||||||
memcpy(b, c, len);
|
memcpy(b, c, len);
|
||||||
m_mtr.memmove(*m_block, page_offset(b), page_offset(c), len);
|
m_mtr.memmove(*m_block, b - m_page, c - m_page, len);
|
||||||
c= cm;
|
c= cm;
|
||||||
b= bm;
|
b= bm;
|
||||||
r= rm;
|
r= rm;
|
||||||
|
|
@ -285,7 +287,7 @@ no_data:
|
||||||
{
|
{
|
||||||
m_mtr.memcpy<mtr_t::FORCED>(*m_block, b, r, m_cur_rec - c);
|
m_mtr.memcpy<mtr_t::FORCED>(*m_block, b, r, m_cur_rec - c);
|
||||||
memcpy(bd, cd, len);
|
memcpy(bd, cd, len);
|
||||||
m_mtr.memmove(*m_block, page_offset(bd), page_offset(cd), len);
|
m_mtr.memmove(*m_block, bd - m_page, cd - m_page, len);
|
||||||
c= cdm;
|
c= cdm;
|
||||||
b= rdm - rd + bd;
|
b= rdm - rd + bd;
|
||||||
r= rdm;
|
r= rdm;
|
||||||
|
|
@ -430,7 +432,7 @@ inline void PageBulk::finishPage()
|
||||||
if (count == (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2)
|
if (count == (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2)
|
||||||
{
|
{
|
||||||
slot-= PAGE_DIR_SLOT_SIZE;
|
slot-= PAGE_DIR_SLOT_SIZE;
|
||||||
mach_write_to_2(slot, page_offset(insert_rec));
|
mach_write_to_2(slot, insert_rec - m_page);
|
||||||
page_rec_set_n_owned<false>(m_block, insert_rec, count, false, &m_mtr);
|
page_rec_set_n_owned<false>(m_block, insert_rec, count, false, &m_mtr);
|
||||||
count= 0;
|
count= 0;
|
||||||
}
|
}
|
||||||
|
|
@ -469,7 +471,7 @@ inline void PageBulk::finishPage()
|
||||||
m_mtr.memcpy(*m_block, PAGE_HEADER + m_page, page_header,
|
m_mtr.memcpy(*m_block, PAGE_HEADER + m_page, page_header,
|
||||||
sizeof page_header);
|
sizeof page_header);
|
||||||
m_mtr.write<2>(*m_block, PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no);
|
m_mtr.write<2>(*m_block, PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no);
|
||||||
m_mtr.memcpy(*m_block, page_offset(slot), slot0 - slot);
|
m_mtr.memcpy(*m_block, slot - m_page, slot0 - slot);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -701,7 +703,7 @@ PageBulk::copyOut(
|
||||||
ULINT_UNDEFINED, &m_heap);
|
ULINT_UNDEFINED, &m_heap);
|
||||||
mach_write_to_2(rec - REC_NEXT, m_is_comp
|
mach_write_to_2(rec - REC_NEXT, m_is_comp
|
||||||
? static_cast<uint16_t>
|
? static_cast<uint16_t>
|
||||||
(PAGE_NEW_SUPREMUM - page_offset(rec))
|
(PAGE_NEW_SUPREMUM - (rec - m_page))
|
||||||
: PAGE_OLD_SUPREMUM);
|
: PAGE_OLD_SUPREMUM);
|
||||||
|
|
||||||
/* Set related members */
|
/* Set related members */
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ unreadable:
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_ad(page_cur_is_before_first(&cur.page_cur));
|
ut_ad(page_cur_is_before_first(&cur.page_cur));
|
||||||
ut_ad(page_is_leaf(cur.page_cur.block->page.frame));
|
ut_ad(page_is_leaf(btr_cur_get_page(&cur)));
|
||||||
|
|
||||||
const rec_t* rec = page_cur_move_to_next(&cur.page_cur);
|
const rec_t* rec = page_cur_move_to_next(&cur.page_cur);
|
||||||
const ulint comp = dict_table_is_comp(index->table);
|
const ulint comp = dict_table_is_comp(index->table);
|
||||||
|
|
@ -591,14 +591,17 @@ btr_intention_t btr_cur_get_and_clear_intention(btr_latch_mode *latch_mode)
|
||||||
|
|
||||||
/** @return whether the distance between two records is at most the
|
/** @return whether the distance between two records is at most the
|
||||||
specified value */
|
specified value */
|
||||||
|
template<bool comp>
|
||||||
static bool
|
static bool
|
||||||
page_rec_distance_is_at_most(const rec_t *left, const rec_t *right, ulint val)
|
page_rec_distance_is_at_most(const page_t *page, const rec_t *left,
|
||||||
|
const rec_t *right, ulint val)
|
||||||
|
noexcept
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (left == right)
|
if (left == right)
|
||||||
return true;
|
return true;
|
||||||
left= page_rec_get_next_const(left);
|
left= page_rec_next_get<comp>(page, left);
|
||||||
}
|
}
|
||||||
while (left && val--);
|
while (left && val--);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -669,25 +672,52 @@ btr_cur_will_modify_tree(
|
||||||
}
|
}
|
||||||
/* check delete will cause. (BTR_INTENTION_BOTH
|
/* check delete will cause. (BTR_INTENTION_BOTH
|
||||||
or BTR_INTENTION_DELETE) */
|
or BTR_INTENTION_DELETE) */
|
||||||
if (n_recs <= max_nodes_deleted * 2
|
if (n_recs <= max_nodes_deleted * 2) {
|
||||||
|| page_rec_is_first(rec, page)) {
|
|
||||||
/* The cursor record can be the left most record
|
/* The cursor record can be the left most record
|
||||||
in this page. */
|
in this page. */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_has_prev(page)
|
if (page_is_comp(page)) {
|
||||||
&& page_rec_distance_is_at_most(
|
const rec_t *const infimum
|
||||||
page_get_infimum_rec(page), rec,
|
= page + PAGE_NEW_INFIMUM;
|
||||||
max_nodes_deleted)) {
|
if (page_rec_next_get<true>(page, infimum)
|
||||||
return true;
|
== rec) {
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
if (page_has_next(page)
|
if (page_has_prev(page)
|
||||||
&& page_rec_distance_is_at_most(
|
&& page_rec_distance_is_at_most<true>(
|
||||||
rec, page_get_supremum_rec(page),
|
page, infimum, rec,
|
||||||
max_nodes_deleted)) {
|
max_nodes_deleted)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
if (page_has_next(page)
|
||||||
|
&& page_rec_distance_is_at_most<true>(
|
||||||
|
page, rec,
|
||||||
|
page + PAGE_NEW_SUPREMUM,
|
||||||
|
max_nodes_deleted)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const rec_t *const infimum
|
||||||
|
= page + PAGE_OLD_INFIMUM;
|
||||||
|
if (page_rec_next_get<false>(page, infimum)
|
||||||
|
== rec) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (page_has_prev(page)
|
||||||
|
&& page_rec_distance_is_at_most<false>(
|
||||||
|
page, infimum, rec,
|
||||||
|
max_nodes_deleted)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (page_has_next(page)
|
||||||
|
&& page_rec_distance_is_at_most<false>(
|
||||||
|
page, rec,
|
||||||
|
page + PAGE_OLD_SUPREMUM,
|
||||||
|
max_nodes_deleted)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete at leftmost record in a page causes delete
|
/* Delete at leftmost record in a page causes delete
|
||||||
|
|
@ -2308,7 +2338,7 @@ btr_cur_ins_lock_and_undo(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!index->is_primary() || !page_is_leaf(page_align(rec))) {
|
if (!index->is_primary() || !page_is_leaf(btr_cur_get_page(cursor))) {
|
||||||
return DB_SUCCESS;
|
return DB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2997,7 +3027,8 @@ static dberr_t btr_cur_upd_rec_sys(buf_block_t *block, rec_t *rec,
|
||||||
To save space, we must have d>6, that is, the complete DB_TRX_ID and
|
To save space, we must have d>6, that is, the complete DB_TRX_ID and
|
||||||
the first byte(s) of DB_ROLL_PTR must match the previous record. */
|
the first byte(s) of DB_ROLL_PTR must match the previous record. */
|
||||||
memcpy(dest, src, d);
|
memcpy(dest, src, d);
|
||||||
mtr->memmove(*block, page_offset(dest), page_offset(src), d);
|
mtr->memmove(*block, dest - block->page.frame, src - block->page.frame,
|
||||||
|
d);
|
||||||
dest+= d;
|
dest+= d;
|
||||||
len-= d;
|
len-= d;
|
||||||
/* DB_TRX_ID,DB_ROLL_PTR must be unique in each record when
|
/* DB_TRX_ID,DB_ROLL_PTR must be unique in each record when
|
||||||
|
|
@ -3185,8 +3216,8 @@ void btr_cur_upd_rec_in_place(rec_t *rec, const dict_index_t *index,
|
||||||
default:
|
default:
|
||||||
mtr->memset(
|
mtr->memset(
|
||||||
block,
|
block,
|
||||||
page_offset(rec_get_field_start_offs(
|
rec_get_field_start_offs(rec, n) + rec
|
||||||
rec, n) + rec),
|
- block->page.frame,
|
||||||
size, 0);
|
size, 0);
|
||||||
}
|
}
|
||||||
ulint l = rec_get_1byte_offs_flag(rec)
|
ulint l = rec_get_1byte_offs_flag(rec)
|
||||||
|
|
@ -3936,7 +3967,9 @@ btr_cur_pess_upd_restore_supremum(
|
||||||
|
|
||||||
lock_rec_reset_and_inherit_gap_locks(*prev_block, block_id,
|
lock_rec_reset_and_inherit_gap_locks(*prev_block, block_id,
|
||||||
PAGE_HEAP_NO_SUPREMUM,
|
PAGE_HEAP_NO_SUPREMUM,
|
||||||
page_rec_get_heap_no(rec));
|
page_is_comp(page)
|
||||||
|
? rec_get_heap_no_new(rec)
|
||||||
|
: rec_get_heap_no_old(rec));
|
||||||
return DB_SUCCESS;
|
return DB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4418,7 +4451,7 @@ return_after_reservations:
|
||||||
template<bool flag>
|
template<bool flag>
|
||||||
void btr_rec_set_deleted(buf_block_t *block, rec_t *rec, mtr_t *mtr)
|
void btr_rec_set_deleted(buf_block_t *block, rec_t *rec, mtr_t *mtr)
|
||||||
{
|
{
|
||||||
if (page_rec_is_comp(rec))
|
if (UNIV_LIKELY(page_is_comp(block->page.frame) != 0))
|
||||||
{
|
{
|
||||||
byte *b= &rec[-REC_NEW_INFO_BITS];
|
byte *b= &rec[-REC_NEW_INFO_BITS];
|
||||||
const byte v= flag
|
const byte v= flag
|
||||||
|
|
@ -4661,7 +4694,7 @@ btr_cur_optimistic_delete(
|
||||||
page_t* page = buf_block_get_frame(block);
|
page_t* page = buf_block_get_frame(block);
|
||||||
page_zip_des_t* page_zip= buf_block_get_page_zip(block);
|
page_zip_des_t* page_zip= buf_block_get_page_zip(block);
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(rec_get_info_bits(rec, page_rec_is_comp(rec))
|
if (UNIV_UNLIKELY(rec_get_info_bits(rec, page_is_comp(page))
|
||||||
& REC_INFO_MIN_REC_FLAG)) {
|
& REC_INFO_MIN_REC_FLAG)) {
|
||||||
/* This should be rolling back instant ADD COLUMN.
|
/* This should be rolling back instant ADD COLUMN.
|
||||||
If this is a recovered transaction, then
|
If this is a recovered transaction, then
|
||||||
|
|
@ -4829,7 +4862,7 @@ btr_cur_pessimistic_delete(
|
||||||
|
|
||||||
if (page_is_leaf(page)) {
|
if (page_is_leaf(page)) {
|
||||||
const bool is_metadata = rec_is_metadata(
|
const bool is_metadata = rec_is_metadata(
|
||||||
rec, page_rec_is_comp(rec));
|
rec, page_is_comp(block->page.frame));
|
||||||
if (UNIV_UNLIKELY(is_metadata)) {
|
if (UNIV_UNLIKELY(is_metadata)) {
|
||||||
/* This should be rolling back instant ALTER TABLE.
|
/* This should be rolling back instant ALTER TABLE.
|
||||||
If this is a recovered transaction, then
|
If this is a recovered transaction, then
|
||||||
|
|
@ -5972,7 +6005,8 @@ struct btr_blob_log_check_t {
|
||||||
uint32_t page_no = FIL_NULL;
|
uint32_t page_no = FIL_NULL;
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(m_op == BTR_STORE_INSERT_BULK)) {
|
if (UNIV_UNLIKELY(m_op == BTR_STORE_INSERT_BULK)) {
|
||||||
offs = page_offset(*m_rec);
|
offs = *m_rec - (*m_block)->page.frame;
|
||||||
|
ut_ad(offs == page_offset(*m_rec));
|
||||||
page_no = (*m_block)->page.id().page_no();
|
page_no = (*m_block)->page.id().page_no();
|
||||||
(*m_block)->page.fix();
|
(*m_block)->page.fix();
|
||||||
ut_ad(page_no != FIL_NULL);
|
ut_ad(page_no != FIL_NULL);
|
||||||
|
|
@ -6081,7 +6115,7 @@ btr_store_big_rec_extern_fields(
|
||||||
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
|
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
|
||||||
ut_a(dict_index_is_clust(index));
|
ut_a(dict_index_is_clust(index));
|
||||||
|
|
||||||
if (!fil_page_index_page_check(page_align(rec))) {
|
if (!fil_page_index_page_check(btr_pcur_get_page(pcur))) {
|
||||||
if (op != BTR_STORE_INSERT_BULK) {
|
if (op != BTR_STORE_INSERT_BULK) {
|
||||||
return DB_PAGE_CORRUPTED;
|
return DB_PAGE_CORRUPTED;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -684,7 +684,7 @@ btr_search_update_hash_ref(
|
||||||
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
|
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
|
||||||
|
|
||||||
ut_ad(block->page.lock.have_x() || block->page.lock.have_s());
|
ut_ad(block->page.lock.have_x() || block->page.lock.have_s());
|
||||||
ut_ad(page_align(btr_cur_get_rec(cursor)) == block->page.frame);
|
ut_ad(btr_cur_get_page(cursor) == block->page.frame);
|
||||||
ut_ad(page_is_leaf(block->page.frame));
|
ut_ad(page_is_leaf(block->page.frame));
|
||||||
assert_block_ahi_valid(block);
|
assert_block_ahi_valid(block);
|
||||||
|
|
||||||
|
|
@ -1278,21 +1278,30 @@ retry:
|
||||||
/* Calculate and cache fold values into an array for fast deletion
|
/* Calculate and cache fold values into an array for fast deletion
|
||||||
from the hash index */
|
from the hash index */
|
||||||
|
|
||||||
rec = page_get_infimum_rec(page);
|
const auto comp = page_is_comp(page);
|
||||||
rec = page_rec_get_next_low(rec, page_is_comp(page));
|
|
||||||
|
|
||||||
ulint* folds;
|
ulint* folds;
|
||||||
ulint n_cached = 0;
|
ulint n_cached = 0;
|
||||||
ulint prev_fold = 0;
|
ulint prev_fold = 0;
|
||||||
|
|
||||||
if (rec && rec_is_metadata(rec, *index)) {
|
if (UNIV_LIKELY(comp != 0)) {
|
||||||
rec = page_rec_get_next_low(rec, page_is_comp(page));
|
rec = page_rec_next_get<true>(page, page + PAGE_NEW_INFIMUM);
|
||||||
if (!--n_recs) {
|
if (rec && rec_is_metadata(rec, TRUE)) {
|
||||||
/* The page only contains the hidden metadata record
|
rec = page_rec_next_get<true>(page, rec);
|
||||||
for instant ALTER TABLE that the adaptive hash index
|
skipped_metadata:
|
||||||
never points to. */
|
if (!--n_recs) {
|
||||||
folds = nullptr;
|
/* The page only contains the hidden
|
||||||
goto all_deleted;
|
metadata record for instant ALTER
|
||||||
|
TABLE that the adaptive hash index
|
||||||
|
never points to. */
|
||||||
|
folds = nullptr;
|
||||||
|
goto all_deleted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rec = page_rec_next_get<false>(page, page + PAGE_OLD_INFIMUM);
|
||||||
|
if (rec && rec_is_metadata(rec, FALSE)) {
|
||||||
|
rec = page_rec_next_get<false>(page, rec);
|
||||||
|
goto skipped_metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1323,9 +1332,16 @@ retry:
|
||||||
folds[n_cached++] = fold;
|
folds[n_cached++] = fold;
|
||||||
|
|
||||||
next_rec:
|
next_rec:
|
||||||
rec = page_rec_get_next_low(rec, page_rec_is_comp(rec));
|
if (comp) {
|
||||||
if (!rec || page_rec_is_supremum(rec)) {
|
rec = page_rec_next_get<true>(page, rec);
|
||||||
break;
|
if (!rec || rec == page + PAGE_NEW_SUPREMUM) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rec = page_rec_next_get<false>(page, rec);
|
||||||
|
if (!rec || rec == page + PAGE_OLD_SUPREMUM) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
prev_fold = fold;
|
prev_fold = fold;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -898,7 +898,8 @@ rec_corrupted:
|
||||||
static_assert(FIL_NULL == 0xffffffff, "compatibility");
|
static_assert(FIL_NULL == 0xffffffff, "compatibility");
|
||||||
static_assert(DICT_FLD__SYS_INDEXES__PAGE_NO ==
|
static_assert(DICT_FLD__SYS_INDEXES__PAGE_NO ==
|
||||||
DICT_FLD__SYS_INDEXES__SPACE + 1, "compatibility");
|
DICT_FLD__SYS_INDEXES__SPACE + 1, "compatibility");
|
||||||
mtr->memset(btr_pcur_get_block(pcur), page_offset(p + 4), 4, 0xff);
|
mtr->memset(btr_pcur_get_block(pcur), p + 4 - btr_pcur_get_page(pcur),
|
||||||
|
4, 0xff);
|
||||||
btr_free_if_exists(s, root_page_no, mach_read_from_8(rec + 8), mtr);
|
btr_free_if_exists(s, root_page_no, mach_read_from_8(rec + 8), mtr);
|
||||||
}
|
}
|
||||||
s->release();
|
s->release();
|
||||||
|
|
|
||||||
|
|
@ -974,7 +974,7 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index,
|
||||||
rec = page_rec_get_next(cursor.page_cur.rec);
|
rec = page_rec_get_next(cursor.page_cur.rec);
|
||||||
const ulint n_core = index->n_core_fields;
|
const ulint n_core = index->n_core_fields;
|
||||||
|
|
||||||
if (rec && !page_rec_is_supremum(rec)) {
|
if (rec && rec != page_get_supremum_rec(page)) {
|
||||||
not_empty_flag = 1;
|
not_empty_flag = 1;
|
||||||
offsets_rec = rec_get_offsets(rec, index, offsets_rec,
|
offsets_rec = rec_get_offsets(rec, index, offsets_rec,
|
||||||
n_core,
|
n_core,
|
||||||
|
|
@ -986,10 +986,11 @@ btr_estimate_number_of_different_key_vals(dict_index_t* index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!page_rec_is_supremum(rec)) {
|
while (rec != page_get_supremum_rec(page)) {
|
||||||
ulint matched_fields;
|
ulint matched_fields;
|
||||||
rec_t* next_rec = page_rec_get_next(rec);
|
rec_t* next_rec = page_rec_get_next(rec);
|
||||||
if (!next_rec || page_rec_is_supremum(next_rec)) {
|
if (!next_rec
|
||||||
|
|| next_rec == page_get_supremum_rec(page)) {
|
||||||
total_external_size +=
|
total_external_size +=
|
||||||
btr_rec_get_externally_stored_len(
|
btr_rec_get_externally_stored_len(
|
||||||
rec, offsets_rec);
|
rec, offsets_rec);
|
||||||
|
|
@ -1510,14 +1511,12 @@ dict_stats_analyze_index_level(
|
||||||
/* If rec and prev_rec are on different pages, then prev_rec
|
/* If rec and prev_rec are on different pages, then prev_rec
|
||||||
must have been copied, because we hold latch only on the page
|
must have been copied, because we hold latch only on the page
|
||||||
where rec resides. */
|
where rec resides. */
|
||||||
if (prev_rec != NULL
|
ut_ad(!prev_rec
|
||||||
&& page_align(rec) != page_align(prev_rec)) {
|
|| btr_pcur_get_page(&pcur) == page_align(prev_rec)
|
||||||
|
|| prev_rec_is_copied);
|
||||||
|
|
||||||
ut_a(prev_rec_is_copied);
|
rec_is_last_on_page = page_rec_get_next_const(rec)
|
||||||
}
|
== page_get_supremum_rec(btr_pcur_get_page(&pcur));
|
||||||
|
|
||||||
rec_is_last_on_page =
|
|
||||||
page_rec_is_supremum(page_rec_get_next_const(rec));
|
|
||||||
|
|
||||||
/* increment the pages counter at the end of each page */
|
/* increment the pages counter at the end of each page */
|
||||||
if (rec_is_last_on_page) {
|
if (rec_is_last_on_page) {
|
||||||
|
|
@ -1534,7 +1533,8 @@ dict_stats_analyze_index_level(
|
||||||
|
|
||||||
if (level == 0
|
if (level == 0
|
||||||
&& !srv_stats_include_delete_marked
|
&& !srv_stats_include_delete_marked
|
||||||
&& rec_get_deleted_flag(rec, page_rec_is_comp(rec))) {
|
&& rec_get_deleted_flag(
|
||||||
|
rec, page_is_comp(btr_pcur_get_page(&pcur)))) {
|
||||||
if (rec_is_last_on_page
|
if (rec_is_last_on_page
|
||||||
&& !prev_rec_is_copied
|
&& !prev_rec_is_copied
|
||||||
&& prev_rec != NULL) {
|
&& prev_rec != NULL) {
|
||||||
|
|
@ -1699,34 +1699,23 @@ func_exit:
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
Gets the pointer to the next non delete-marked record on the page.
|
Gets the pointer to the next non delete-marked record on the page.
|
||||||
If all subsequent records are delete-marked, then this function
|
If all subsequent records are delete-marked, then this function
|
||||||
will return the supremum record.
|
will return the supremum record.
|
||||||
@return pointer to next non delete-marked record or pointer to supremum */
|
@return pointer to next non delete-marked record or pointer to supremum */
|
||||||
|
template<bool comp>
|
||||||
static
|
static
|
||||||
const rec_t*
|
const rec_t*
|
||||||
page_rec_get_next_non_del_marked(
|
page_rec_get_next_non_del_marked(const page_t *page, const rec_t *rec)
|
||||||
/*=============================*/
|
|
||||||
const rec_t* rec) /*!< in: pointer to record */
|
|
||||||
{
|
{
|
||||||
const page_t *const page= page_align(rec);
|
ut_ad(!!page_is_comp(page) == comp);
|
||||||
|
ut_ad(page_align(rec) == page);
|
||||||
|
|
||||||
if (page_is_comp(page))
|
for (rec= page_rec_next_get<comp>(page, rec);
|
||||||
{
|
rec && rec_get_deleted_flag(rec, comp);
|
||||||
for (rec= page_rec_get_next_low(rec, TRUE);
|
rec= page_rec_next_get<comp>(page, rec));
|
||||||
rec && rec_get_deleted_flag(rec, TRUE);
|
return rec ? rec : page + (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM);
|
||||||
rec= page_rec_get_next_low(rec, TRUE));
|
|
||||||
return rec ? rec : page + PAGE_NEW_SUPREMUM;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (rec= page_rec_get_next_low(rec, FALSE);
|
|
||||||
rec && rec_get_deleted_flag(rec, FALSE);
|
|
||||||
rec= page_rec_get_next_low(rec, FALSE));
|
|
||||||
return rec ? rec : page + PAGE_OLD_SUPREMUM;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Scan a page, reading records from left to right and counting the number
|
/** Scan a page, reading records from left to right and counting the number
|
||||||
|
|
@ -1773,10 +1762,13 @@ dict_stats_scan_page(
|
||||||
this memory heap should never be used. */
|
this memory heap should never be used. */
|
||||||
mem_heap_t* heap = NULL;
|
mem_heap_t* heap = NULL;
|
||||||
ut_ad(!!n_core == page_is_leaf(page));
|
ut_ad(!!n_core == page_is_leaf(page));
|
||||||
const rec_t* (*get_next)(const rec_t*)
|
const rec_t* (*get_next)(const page_t*, const rec_t*)
|
||||||
= !n_core || srv_stats_include_delete_marked
|
= !n_core || srv_stats_include_delete_marked
|
||||||
? page_rec_get_next_const
|
? (page_is_comp(page)
|
||||||
: page_rec_get_next_non_del_marked;
|
? page_rec_next_get<true> : page_rec_next_get<false>)
|
||||||
|
: page_is_comp(page)
|
||||||
|
? page_rec_get_next_non_del_marked<true>
|
||||||
|
: page_rec_get_next_non_del_marked<false>;
|
||||||
|
|
||||||
const bool should_count_external_pages = n_external_pages != NULL;
|
const bool should_count_external_pages = n_external_pages != NULL;
|
||||||
|
|
||||||
|
|
@ -1784,9 +1776,9 @@ dict_stats_scan_page(
|
||||||
*n_external_pages = 0;
|
*n_external_pages = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = get_next(page_get_infimum_rec(page));
|
rec = get_next(page, page_get_infimum_rec(page));
|
||||||
|
|
||||||
if (!rec || page_rec_is_supremum(rec)) {
|
if (!rec || rec == page_get_supremum_rec(page)) {
|
||||||
/* the page is empty or contains only delete-marked records */
|
/* the page is empty or contains only delete-marked records */
|
||||||
*n_diff = 0;
|
*n_diff = 0;
|
||||||
*out_rec = NULL;
|
*out_rec = NULL;
|
||||||
|
|
@ -1801,11 +1793,11 @@ dict_stats_scan_page(
|
||||||
rec, offsets_rec);
|
rec, offsets_rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
next_rec = get_next(rec);
|
next_rec = get_next(page, rec);
|
||||||
|
|
||||||
*n_diff = 1;
|
*n_diff = 1;
|
||||||
|
|
||||||
while (next_rec && !page_rec_is_supremum(next_rec)) {
|
while (next_rec && next_rec != page_get_supremum_rec(page)) {
|
||||||
|
|
||||||
ulint matched_fields;
|
ulint matched_fields;
|
||||||
|
|
||||||
|
|
@ -1846,7 +1838,7 @@ dict_stats_scan_page(
|
||||||
rec, offsets_rec);
|
rec, offsets_rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
next_rec = get_next(next_rec);
|
next_rec = get_next(page, next_rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* offsets1,offsets2 should have been big enough */
|
/* offsets1,offsets2 should have been big enough */
|
||||||
|
|
@ -1908,8 +1900,8 @@ dict_stats_analyze_index_below_cur(
|
||||||
rec_offs_set_n_alloc(offsets2, size);
|
rec_offs_set_n_alloc(offsets2, size);
|
||||||
|
|
||||||
rec = btr_cur_get_rec(cur);
|
rec = btr_cur_get_rec(cur);
|
||||||
page = page_align(rec);
|
page = btr_cur_get_page(cur);
|
||||||
ut_ad(!page_rec_is_leaf(rec));
|
ut_ad(!page_is_leaf(page));
|
||||||
|
|
||||||
offsets_rec = rec_get_offsets(rec, index, offsets1, 0,
|
offsets_rec = rec_get_offsets(rec, index, offsets1, 0,
|
||||||
ULINT_UNDEFINED, &heap);
|
ULINT_UNDEFINED, &heap);
|
||||||
|
|
|
||||||
|
|
@ -446,8 +446,9 @@ Returns page offset of the first page in extent described by a descriptor.
|
||||||
static uint32_t xdes_get_offset(const xdes_t *descr)
|
static uint32_t xdes_get_offset(const xdes_t *descr)
|
||||||
{
|
{
|
||||||
ut_ad(descr);
|
ut_ad(descr);
|
||||||
return page_get_page_no(page_align(descr)) +
|
const page_t *page= page_align(descr);
|
||||||
uint32_t(((page_offset(descr) - XDES_ARR_OFFSET) / XDES_SIZE) *
|
return page_get_page_no(page) +
|
||||||
|
uint32_t(((descr - page - XDES_ARR_OFFSET) / XDES_SIZE) *
|
||||||
FSP_EXTENT_SIZE);
|
FSP_EXTENT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1507,7 +1508,8 @@ static void fsp_free_seg_inode(fil_space_t *space, fseg_inode_t *inode,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mtr->memset(iblock, page_offset(inode) + FSEG_ID, FSEG_INODE_SIZE, 0);
|
mtr->memset(iblock, inode - iblock->page.frame + FSEG_ID,
|
||||||
|
FSEG_INODE_SIZE, 0);
|
||||||
|
|
||||||
if (ULINT_UNDEFINED != fsp_seg_inode_page_find_used(iblock->page.frame,
|
if (ULINT_UNDEFINED != fsp_seg_inode_page_find_used(iblock->page.frame,
|
||||||
physical_size))
|
physical_size))
|
||||||
|
|
@ -1778,7 +1780,8 @@ page_alloc:
|
||||||
}
|
}
|
||||||
|
|
||||||
mtr->write<2>(*block, byte_offset + FSEG_HDR_OFFSET
|
mtr->write<2>(*block, byte_offset + FSEG_HDR_OFFSET
|
||||||
+ block->page.frame, page_offset(inode));
|
+ block->page.frame,
|
||||||
|
uintptr_t(inode - iblock->page.frame));
|
||||||
|
|
||||||
mtr->write<4>(*block, byte_offset + FSEG_HDR_PAGE_NO
|
mtr->write<4>(*block, byte_offset + FSEG_HDR_PAGE_NO
|
||||||
+ block->page.frame, iblock->page.id().page_no());
|
+ block->page.frame, iblock->page.id().page_no());
|
||||||
|
|
@ -1920,11 +1923,12 @@ fseg_alloc_free_extent(
|
||||||
mtr_t* mtr,
|
mtr_t* mtr,
|
||||||
dberr_t* err)
|
dberr_t* err)
|
||||||
{
|
{
|
||||||
ut_ad(!((page_offset(inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
|
ut_ad(iblock->page.frame == page_align(inode));
|
||||||
|
ut_ad(!((inode - iblock->page.frame - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
|
||||||
ut_ad(!memcmp(FSEG_MAGIC_N_BYTES, FSEG_MAGIC_N + inode, 4));
|
ut_ad(!memcmp(FSEG_MAGIC_N_BYTES, FSEG_MAGIC_N + inode, 4));
|
||||||
ut_d(space->modify_check(*mtr));
|
ut_d(space->modify_check(*mtr));
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(page_offset(inode) < FSEG_ARR_OFFSET))
|
if (UNIV_UNLIKELY(uintptr_t(inode - iblock->page.frame) < FSEG_ARR_OFFSET))
|
||||||
{
|
{
|
||||||
corrupted:
|
corrupted:
|
||||||
*err= DB_CORRUPTION;
|
*err= DB_CORRUPTION;
|
||||||
|
|
@ -2813,33 +2817,18 @@ remove:
|
||||||
return DB_SUCCESS;
|
return DB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Frees part of a segment. This function can be used to free
|
bool fseg_free_step(buf_block_t *block, size_t header, mtr_t *mtr
|
||||||
a segment by repeatedly calling this function in different
|
|
||||||
mini-transactions. Doing the freeing in a single mini-transaction
|
|
||||||
might result in too big a mini-transaction.
|
|
||||||
@param header segment header; NOTE: if the header resides on first
|
|
||||||
page of the frag list of the segment, this pointer
|
|
||||||
becomes obsolete after the last freeing step
|
|
||||||
@param mtr mini-transaction
|
|
||||||
@param ahi Drop the adaptive hash index
|
|
||||||
@return whether the freeing was completed */
|
|
||||||
bool
|
|
||||||
fseg_free_step(
|
|
||||||
fseg_header_t* header,
|
|
||||||
mtr_t* mtr
|
|
||||||
#ifdef BTR_CUR_HASH_ADAPT
|
#ifdef BTR_CUR_HASH_ADAPT
|
||||||
,bool ahi
|
, bool ahi
|
||||||
#endif /* BTR_CUR_HASH_ADAPT */
|
#endif /* BTR_CUR_HASH_ADAPT */
|
||||||
)
|
) noexcept
|
||||||
{
|
{
|
||||||
ulint n;
|
ulint n;
|
||||||
fseg_inode_t* inode;
|
fseg_inode_t* inode;
|
||||||
|
|
||||||
const uint32_t space_id = page_get_space_id(page_align(header));
|
const page_id_t header_id{block->page.id()};
|
||||||
const uint32_t header_page = page_get_page_no(page_align(header));
|
fil_space_t* space = mtr->x_lock_space(header_id.space());
|
||||||
|
xdes_t* descr = xdes_get_descriptor(space, header_id.page_no(), mtr);
|
||||||
fil_space_t* space = mtr->x_lock_space(space_id);
|
|
||||||
xdes_t* descr = xdes_get_descriptor(space, header_page, mtr);
|
|
||||||
|
|
||||||
if (!descr) {
|
if (!descr) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2849,14 +2838,17 @@ fseg_free_step(
|
||||||
freed yet */
|
freed yet */
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(xdes_is_free(descr,
|
if (UNIV_UNLIKELY(xdes_is_free(descr,
|
||||||
header_page & (FSP_EXTENT_SIZE - 1)))) {
|
header_id.page_no()
|
||||||
|
& (FSP_EXTENT_SIZE - 1)))) {
|
||||||
/* Some corruption was detected: stop the freeing
|
/* Some corruption was detected: stop the freeing
|
||||||
in order to prevent a crash. */
|
in order to prevent a crash. */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
buf_block_t* iblock;
|
buf_block_t* iblock;
|
||||||
const ulint zip_size = space->zip_size();
|
const ulint zip_size = space->zip_size();
|
||||||
inode = fseg_inode_try_get(header, space_id, zip_size, mtr, &iblock);
|
inode = fseg_inode_try_get(block->page.frame + header,
|
||||||
|
header_id.space(), zip_size,
|
||||||
|
mtr, &iblock);
|
||||||
if (!inode || space->is_stopping()) {
|
if (!inode || space->is_stopping()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -2915,33 +2907,31 @@ fseg_free_step(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool fseg_free_step_not_header(buf_block_t *block, size_t header, mtr_t *mtr
|
||||||
fseg_free_step_not_header(
|
|
||||||
fseg_header_t* header,
|
|
||||||
mtr_t* mtr
|
|
||||||
#ifdef BTR_CUR_HASH_ADAPT
|
#ifdef BTR_CUR_HASH_ADAPT
|
||||||
,bool ahi
|
, bool ahi
|
||||||
#endif /* BTR_CUR_HASH_ADAPT */
|
#endif /* BTR_CUR_HASH_ADAPT */
|
||||||
)
|
) noexcept
|
||||||
{
|
{
|
||||||
fseg_inode_t* inode;
|
fseg_inode_t* inode;
|
||||||
|
const page_id_t header_id{block->page.id()};
|
||||||
|
ut_ad(mtr->is_named_space(header_id.space()));
|
||||||
|
|
||||||
const uint32_t space_id = page_get_space_id(page_align(header));
|
fil_space_t* space = mtr->x_lock_space(header_id.space());
|
||||||
ut_ad(mtr->is_named_space(space_id));
|
buf_block_t* iblock;
|
||||||
|
|
||||||
fil_space_t* space = mtr->x_lock_space(space_id);
|
inode = fseg_inode_try_get(block->page.frame + header,
|
||||||
buf_block_t* iblock;
|
header_id.space(), space->zip_size(),
|
||||||
|
|
||||||
inode = fseg_inode_try_get(header, space_id, space->zip_size(),
|
|
||||||
mtr, &iblock);
|
mtr, &iblock);
|
||||||
if (space->is_stopping()) {
|
if (space->is_stopping()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inode) {
|
if (UNIV_UNLIKELY(!inode)) {
|
||||||
ib::warn() << "Double free of "
|
sql_print_warning("InnoDB: Double free of page " UINT32PF
|
||||||
<< page_id_t(space_id,
|
" in file %s",
|
||||||
page_get_page_no(page_align(header)));
|
header_id.page_no(),
|
||||||
|
space->chain.start->name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2973,7 +2963,7 @@ fseg_free_step_not_header(
|
||||||
|
|
||||||
uint32_t page_no = fseg_get_nth_frag_page_no(inode, n);
|
uint32_t page_no = fseg_get_nth_frag_page_no(inode, n);
|
||||||
|
|
||||||
if (page_no == page_get_page_no(page_align(header))) {
|
if (page_no == header_id.page_no()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3052,8 +3042,9 @@ static void fseg_print_low(const fseg_inode_t *inode)
|
||||||
ulint page_no;
|
ulint page_no;
|
||||||
ib_id_t seg_id;
|
ib_id_t seg_id;
|
||||||
|
|
||||||
space = page_get_space_id(page_align(inode));
|
const page_t* inode_page = page_align(inode);
|
||||||
page_no = page_get_page_no(page_align(inode));
|
space = page_get_space_id(inode_page);
|
||||||
|
page_no = page_get_page_no(inode_page);
|
||||||
|
|
||||||
reserved = fseg_n_reserved_pages_low(inode, &used);
|
reserved = fseg_n_reserved_pages_low(inode, &used);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3190,7 +3190,7 @@ fts_fetch_doc_from_rec(
|
||||||
parser = get_doc->index_cache->index->parser;
|
parser = get_doc->index_cache->index->parser;
|
||||||
|
|
||||||
clust_rec = btr_pcur_get_rec(pcur);
|
clust_rec = btr_pcur_get_rec(pcur);
|
||||||
ut_ad(!page_rec_is_comp(clust_rec)
|
ut_ad(!page_is_comp(btr_pcur_get_page(pcur))
|
||||||
|| rec_get_status(clust_rec) == REC_STATUS_ORDINARY);
|
|| rec_get_status(clust_rec) == REC_STATUS_ORDINARY);
|
||||||
|
|
||||||
for (ulint i = 0; i < index->n_fields; i++) {
|
for (ulint i = 0; i < index->n_fields; i++) {
|
||||||
|
|
|
||||||
|
|
@ -72,13 +72,13 @@ static void flst_write_addr(const buf_block_t& block, byte *faddr,
|
||||||
@param[in,out] mtr mini-transaction */
|
@param[in,out] mtr mini-transaction */
|
||||||
static void flst_zero_both(const buf_block_t& b, byte *addr, mtr_t *mtr)
|
static void flst_zero_both(const buf_block_t& b, byte *addr, mtr_t *mtr)
|
||||||
{
|
{
|
||||||
|
const ulint boffset= ulint(addr - b.page.frame);
|
||||||
if (mach_read_from_4(addr + FIL_ADDR_PAGE) != FIL_NULL)
|
if (mach_read_from_4(addr + FIL_ADDR_PAGE) != FIL_NULL)
|
||||||
mtr->memset(&b, ulint(addr - b.page.frame) + FIL_ADDR_PAGE, 4, 0xff);
|
mtr->memset(&b, boffset + FIL_ADDR_PAGE, 4, 0xff);
|
||||||
mtr->write<2,mtr_t::MAYBE_NOP>(b, addr + FIL_ADDR_BYTE, 0U);
|
mtr->write<2,mtr_t::MAYBE_NOP>(b, addr + FIL_ADDR_BYTE, 0U);
|
||||||
/* Initialize the other address by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source)
|
/* Initialize the other address by (MEMMOVE|0x80,offset,FIL_ADDR_SIZE,source)
|
||||||
which is 4 bytes, or less than FIL_ADDR_SIZE. */
|
which is 4 bytes, or less than FIL_ADDR_SIZE. */
|
||||||
memcpy(addr + FIL_ADDR_SIZE, addr, FIL_ADDR_SIZE);
|
memcpy(addr + FIL_ADDR_SIZE, addr, FIL_ADDR_SIZE);
|
||||||
const uint16_t boffset= page_offset(addr);
|
|
||||||
mtr->memmove(b, boffset + FIL_ADDR_SIZE, boffset, FIL_ADDR_SIZE);
|
mtr->memmove(b, boffset + FIL_ADDR_SIZE, boffset, FIL_ADDR_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ rtr_update_mbr_field(
|
||||||
rec_offs* offsets2;
|
rec_offs* offsets2;
|
||||||
|
|
||||||
rec = btr_cur_get_rec(cursor);
|
rec = btr_cur_get_rec(cursor);
|
||||||
page = page_align(rec);
|
page = btr_cur_get_page(cursor);
|
||||||
|
|
||||||
rec_info = rec_get_info_bits(rec, rec_offs_comp(offsets));
|
rec_info = rec_get_info_bits(rec, rec_offs_comp(offsets));
|
||||||
|
|
||||||
|
|
@ -1318,7 +1318,7 @@ rtr_page_copy_rec_list_end_no_locks(
|
||||||
return DB_CORRUPTION;
|
return DB_CORRUPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(page_is_comp(new_page) == page_rec_is_comp(rec));
|
ut_a(page_is_comp(new_page) == page_is_comp(block->page.frame));
|
||||||
ut_a(mach_read_from_2(new_page + srv_page_size - 10) == (ulint)
|
ut_a(mach_read_from_2(new_page + srv_page_size - 10) == (ulint)
|
||||||
(page_is_comp(new_page) ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
|
(page_is_comp(new_page) ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1284,11 +1284,13 @@ rtr_page_get_father_block(
|
||||||
btr_cur_t* cursor) /*!< out: cursor on node pointer record,
|
btr_cur_t* cursor) /*!< out: cursor on node pointer record,
|
||||||
its page x-latched */
|
its page x-latched */
|
||||||
{
|
{
|
||||||
rec_t *rec=
|
const page_t *const page= cursor->block()->page.frame;
|
||||||
page_rec_get_next(page_get_infimum_rec(cursor->block()->page.frame));
|
const rec_t *rec= page_is_comp(page)
|
||||||
|
? page_rec_next_get<true>(page, page + PAGE_NEW_INFIMUM)
|
||||||
|
: page_rec_next_get<false>(page, page + PAGE_OLD_INFIMUM);
|
||||||
if (!rec)
|
if (!rec)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
cursor->page_cur.rec= rec;
|
cursor->page_cur.rec= const_cast<rec_t*>(rec);
|
||||||
return rtr_page_get_father_node_ptr(offsets, heap, sea_cur, cursor, mtr);
|
return rtr_page_get_father_node_ptr(offsets, heap, sea_cur, cursor, mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2010,7 +2010,7 @@ static
|
||||||
ulint
|
ulint
|
||||||
ibuf_get_merge_page_nos_func(
|
ibuf_get_merge_page_nos_func(
|
||||||
/*=========================*/
|
/*=========================*/
|
||||||
const rec_t* rec, /*!< in: insert buffer record */
|
const btr_cur_t&cur, /*!< in: insert buffer record */
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
mtr_t* mtr, /*!< in: mini-transaction holding rec */
|
mtr_t* mtr, /*!< in: mini-transaction holding rec */
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
@ -2032,6 +2032,8 @@ ibuf_get_merge_page_nos_func(
|
||||||
ulint rec_volume;
|
ulint rec_volume;
|
||||||
ulint limit;
|
ulint limit;
|
||||||
ulint n_pages;
|
ulint n_pages;
|
||||||
|
const rec_t* rec= btr_cur_get_rec(&cur);
|
||||||
|
const page_t* page= btr_cur_get_page(&cur);
|
||||||
|
|
||||||
ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX
|
ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX
|
||||||
| MTR_MEMO_PAGE_S_FIX));
|
| MTR_MEMO_PAGE_S_FIX));
|
||||||
|
|
@ -2039,7 +2041,7 @@ ibuf_get_merge_page_nos_func(
|
||||||
|
|
||||||
*n_stored = 0;
|
*n_stored = 0;
|
||||||
|
|
||||||
if (page_rec_is_supremum(rec)) {
|
if (page_rec_is_supremum_low(rec - page)) {
|
||||||
|
|
||||||
rec = page_rec_get_prev_const(rec);
|
rec = page_rec_get_prev_const(rec);
|
||||||
if (UNIV_UNLIKELY(!rec)) {
|
if (UNIV_UNLIKELY(!rec)) {
|
||||||
|
|
@ -2049,9 +2051,9 @@ corruption:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_rec_is_infimum(rec)) {
|
if (page_rec_is_infimum_low(rec - page)) {
|
||||||
rec = page_rec_get_next_const(rec);
|
rec = page_rec_next_get<false>(page, rec);
|
||||||
if (!rec || page_rec_is_supremum(rec)) {
|
if (!rec || page_rec_is_supremum_low(rec - page)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2069,7 +2071,8 @@ corruption:
|
||||||
'merge area', or the page start or the limit of storeable pages is
|
'merge area', or the page start or the limit of storeable pages is
|
||||||
reached */
|
reached */
|
||||||
|
|
||||||
while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) {
|
while (!page_rec_is_infimum_low(rec - page)
|
||||||
|
&& UNIV_LIKELY(n_pages < limit)) {
|
||||||
|
|
||||||
rec_page_no = ibuf_rec_get_page_no(mtr, rec);
|
rec_page_no = ibuf_rec_get_page_no(mtr, rec);
|
||||||
rec_space_id = ibuf_rec_get_space(mtr, rec);
|
rec_space_id = ibuf_rec_get_space(mtr, rec);
|
||||||
|
|
@ -2094,7 +2097,7 @@ corruption:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = page_rec_get_next_const(rec);
|
rec = page_rec_next_get<false>(page, rec);
|
||||||
|
|
||||||
/* At the loop start there is no prev page; we mark this with a pair
|
/* At the loop start there is no prev page; we mark this with a pair
|
||||||
of space id, page no (0, 0) for which there can never be entries in
|
of space id, page no (0, 0) for which there can never be entries in
|
||||||
|
|
@ -2106,7 +2109,7 @@ corruption:
|
||||||
volume_for_page = 0;
|
volume_for_page = 0;
|
||||||
|
|
||||||
while (*n_stored < limit && rec) {
|
while (*n_stored < limit && rec) {
|
||||||
if (page_rec_is_supremum(rec)) {
|
if (page_rec_is_supremum_low(rec - page)) {
|
||||||
/* When no more records available, mark this with
|
/* When no more records available, mark this with
|
||||||
another 'impossible' pair of space id, page no */
|
another 'impossible' pair of space id, page no */
|
||||||
rec_page_no = 1;
|
rec_page_no = 1;
|
||||||
|
|
@ -2168,7 +2171,7 @@ corruption:
|
||||||
prev_page_no = rec_page_no;
|
prev_page_no = rec_page_no;
|
||||||
prev_space_id = rec_space_id;
|
prev_space_id = rec_space_id;
|
||||||
|
|
||||||
rec = page_rec_get_next_const(rec);
|
rec = page_rec_next_get<false>(page, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIV_IBUF_DEBUG
|
#ifdef UNIV_IBUF_DEBUG
|
||||||
|
|
@ -2434,7 +2437,7 @@ ATTRIBUTE_COLD ulint ibuf_contract()
|
||||||
}
|
}
|
||||||
|
|
||||||
ulint n_pages = 0;
|
ulint n_pages = 0;
|
||||||
sum_sizes = ibuf_get_merge_page_nos(btr_cur_get_rec(&cur), &mtr,
|
sum_sizes = ibuf_get_merge_page_nos(cur, &mtr,
|
||||||
space_ids, page_nos, &n_pages);
|
space_ids, page_nos, &n_pages);
|
||||||
ibuf_mtr_commit(&mtr);
|
ibuf_mtr_commit(&mtr);
|
||||||
|
|
||||||
|
|
@ -2726,10 +2729,10 @@ ibuf_get_volume_buffered(
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = btr_pcur_get_rec(pcur);
|
rec = btr_pcur_get_rec(pcur);
|
||||||
page = page_align(rec);
|
page = btr_pcur_get_page(pcur);
|
||||||
ut_ad(page_validate(page, ibuf.index));
|
ut_ad(page_validate(page, ibuf.index));
|
||||||
|
|
||||||
if (page_rec_is_supremum(rec)
|
if (rec == page + PAGE_OLD_SUPREMUM
|
||||||
&& UNIV_UNLIKELY(!(rec = page_rec_get_prev_const(rec)))) {
|
&& UNIV_UNLIKELY(!(rec = page_rec_get_prev_const(rec)))) {
|
||||||
corruption:
|
corruption:
|
||||||
ut_ad("corrupted page" == 0);
|
ut_ad("corrupted page" == 0);
|
||||||
|
|
@ -2738,7 +2741,7 @@ corruption:
|
||||||
|
|
||||||
uint32_t prev_page_no;
|
uint32_t prev_page_no;
|
||||||
|
|
||||||
for (; !page_rec_is_infimum(rec); ) {
|
while (rec != page + PAGE_OLD_INFIMUM) {
|
||||||
ut_ad(page_align(rec) == page);
|
ut_ad(page_align(rec) == page);
|
||||||
|
|
||||||
if (page_no != ibuf_rec_get_page_no(mtr, rec)
|
if (page_no != ibuf_rec_get_page_no(mtr, rec)
|
||||||
|
|
@ -2818,12 +2821,12 @@ corruption:
|
||||||
count_later:
|
count_later:
|
||||||
rec = btr_pcur_get_rec(pcur);
|
rec = btr_pcur_get_rec(pcur);
|
||||||
|
|
||||||
if (!page_rec_is_supremum(rec)) {
|
if (rec != page + PAGE_OLD_SUPREMUM) {
|
||||||
rec = page_rec_get_next_const(rec);
|
rec = page_rec_next_get<false>(page, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; !page_rec_is_supremum(rec);
|
for (; rec != page + PAGE_OLD_SUPREMUM;
|
||||||
rec = page_rec_get_next_const(rec)) {
|
rec = page_rec_next_get<false>(page, rec)) {
|
||||||
if (UNIV_UNLIKELY(!rec)) {
|
if (UNIV_UNLIKELY(!rec)) {
|
||||||
return srv_page_size;
|
return srv_page_size;
|
||||||
}
|
}
|
||||||
|
|
@ -2864,11 +2867,11 @@ count_later:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = page_get_infimum_rec(next_page);
|
rec = page_rec_next_get<false>(next_page,
|
||||||
rec = page_rec_get_next_const(rec);
|
next_page + PAGE_OLD_INFIMUM);
|
||||||
|
|
||||||
for (; ; rec = page_rec_get_next_const(rec)) {
|
for (;; rec = page_rec_next_get<false>(next_page, rec)) {
|
||||||
if (!rec || page_rec_is_supremum(rec)) {
|
if (!rec || rec == next_page + PAGE_OLD_SUPREMUM) {
|
||||||
/* We give up */
|
/* We give up */
|
||||||
return(srv_page_size);
|
return(srv_page_size);
|
||||||
}
|
}
|
||||||
|
|
@ -3591,16 +3594,26 @@ ibuf_insert_to_index_page(
|
||||||
assert_block_ahi_empty(block);
|
assert_block_ahi_empty(block);
|
||||||
#endif /* BTR_CUR_HASH_ADAPT */
|
#endif /* BTR_CUR_HASH_ADAPT */
|
||||||
ut_ad(mtr->is_named_space(block->page.id().space()));
|
ut_ad(mtr->is_named_space(block->page.id().space()));
|
||||||
|
const auto comp = page_is_comp(page);
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
|
if (UNIV_UNLIKELY(index->table->not_redundant() != !!comp)) {
|
||||||
!= (ibool)!!page_is_comp(page))) {
|
|
||||||
return DB_CORRUPTION;
|
return DB_CORRUPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = page_rec_get_next(page_get_infimum_rec(page));
|
if (comp) {
|
||||||
|
rec = const_cast<rec_t*>(
|
||||||
if (!rec || page_rec_is_supremum(rec)) {
|
page_rec_next_get<true>(page,
|
||||||
return DB_CORRUPTION;
|
page + PAGE_NEW_INFIMUM));
|
||||||
|
if (!rec || rec == page + PAGE_NEW_SUPREMUM) {
|
||||||
|
return DB_CORRUPTION;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rec = const_cast<rec_t*>(
|
||||||
|
page_rec_next_get<false>(page,
|
||||||
|
page + PAGE_OLD_INFIMUM));
|
||||||
|
if (!rec || rec == page + PAGE_OLD_SUPREMUM) {
|
||||||
|
return DB_CORRUPTION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rec_n_fields_is_sane(index, rec, entry)) {
|
if (!rec_n_fields_is_sane(index, rec, entry)) {
|
||||||
|
|
@ -4214,7 +4227,8 @@ loop:
|
||||||
dict_index_t* dummy_index;
|
dict_index_t* dummy_index;
|
||||||
ibuf_op_t op = ibuf_rec_get_op_type(&mtr, rec);
|
ibuf_op_t op = ibuf_rec_get_op_type(&mtr, rec);
|
||||||
|
|
||||||
max_trx_id = page_get_max_trx_id(page_align(rec));
|
max_trx_id =
|
||||||
|
page_get_max_trx_id(btr_pcur_get_page(&pcur));
|
||||||
page_update_max_trx_id(block,
|
page_update_max_trx_id(block,
|
||||||
buf_block_get_page_zip(block),
|
buf_block_get_page_zip(block),
|
||||||
max_trx_id, &mtr);
|
max_trx_id, &mtr);
|
||||||
|
|
|
||||||
|
|
@ -269,20 +269,19 @@ dberr_t btr_page_reorganize(page_cur_t *cursor, mtr_t *mtr)
|
||||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||||
/** Decide if the page should be split at the convergence point of inserts
|
/** Decide if the page should be split at the convergence point of inserts
|
||||||
converging to the left.
|
converging to the left.
|
||||||
@param[in] cursor insert position
|
@param cursor insert position
|
||||||
@return the first record to be moved to the right half page
|
@return the first record to be moved to the right half page
|
||||||
@retval NULL if no split is recommended */
|
@retval nullptr if no split is recommended */
|
||||||
rec_t* btr_page_get_split_rec_to_left(const btr_cur_t* cursor);
|
rec_t *btr_page_get_split_rec_to_left(const btr_cur_t *cursor) noexcept;
|
||||||
/** Decide if the page should be split at the convergence point of inserts
|
/** Decide if the page should be split at the convergence point of inserts
|
||||||
converging to the right.
|
converging to the right.
|
||||||
@param[in] cursor insert position
|
@param cursor insert position
|
||||||
@param[out] split_rec if split recommended, the first record
|
@param split_rec if split recommended, the first record on the right
|
||||||
on the right half page, or
|
half page, or nullptr if the to-be-inserted record should be first
|
||||||
NULL if the to-be-inserted record
|
|
||||||
should be first
|
|
||||||
@return whether split is recommended */
|
@return whether split is recommended */
|
||||||
bool
|
bool
|
||||||
btr_page_get_split_rec_to_right(const btr_cur_t* cursor, rec_t** split_rec);
|
btr_page_get_split_rec_to_right(const btr_cur_t *cursor, rec_t **split_rec)
|
||||||
|
noexcept;
|
||||||
|
|
||||||
/*************************************************************//**
|
/*************************************************************//**
|
||||||
Splits an index page to halves and inserts the tuple. It is assumed
|
Splits an index page to halves and inserts the tuple. It is assumed
|
||||||
|
|
@ -333,7 +332,7 @@ inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
|
||||||
ut_ad(!page_is_leaf(block.page.frame));
|
ut_ad(!page_is_leaf(block.page.frame));
|
||||||
ut_ad(has_prev == page_has_prev(block.page.frame));
|
ut_ad(has_prev == page_has_prev(block.page.frame));
|
||||||
|
|
||||||
rec-= page_rec_is_comp(rec) ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS;
|
rec-= page_is_comp(block.page.frame) ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS;
|
||||||
|
|
||||||
if (block.page.zip.data)
|
if (block.page.zip.data)
|
||||||
/* This flag is computed from other contents on a ROW_FORMAT=COMPRESSED
|
/* This flag is computed from other contents on a ROW_FORMAT=COMPRESSED
|
||||||
|
|
@ -344,11 +343,11 @@ inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Seek to the parent page of a B-tree page.
|
/** Seek to the parent page of a B-tree page.
|
||||||
@param[in,out] mtr mini-transaction
|
@param mtr mini-transaction
|
||||||
@param[in,out] cursor cursor pointing to the x-latched parent page
|
@param cursor cursor pointing to the x-latched parent page
|
||||||
@return whether the cursor was successfully positioned */
|
@return whether the cursor was successfully positioned */
|
||||||
bool btr_page_get_father(mtr_t* mtr, btr_cur_t* cursor)
|
bool btr_page_get_father(mtr_t *mtr, btr_cur_t *cursor) noexcept
|
||||||
MY_ATTRIBUTE((nonnull,warn_unused_result));
|
MY_ATTRIBUTE((nonnull,warn_unused_result));
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
Checks that the node pointer to a page is appropriate.
|
Checks that the node pointer to a page is appropriate.
|
||||||
|
|
@ -502,15 +501,15 @@ btr_print_index(
|
||||||
Checks the size and number of fields in a record based on the definition of
|
Checks the size and number of fields in a record based on the definition of
|
||||||
the index.
|
the index.
|
||||||
@return TRUE if ok */
|
@return TRUE if ok */
|
||||||
ibool
|
bool
|
||||||
btr_index_rec_validate(
|
btr_index_rec_validate(
|
||||||
/*===================*/
|
/*===================*/
|
||||||
const rec_t* rec, /*!< in: index record */
|
const page_cur_t& cur, /*!< in: index record */
|
||||||
const dict_index_t* index, /*!< in: index */
|
const dict_index_t* index, /*!< in: index */
|
||||||
ibool dump_on_error) /*!< in: TRUE if the function
|
bool dump_on_error) /*!< in: true if the function
|
||||||
should print hex dump of record
|
should print hex dump of record
|
||||||
and page on error */
|
and page on error */
|
||||||
MY_ATTRIBUTE((warn_unused_result));
|
noexcept MY_ATTRIBUTE((warn_unused_result));
|
||||||
/**************************************************************//**
|
/**************************************************************//**
|
||||||
Checks the consistency of an index tree.
|
Checks the consistency of an index tree.
|
||||||
@return DB_SUCCESS if ok, error code if not */
|
@return DB_SUCCESS if ok, error code if not */
|
||||||
|
|
|
||||||
|
|
@ -460,42 +460,36 @@ fseg_free_page(
|
||||||
dberr_t fseg_page_is_allocated(fil_space_t *space, unsigned page)
|
dberr_t fseg_page_is_allocated(fil_space_t *space, unsigned page)
|
||||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||||
|
|
||||||
|
MY_ATTRIBUTE((nonnull, warn_unused_result))
|
||||||
/** Frees part of a segment. This function can be used to free
|
/** Frees part of a segment. This function can be used to free
|
||||||
a segment by repeatedly calling this function in different
|
a segment by repeatedly calling this function in different
|
||||||
mini-transactions. Doing the freeing in a single mini-transaction
|
mini-transactions. Doing the freeing in a single mini-transaction
|
||||||
might result in too big a mini-transaction.
|
might result in too big a mini-transaction.
|
||||||
@param header segment header; NOTE: if the header resides on first
|
@param block segment header block
|
||||||
page of the frag list of the segment, this pointer
|
@param header segment header offset in the block;
|
||||||
becomes obsolete after the last freeing step
|
NOTE: if the header resides on first page of the frag list of the segment,
|
||||||
@param mtr mini-transaction
|
this pointer becomes obsolete after the last freeing step
|
||||||
@param ahi Drop the adaptive hash index
|
@param mtr mini-transaction
|
||||||
@return whether the freeing was completed */
|
@return whether the freeing was completed */
|
||||||
bool
|
bool fseg_free_step(buf_block_t *block, size_t header, mtr_t *mtr
|
||||||
fseg_free_step(
|
|
||||||
fseg_header_t* header,
|
|
||||||
mtr_t* mtr
|
|
||||||
#ifdef BTR_CUR_HASH_ADAPT
|
#ifdef BTR_CUR_HASH_ADAPT
|
||||||
,bool ahi=false
|
, bool ahi=false /*!< whether to drop the AHI */
|
||||||
#endif /* BTR_CUR_HASH_ADAPT */
|
#endif /* BTR_CUR_HASH_ADAPT */
|
||||||
)
|
) noexcept;
|
||||||
MY_ATTRIBUTE((warn_unused_result));
|
|
||||||
|
|
||||||
|
MY_ATTRIBUTE((nonnull, warn_unused_result))
|
||||||
/** Frees part of a segment. Differs from fseg_free_step because
|
/** Frees part of a segment. Differs from fseg_free_step because
|
||||||
this function leaves the header page unfreed.
|
this function leaves the header page unfreed.
|
||||||
@param header segment header which must reside on the first
|
@param block segment header block; must reside on the first
|
||||||
fragment page of the segment
|
fragment page of the segment
|
||||||
@param mtr mini-transaction
|
@param header segment header offset in the block
|
||||||
@param ahi drop the adaptive hash index
|
@param mtr mini-transaction
|
||||||
@return whether the freeing was completed, except for the header page */
|
@return whether the freeing was completed, except for the header page */
|
||||||
bool
|
bool fseg_free_step_not_header(buf_block_t *block, size_t header, mtr_t *mtr
|
||||||
fseg_free_step_not_header(
|
|
||||||
fseg_header_t* header,
|
|
||||||
mtr_t* mtr
|
|
||||||
#ifdef BTR_CUR_HASH_ADAPT
|
#ifdef BTR_CUR_HASH_ADAPT
|
||||||
,bool ahi=false
|
, bool ahi=false /*!< whether to drop the AHI */
|
||||||
#endif /* BTR_CUR_HASH_ADAPT */
|
#endif /* BTR_CUR_HASH_ADAPT */
|
||||||
)
|
) noexcept;
|
||||||
MY_ATTRIBUTE((warn_unused_result));
|
|
||||||
|
|
||||||
/** Reset the page type.
|
/** Reset the page type.
|
||||||
Data files created before MySQL 5.1.48 may contain garbage in FIL_PAGE_TYPE.
|
Data files created before MySQL 5.1.48 may contain garbage in FIL_PAGE_TYPE.
|
||||||
|
|
|
||||||
|
|
@ -460,7 +460,7 @@ lock_rec_unlock(
|
||||||
/*============*/
|
/*============*/
|
||||||
trx_t* trx, /*!< in/out: transaction that has
|
trx_t* trx, /*!< in/out: transaction that has
|
||||||
set a record lock */
|
set a record lock */
|
||||||
const page_id_t id, /*!< in: page containing rec */
|
const buf_block_t& block, /*!< in: page containing rec */
|
||||||
const rec_t* rec, /*!< in: record */
|
const rec_t* rec, /*!< in: record */
|
||||||
lock_mode lock_mode);/*!< in: LOCK_S or LOCK_X */
|
lock_mode lock_mode);/*!< in: LOCK_S or LOCK_X */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -210,8 +210,7 @@ inline bool mtr_t::write(const buf_block_t &block, void *ptr, V val)
|
||||||
p--;
|
p--;
|
||||||
}
|
}
|
||||||
::memcpy(ptr, buf, l);
|
::memcpy(ptr, buf, l);
|
||||||
memcpy_low(block, static_cast<uint16_t>
|
memcpy_low(block, uint16_t(p - block.page.frame), p, end - p);
|
||||||
(ut_align_offset(p, srv_page_size)), p, end - p);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -490,12 +489,12 @@ inline void mtr_t::memcpy(const buf_block_t &b, void *dest, const void *str,
|
||||||
ulint len)
|
ulint len)
|
||||||
{
|
{
|
||||||
ut_ad(ut_align_down(dest, srv_page_size) == b.page.frame);
|
ut_ad(ut_align_down(dest, srv_page_size) == b.page.frame);
|
||||||
char *d= static_cast<char*>(dest);
|
byte *d= static_cast<byte*>(dest);
|
||||||
const char *s= static_cast<const char*>(str);
|
const char *s= static_cast<const char*>(str);
|
||||||
if (w != FORCED && is_logged())
|
if (w != FORCED && is_logged())
|
||||||
{
|
{
|
||||||
ut_ad(len);
|
ut_ad(len);
|
||||||
const char *const end= d + len;
|
const byte *const end= d + len;
|
||||||
while (*d++ == *s++)
|
while (*d++ == *s++)
|
||||||
{
|
{
|
||||||
if (d == end)
|
if (d == end)
|
||||||
|
|
@ -509,7 +508,7 @@ inline void mtr_t::memcpy(const buf_block_t &b, void *dest, const void *str,
|
||||||
len= static_cast<ulint>(end - d);
|
len= static_cast<ulint>(end - d);
|
||||||
}
|
}
|
||||||
::memcpy(d, s, len);
|
::memcpy(d, s, len);
|
||||||
memcpy(b, ut_align_offset(d, srv_page_size), len);
|
memcpy(b, d - b.page.frame, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Write an EXTENDED log record.
|
/** Write an EXTENDED log record.
|
||||||
|
|
|
||||||
|
|
@ -196,13 +196,14 @@ extern my_bool srv_immediate_scrub_data_uncompressed;
|
||||||
/** Get the start of a page frame.
|
/** Get the start of a page frame.
|
||||||
@param[in] ptr pointer within a page frame
|
@param[in] ptr pointer within a page frame
|
||||||
@return start of the page frame */
|
@return start of the page frame */
|
||||||
MY_ATTRIBUTE((const))
|
MY_ATTRIBUTE((const,nonnull))
|
||||||
inline page_t* page_align(void *ptr)
|
inline page_t *page_align(void *ptr) noexcept
|
||||||
{
|
{
|
||||||
return my_assume_aligned<UNIV_PAGE_SIZE_MIN>
|
return my_assume_aligned<UNIV_PAGE_SIZE_MIN>
|
||||||
(reinterpret_cast<page_t*>(ut_align_down(ptr, srv_page_size)));
|
(reinterpret_cast<page_t*>(ut_align_down(ptr, srv_page_size)));
|
||||||
}
|
}
|
||||||
inline const page_t *page_align(const void *ptr)
|
|
||||||
|
inline const page_t *page_align(const void *ptr) noexcept
|
||||||
{
|
{
|
||||||
return page_align(const_cast<void*>(ptr));
|
return page_align(const_cast<void*>(ptr));
|
||||||
}
|
}
|
||||||
|
|
@ -210,8 +211,8 @@ inline const page_t *page_align(const void *ptr)
|
||||||
/** Gets the byte offset within a page frame.
|
/** Gets the byte offset within a page frame.
|
||||||
@param[in] ptr pointer within a page frame
|
@param[in] ptr pointer within a page frame
|
||||||
@return offset from the start of the page */
|
@return offset from the start of the page */
|
||||||
MY_ATTRIBUTE((const))
|
MY_ATTRIBUTE((const,nonnull))
|
||||||
inline uint16_t page_offset(const void* ptr)
|
inline uint16_t page_offset(const void *ptr) noexcept
|
||||||
{
|
{
|
||||||
return static_cast<uint16_t>(ut_align_offset(ptr, srv_page_size));
|
return static_cast<uint16_t>(ut_align_offset(ptr, srv_page_size));
|
||||||
}
|
}
|
||||||
|
|
@ -687,6 +688,7 @@ page_dir_find_owner_slot(
|
||||||
/*=====================*/
|
/*=====================*/
|
||||||
const rec_t* rec); /*!< in: the physical record */
|
const rec_t* rec); /*!< in: the physical record */
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
/***************************************************************//**
|
/***************************************************************//**
|
||||||
Returns the heap number of a record.
|
Returns the heap number of a record.
|
||||||
@return heap number */
|
@return heap number */
|
||||||
|
|
@ -695,6 +697,7 @@ ulint
|
||||||
page_rec_get_heap_no(
|
page_rec_get_heap_no(
|
||||||
/*=================*/
|
/*=================*/
|
||||||
const rec_t* rec); /*!< in: the physical record */
|
const rec_t* rec); /*!< in: the physical record */
|
||||||
|
#endif
|
||||||
/** Determine whether a page has any siblings.
|
/** Determine whether a page has any siblings.
|
||||||
@param[in] page page frame
|
@param[in] page page frame
|
||||||
@return true if the page has any siblings */
|
@return true if the page has any siblings */
|
||||||
|
|
@ -738,15 +741,28 @@ inline uint64_t page_get_autoinc(const page_t *page)
|
||||||
return mach_read_from_8(p);
|
return mach_read_from_8(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************//**
|
/** Get the pointer to the next record on the page.
|
||||||
Gets the pointer to the next record on the page.
|
@tparam comp whether ROW_FORMAT is not REDUNDANT
|
||||||
@return pointer to next record */
|
@param page index page
|
||||||
UNIV_INLINE
|
@param rec index record
|
||||||
const rec_t*
|
@return successor of rec in the page
|
||||||
page_rec_get_next_low(
|
@retval nullptr on corruption */
|
||||||
/*==================*/
|
template<bool comp>
|
||||||
const rec_t* rec, /*!< in: pointer to record */
|
inline const rec_t *page_rec_next_get(const page_t *page, const rec_t *rec)
|
||||||
ulint comp); /*!< in: nonzero=compact page layout */
|
{
|
||||||
|
ut_ad(!!page_is_comp(page) == comp);
|
||||||
|
ut_ad(page_align(rec) == page);
|
||||||
|
ulint offs= rec_get_next_offs(rec, comp);
|
||||||
|
if (UNIV_UNLIKELY(offs < (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM)))
|
||||||
|
return nullptr;
|
||||||
|
if (UNIV_UNLIKELY(offs > page_header_get_field(page, PAGE_HEAP_TOP)))
|
||||||
|
return nullptr;
|
||||||
|
ut_ad(page_rec_is_infimum(rec) ||
|
||||||
|
(!page_is_leaf(page) && !page_has_prev(page)) ||
|
||||||
|
!(rec_get_info_bits(page + offs, comp) & REC_INFO_MIN_REC_FLAG));
|
||||||
|
return page + offs;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
Gets the pointer to the next record on the page.
|
Gets the pointer to the next record on the page.
|
||||||
@return pointer to next record */
|
@return pointer to next record */
|
||||||
|
|
@ -755,6 +771,7 @@ rec_t*
|
||||||
page_rec_get_next(
|
page_rec_get_next(
|
||||||
/*==============*/
|
/*==============*/
|
||||||
rec_t* rec); /*!< in: pointer to record */
|
rec_t* rec); /*!< in: pointer to record */
|
||||||
|
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
Gets the pointer to the next record on the page.
|
Gets the pointer to the next record on the page.
|
||||||
@return pointer to next record */
|
@return pointer to next record */
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,7 @@ inline void page_header_reset_last_insert(buf_block_t *block, mtr_t *mtr)
|
||||||
memset_aligned<2>(&block->page.zip.data[field], 0, 2);
|
memset_aligned<2>(&block->page.zip.data[field], 0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
/***************************************************************//**
|
/***************************************************************//**
|
||||||
Returns the heap number of a record.
|
Returns the heap number of a record.
|
||||||
@return heap number */
|
@return heap number */
|
||||||
|
|
@ -143,6 +144,7 @@ page_rec_get_heap_no(
|
||||||
return(rec_get_heap_no_old(rec));
|
return(rec_get_heap_no_old(rec));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Determine whether an index page record is a user record.
|
/** Determine whether an index page record is a user record.
|
||||||
@param[in] rec record in an index page
|
@param[in] rec record in an index page
|
||||||
|
|
@ -235,7 +237,9 @@ page_get_page_no(
|
||||||
/*=============*/
|
/*=============*/
|
||||||
const page_t* page) /*!< in: page */
|
const page_t* page) /*!< in: page */
|
||||||
{
|
{
|
||||||
ut_ad(page == page_align((page_t*) page));
|
#ifndef UNIV_INNOCHECKSUM
|
||||||
|
ut_ad(page == page_align(page));
|
||||||
|
#endif /* !UNIV_INNOCHECKSUM */
|
||||||
return mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_OFFSET));
|
return mach_read_from_4(my_assume_aligned<4>(page + FIL_PAGE_OFFSET));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,7 +253,7 @@ page_get_space_id(
|
||||||
/*==============*/
|
/*==============*/
|
||||||
const page_t* page) /*!< in: page */
|
const page_t* page) /*!< in: page */
|
||||||
{
|
{
|
||||||
ut_ad(page == page_align((page_t*) page));
|
ut_ad(page == page_align(page));
|
||||||
return mach_read_from_4(my_assume_aligned<2>
|
return mach_read_from_4(my_assume_aligned<2>
|
||||||
(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
|
(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
|
||||||
}
|
}
|
||||||
|
|
@ -357,8 +361,6 @@ page_rec_get_next_low(
|
||||||
const page_t *page= page_align(rec);
|
const page_t *page= page_align(rec);
|
||||||
ut_ad(page_rec_check(rec));
|
ut_ad(page_rec_check(rec));
|
||||||
ulint offs= rec_get_next_offs(rec, comp);
|
ulint offs= rec_get_next_offs(rec, comp);
|
||||||
if (!offs)
|
|
||||||
return nullptr;
|
|
||||||
if (UNIV_UNLIKELY(offs < (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM)))
|
if (UNIV_UNLIKELY(offs < (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (UNIV_UNLIKELY(offs > page_header_get_field(page, PAGE_HEAP_TOP)))
|
if (UNIV_UNLIKELY(offs > page_header_get_field(page, PAGE_HEAP_TOP)))
|
||||||
|
|
|
||||||
|
|
@ -326,7 +326,7 @@ public:
|
||||||
page_id_t get_page_id() const { return page_id; }
|
page_id_t get_page_id() const { return page_id; }
|
||||||
|
|
||||||
/** Handle the DML undo log and apply it on online indexes */
|
/** Handle the DML undo log and apply it on online indexes */
|
||||||
inline void apply_undo_rec(const trx_undo_rec_t *rec);
|
inline void apply_undo_rec(const trx_undo_rec_t *rec, uint16_t offset);
|
||||||
|
|
||||||
~UndorecApplier()
|
~UndorecApplier()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2772,8 +2772,8 @@ lock_move_reorganize_page(
|
||||||
old_heap_no= rec_get_heap_no_new(rec2);
|
old_heap_no= rec_get_heap_no_new(rec2);
|
||||||
new_heap_no= rec_get_heap_no_new(rec1);
|
new_heap_no= rec_get_heap_no_new(rec1);
|
||||||
|
|
||||||
rec1= page_rec_get_next_low(rec1, TRUE);
|
rec1= page_rec_next_get<true>(block->page.frame, rec1);
|
||||||
rec2= page_rec_get_next_low(rec2, TRUE);
|
rec2= page_rec_next_get<true>(oblock->page.frame, rec2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2781,8 +2781,8 @@ lock_move_reorganize_page(
|
||||||
new_heap_no= rec_get_heap_no_old(rec1);
|
new_heap_no= rec_get_heap_no_old(rec1);
|
||||||
ut_ad(!memcmp(rec1, rec2, rec_get_data_size_old(rec2)));
|
ut_ad(!memcmp(rec1, rec2, rec_get_data_size_old(rec2)));
|
||||||
|
|
||||||
rec1= page_rec_get_next_low(rec1, FALSE);
|
rec1= page_rec_next_get<false>(block->page.frame, rec1);
|
||||||
rec2= page_rec_get_next_low(rec2, FALSE);
|
rec2= page_rec_next_get<false>(oblock->page.frame, rec2);
|
||||||
}
|
}
|
||||||
|
|
||||||
trx_t *lock_trx= lock->trx;
|
trx_t *lock_trx= lock->trx;
|
||||||
|
|
@ -2838,9 +2838,10 @@ lock_move_rec_list_end(
|
||||||
const rec_t* rec) /*!< in: record on page: this
|
const rec_t* rec) /*!< in: record on page: this
|
||||||
is the first record moved */
|
is the first record moved */
|
||||||
{
|
{
|
||||||
const ulint comp= page_rec_is_comp(rec);
|
const page_t *const page= block->page.frame;
|
||||||
|
const page_t *const new_page= new_block->page.frame;
|
||||||
ut_ad(block->page.frame == page_align(rec));
|
const ulint comp= page_is_comp(page);
|
||||||
|
ut_ad(page == page_align(rec));
|
||||||
ut_ad(comp == page_is_comp(new_block->page.frame));
|
ut_ad(comp == page_is_comp(new_block->page.frame));
|
||||||
|
|
||||||
const page_id_t id{block->page.id()};
|
const page_id_t id{block->page.id()};
|
||||||
|
|
@ -2863,17 +2864,15 @@ lock_move_rec_list_end(
|
||||||
|
|
||||||
if (comp)
|
if (comp)
|
||||||
{
|
{
|
||||||
if (page_offset(rec1) == PAGE_NEW_INFIMUM)
|
if (rec1 - page == PAGE_NEW_INFIMUM)
|
||||||
rec1= page_rec_get_next_low(rec1, TRUE);
|
rec1= page_rec_next_get<true>(page, rec1);
|
||||||
rec2= page_rec_get_next_low(new_block->page.frame + PAGE_NEW_INFIMUM,
|
rec2= page_rec_next_get<true>(new_page, PAGE_NEW_INFIMUM + new_page);
|
||||||
TRUE);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (page_offset(rec1) == PAGE_OLD_INFIMUM)
|
if (rec1 - page == PAGE_OLD_INFIMUM)
|
||||||
rec1= page_rec_get_next_low(rec1, FALSE);
|
rec1= page_rec_next_get<false>(page, rec1);
|
||||||
rec2= page_rec_get_next_low(new_block->page.frame + PAGE_OLD_INFIMUM,
|
rec2= page_rec_next_get<false>(new_page, PAGE_OLD_INFIMUM + new_page);
|
||||||
FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(!rec1 || !rec2))
|
if (UNIV_UNLIKELY(!rec1 || !rec2))
|
||||||
|
|
@ -2895,19 +2894,19 @@ lock_move_rec_list_end(
|
||||||
if (comp)
|
if (comp)
|
||||||
{
|
{
|
||||||
rec1_heap_no= rec_get_heap_no_new(rec1);
|
rec1_heap_no= rec_get_heap_no_new(rec1);
|
||||||
if (!(rec1= page_rec_get_next_low(rec1, TRUE)))
|
if (!(rec1= page_rec_next_get<true>(page, rec1)))
|
||||||
{
|
{
|
||||||
ut_ad(rec1_heap_no == PAGE_HEAP_NO_SUPREMUM);
|
ut_ad(rec1_heap_no == PAGE_HEAP_NO_SUPREMUM);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rec2_heap_no= rec_get_heap_no_new(rec2);
|
rec2_heap_no= rec_get_heap_no_new(rec2);
|
||||||
rec2= page_rec_get_next_low(rec2, TRUE);
|
rec2= page_rec_next_get<true>(new_page, rec2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ut_d(const rec_t *old1= rec1);
|
ut_d(const rec_t *old1= rec1);
|
||||||
rec1_heap_no= rec_get_heap_no_old(rec1);
|
rec1_heap_no= rec_get_heap_no_old(rec1);
|
||||||
if (!(rec1= page_rec_get_next_low(rec1, FALSE)))
|
if (!(rec1= page_rec_next_get<false>(page, rec1)))
|
||||||
{
|
{
|
||||||
ut_ad(rec1_heap_no == PAGE_HEAP_NO_SUPREMUM);
|
ut_ad(rec1_heap_no == PAGE_HEAP_NO_SUPREMUM);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2917,7 +2916,7 @@ lock_move_rec_list_end(
|
||||||
ut_ad(!memcmp(old1, rec2, rec_get_data_size_old(old1)));
|
ut_ad(!memcmp(old1, rec2, rec_get_data_size_old(old1)));
|
||||||
|
|
||||||
rec2_heap_no= rec_get_heap_no_old(rec2);
|
rec2_heap_no= rec_get_heap_no_old(rec2);
|
||||||
rec2= page_rec_get_next_low(rec2, FALSE);
|
rec2= page_rec_next_get<false>(new_page, rec2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(!rec2))
|
if (UNIV_UNLIKELY(!rec2))
|
||||||
|
|
@ -2941,7 +2940,7 @@ lock_move_rec_list_end(
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_rec_add_to_queue(type_mode, g.cell2(), new_id,
|
lock_rec_add_to_queue(type_mode, g.cell2(), new_id,
|
||||||
new_block->page.frame,
|
new_page,
|
||||||
rec2_heap_no, lock->index, lock_trx, true);
|
rec2_heap_no, lock->index, lock_trx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2980,7 +2979,7 @@ lock_move_rec_list_start(
|
||||||
before the records
|
before the records
|
||||||
were copied */
|
were copied */
|
||||||
{
|
{
|
||||||
const ulint comp= page_rec_is_comp(rec);
|
const ulint comp= page_is_comp(block->page.frame);
|
||||||
|
|
||||||
ut_ad(block->page.frame == page_align(rec));
|
ut_ad(block->page.frame == page_align(rec));
|
||||||
ut_ad(comp == page_is_comp(new_block->page.frame));
|
ut_ad(comp == page_is_comp(new_block->page.frame));
|
||||||
|
|
@ -3002,15 +3001,15 @@ lock_move_rec_list_start(
|
||||||
|
|
||||||
if (comp)
|
if (comp)
|
||||||
{
|
{
|
||||||
rec1= page_rec_get_next_low(block->page.frame + PAGE_NEW_INFIMUM,
|
rec1= page_rec_next_get<true>(block->page.frame,
|
||||||
TRUE);
|
block->page.frame + PAGE_NEW_INFIMUM);
|
||||||
rec2= page_rec_get_next_low(old_end, TRUE);
|
rec2= page_rec_next_get<true>(new_block->page.frame, old_end);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rec1= page_rec_get_next_low(block->page.frame + PAGE_OLD_INFIMUM,
|
rec1= page_rec_next_get<false>(block->page.frame,
|
||||||
FALSE);
|
block->page.frame + PAGE_OLD_INFIMUM);
|
||||||
rec2= page_rec_get_next_low(old_end, FALSE);
|
rec2= page_rec_next_get<false>(new_block->page.frame, old_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy lock requests on user records to new page and
|
/* Copy lock requests on user records to new page and
|
||||||
|
|
@ -3035,8 +3034,8 @@ lock_move_rec_list_start(
|
||||||
rec1_heap_no= rec_get_heap_no_new(rec1);
|
rec1_heap_no= rec_get_heap_no_new(rec1);
|
||||||
rec2_heap_no= rec_get_heap_no_new(rec2);
|
rec2_heap_no= rec_get_heap_no_new(rec2);
|
||||||
|
|
||||||
rec1= page_rec_get_next_low(rec1, TRUE);
|
rec1= page_rec_next_get<true>(block->page.frame, rec1);
|
||||||
rec2= page_rec_get_next_low(rec2, TRUE);
|
rec2= page_rec_next_get<true>(new_block->page.frame, rec2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -3045,8 +3044,8 @@ lock_move_rec_list_start(
|
||||||
|
|
||||||
ut_ad(!memcmp(rec1, rec2, rec_get_data_size_old(rec2)));
|
ut_ad(!memcmp(rec1, rec2, rec_get_data_size_old(rec2)));
|
||||||
|
|
||||||
rec1= page_rec_get_next_low(rec1, FALSE);
|
rec1= page_rec_next_get<false>(block->page.frame, rec1);
|
||||||
rec2= page_rec_get_next_low(rec2, FALSE);
|
rec2= page_rec_next_get<false>(new_block->page.frame, rec2);
|
||||||
}
|
}
|
||||||
|
|
||||||
trx_t *lock_trx= lock->trx;
|
trx_t *lock_trx= lock->trx;
|
||||||
|
|
@ -3101,8 +3100,7 @@ lock_rtr_move_rec_list(
|
||||||
if (!num_move)
|
if (!num_move)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ulint comp= page_rec_is_comp(rec_move[0].old_rec);
|
const ulint comp= page_is_comp(block->page.frame);
|
||||||
|
|
||||||
ut_ad(block->page.frame == page_align(rec_move[0].old_rec));
|
ut_ad(block->page.frame == page_align(rec_move[0].old_rec));
|
||||||
ut_ad(new_block->page.frame == page_align(rec_move[0].new_rec));
|
ut_ad(new_block->page.frame == page_align(rec_move[0].new_rec));
|
||||||
ut_ad(comp == page_rec_is_comp(rec_move[0].new_rec));
|
ut_ad(comp == page_rec_is_comp(rec_move[0].new_rec));
|
||||||
|
|
@ -3233,6 +3231,17 @@ static void lock_assert_no_spatial(const page_id_t id)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** Determine the heap number of an index record
|
||||||
|
@param block index page
|
||||||
|
@param rec index record
|
||||||
|
@return the heap number of the record */
|
||||||
|
static ulint lock_get_heap_no(const buf_block_t &block, const rec_t *rec)
|
||||||
|
{
|
||||||
|
ut_ad(page_align(rec) == block.page.frame);
|
||||||
|
return page_is_comp(block.page.frame)
|
||||||
|
? rec_get_heap_no_new(rec) : rec_get_heap_no_old(rec);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************//**
|
/*************************************************************//**
|
||||||
Updates the lock table when a page is merged to the right. */
|
Updates the lock table when a page is merged to the right. */
|
||||||
void
|
void
|
||||||
|
|
@ -3252,6 +3261,7 @@ lock_update_merge_right(
|
||||||
|
|
||||||
const page_id_t l{left_block->page.id()};
|
const page_id_t l{left_block->page.id()};
|
||||||
const page_id_t r{right_block->page.id()};
|
const page_id_t r{right_block->page.id()};
|
||||||
|
const ulint h= lock_get_heap_no(*right_block, orig_succ);
|
||||||
/* This would likely be too large for a memory transaction. */
|
/* This would likely be too large for a memory transaction. */
|
||||||
LockMultiGuard g{lock_sys.rec_hash, l, r};
|
LockMultiGuard g{lock_sys.rec_hash, l, r};
|
||||||
|
|
||||||
|
|
@ -3259,8 +3269,7 @@ lock_update_merge_right(
|
||||||
original successor of infimum on the right page, to which the left
|
original successor of infimum on the right page, to which the left
|
||||||
page was merged */
|
page was merged */
|
||||||
lock_rec_inherit_to_gap(g.cell2(), r, g.cell1(), l, right_block->page.frame,
|
lock_rec_inherit_to_gap(g.cell2(), r, g.cell1(), l, right_block->page.frame,
|
||||||
page_rec_get_heap_no(orig_succ),
|
h, PAGE_HEAP_NO_SUPREMUM);
|
||||||
PAGE_HEAP_NO_SUPREMUM);
|
|
||||||
|
|
||||||
/* Reset the locks on the supremum of the left page, releasing
|
/* Reset the locks on the supremum of the left page, releasing
|
||||||
waiting transactions */
|
waiting transactions */
|
||||||
|
|
@ -3329,21 +3338,38 @@ void lock_update_merge_left(const buf_block_t& left, const rec_t *orig_pred,
|
||||||
ut_ad(left.page.frame == page_align(orig_pred));
|
ut_ad(left.page.frame == page_align(orig_pred));
|
||||||
|
|
||||||
const page_id_t l{left.page.id()};
|
const page_id_t l{left.page.id()};
|
||||||
const rec_t *left_next_rec= page_rec_get_next_const(orig_pred);
|
const auto comp= page_is_comp(left.page.frame);
|
||||||
if (UNIV_UNLIKELY(!left_next_rec))
|
const rec_t *left_next_rec;
|
||||||
|
ulint heap_no;
|
||||||
|
if (comp)
|
||||||
{
|
{
|
||||||
ut_ad("corrupted page" == 0);
|
left_next_rec= page_rec_next_get<true>(left.page.frame, orig_pred);
|
||||||
return;
|
if (UNIV_UNLIKELY(!left_next_rec))
|
||||||
|
{
|
||||||
|
ut_ad("corrupted page" == 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
heap_no= rec_get_heap_no_new(left_next_rec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
left_next_rec= page_rec_next_get<false>(left.page.frame, orig_pred);
|
||||||
|
if (UNIV_UNLIKELY(!left_next_rec))
|
||||||
|
{
|
||||||
|
ut_ad("corrupted page" == 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
heap_no= rec_get_heap_no_old(left_next_rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This would likely be too large for a memory transaction. */
|
/* This would likely be too large for a memory transaction. */
|
||||||
LockMultiGuard g{lock_sys.rec_hash, l, right};
|
LockMultiGuard g{lock_sys.rec_hash, l, right};
|
||||||
if (!page_rec_is_supremum(left_next_rec))
|
if (heap_no != PAGE_HEAP_NO_SUPREMUM)
|
||||||
{
|
{
|
||||||
/* Inherit the locks on the supremum of the left page to the
|
/* Inherit the locks on the supremum of the left page to the
|
||||||
first record which was moved from the right page */
|
first record which was moved from the right page */
|
||||||
lock_rec_inherit_to_gap(g.cell1(), l, g.cell1(), l, left.page.frame,
|
lock_rec_inherit_to_gap(g.cell1(), l, g.cell1(), l, left.page.frame,
|
||||||
page_rec_get_heap_no(left_next_rec),
|
heap_no,
|
||||||
PAGE_HEAP_NO_SUPREMUM);
|
PAGE_HEAP_NO_SUPREMUM);
|
||||||
|
|
||||||
/* Reset the locks on the supremum of the left page,
|
/* Reset the locks on the supremum of the left page,
|
||||||
|
|
@ -3479,16 +3505,16 @@ lock_update_insert(
|
||||||
/* Inherit the gap-locking locks for rec, in gap mode, from the next
|
/* Inherit the gap-locking locks for rec, in gap mode, from the next
|
||||||
record */
|
record */
|
||||||
|
|
||||||
if (page_rec_is_comp(rec)) {
|
if (page_is_comp(block->page.frame)) {
|
||||||
receiver_heap_no = rec_get_heap_no_new(rec);
|
receiver_heap_no = rec_get_heap_no_new(rec);
|
||||||
rec = page_rec_get_next_low(rec, TRUE);
|
rec = page_rec_next_get<true>(block->page.frame, rec);
|
||||||
if (UNIV_UNLIKELY(!rec)) {
|
if (UNIV_UNLIKELY(!rec)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
donator_heap_no = rec_get_heap_no_new(rec);
|
donator_heap_no = rec_get_heap_no_new(rec);
|
||||||
} else {
|
} else {
|
||||||
receiver_heap_no = rec_get_heap_no_old(rec);
|
receiver_heap_no = rec_get_heap_no_old(rec);
|
||||||
rec = page_rec_get_next_low(rec, FALSE);
|
rec = page_rec_next_get<false>(block->page.frame, rec);
|
||||||
if (UNIV_UNLIKELY(!rec)) {
|
if (UNIV_UNLIKELY(!rec)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -3555,9 +3581,7 @@ lock_rec_store_on_page_infimum(
|
||||||
bits are reset on the
|
bits are reset on the
|
||||||
record */
|
record */
|
||||||
{
|
{
|
||||||
const ulint heap_no= page_rec_get_heap_no(rec);
|
const ulint heap_no= lock_get_heap_no(*block, rec);
|
||||||
|
|
||||||
ut_ad(block->page.frame == page_align(rec));
|
|
||||||
const page_id_t id{block->page.id()};
|
const page_id_t id{block->page.id()};
|
||||||
#ifdef ENABLED_DEBUG_SYNC
|
#ifdef ENABLED_DEBUG_SYNC
|
||||||
SCOPE_EXIT([]() { DEBUG_SYNC_C("lock_rec_store_on_page_infimum_end"); });
|
SCOPE_EXIT([]() { DEBUG_SYNC_C("lock_rec_store_on_page_infimum_end"); });
|
||||||
|
|
@ -3577,7 +3601,7 @@ whose infimum stored the lock state; lock bits are reset on the infimum */
|
||||||
void lock_rec_restore_from_page_infimum(const buf_block_t &block,
|
void lock_rec_restore_from_page_infimum(const buf_block_t &block,
|
||||||
const rec_t *rec, page_id_t donator)
|
const rec_t *rec, page_id_t donator)
|
||||||
{
|
{
|
||||||
const ulint heap_no= page_rec_get_heap_no(rec);
|
const ulint heap_no= lock_get_heap_no(block, rec);
|
||||||
const page_id_t id{block.page.id()};
|
const page_id_t id{block.page.id()};
|
||||||
LockMultiGuard g{lock_sys.rec_hash, id, donator};
|
LockMultiGuard g{lock_sys.rec_hash, id, donator};
|
||||||
lock_rec_move(g.cell1(), block, id, g.cell2(), donator, heap_no,
|
lock_rec_move(g.cell1(), block, id, g.cell2(), donator, heap_no,
|
||||||
|
|
@ -4262,21 +4286,22 @@ lock_rec_unlock(
|
||||||
/*============*/
|
/*============*/
|
||||||
trx_t* trx, /*!< in/out: transaction that has
|
trx_t* trx, /*!< in/out: transaction that has
|
||||||
set a record lock */
|
set a record lock */
|
||||||
const page_id_t id, /*!< in: page containing rec */
|
const buf_block_t& block, /*!< in: page containing rec */
|
||||||
const rec_t* rec, /*!< in: record */
|
const rec_t* rec, /*!< in: record */
|
||||||
lock_mode lock_mode)/*!< in: LOCK_S or LOCK_X */
|
lock_mode lock_mode)/*!< in: LOCK_S or LOCK_X */
|
||||||
{
|
{
|
||||||
lock_t* first_lock;
|
lock_t* first_lock;
|
||||||
lock_t* lock;
|
lock_t* lock;
|
||||||
ulint heap_no;
|
|
||||||
|
|
||||||
ut_ad(trx);
|
ut_ad(trx);
|
||||||
ut_ad(rec);
|
ut_ad(rec);
|
||||||
ut_ad(!trx->lock.wait_lock);
|
ut_ad(!trx->lock.wait_lock);
|
||||||
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
|
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
|
||||||
|
ut_ad(page_rec_is_leaf(rec));
|
||||||
ut_ad(!page_rec_is_metadata(rec));
|
ut_ad(!page_rec_is_metadata(rec));
|
||||||
|
|
||||||
heap_no = page_rec_get_heap_no(rec);
|
const ulint heap_no = lock_get_heap_no(block, rec);
|
||||||
|
const page_id_t id{block.page.id()};
|
||||||
|
|
||||||
LockGuard g{lock_sys.rec_hash, id};
|
LockGuard g{lock_sys.rec_hash, id};
|
||||||
|
|
||||||
|
|
@ -5752,14 +5777,26 @@ lock_rec_insert_check_and_lock(
|
||||||
ut_ad(page_is_leaf(block->page.frame));
|
ut_ad(page_is_leaf(block->page.frame));
|
||||||
ut_ad(!index->table->is_temporary());
|
ut_ad(!index->table->is_temporary());
|
||||||
|
|
||||||
const rec_t *next_rec= page_rec_get_next_const(rec);
|
const auto comp= page_is_comp(block->page.frame);
|
||||||
if (UNIV_UNLIKELY(!next_rec || rec_is_metadata(next_rec, *index)))
|
const rec_t *next_rec;
|
||||||
return DB_CORRUPTION;
|
if (UNIV_LIKELY(comp != 0))
|
||||||
|
{
|
||||||
|
next_rec= page_rec_next_get<true>(block->page.frame, rec);
|
||||||
|
if (UNIV_UNLIKELY(!next_rec || rec_is_metadata(next_rec, TRUE)))
|
||||||
|
return DB_CORRUPTION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
next_rec= page_rec_next_get<false>(block->page.frame, rec);
|
||||||
|
if (UNIV_UNLIKELY(!next_rec || rec_is_metadata(next_rec, FALSE)))
|
||||||
|
return DB_CORRUPTION;
|
||||||
|
}
|
||||||
|
|
||||||
dberr_t err= DB_SUCCESS;
|
dberr_t err= DB_SUCCESS;
|
||||||
bool inherit_in= *inherit;
|
bool inherit_in= *inherit;
|
||||||
trx_t *trx= thr_get_trx(thr);
|
trx_t *trx= thr_get_trx(thr);
|
||||||
ulint heap_no= page_rec_get_heap_no(next_rec);
|
const ulint heap_no= comp
|
||||||
|
? rec_get_heap_no_new(next_rec) : rec_get_heap_no_old(next_rec);
|
||||||
const page_id_t id{block->page.id()};
|
const page_id_t id{block->page.id()};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -5842,12 +5879,12 @@ lock_rec_insert_check_and_lock(
|
||||||
/** Create an explicit record lock for a transaction that currently only
|
/** Create an explicit record lock for a transaction that currently only
|
||||||
has an implicit lock on the record.
|
has an implicit lock on the record.
|
||||||
@param trx referenced, active transaction, or nullptr
|
@param trx referenced, active transaction, or nullptr
|
||||||
@param id page identifier
|
@param block index leaf page
|
||||||
@param rec record in the page
|
@param rec record in the page
|
||||||
@param index the index B-tree that the record belongs to
|
@param index the index B-tree that the record belongs to
|
||||||
@return trx, with the reference released */
|
@return trx, with the reference released */
|
||||||
static trx_t *lock_rec_convert_impl_to_expl_for_trx(trx_t *trx,
|
static trx_t *lock_rec_convert_impl_to_expl_for_trx(trx_t *trx,
|
||||||
const page_id_t id,
|
const buf_block_t &block,
|
||||||
const rec_t *rec,
|
const rec_t *rec,
|
||||||
dict_index_t *index)
|
dict_index_t *index)
|
||||||
{
|
{
|
||||||
|
|
@ -5857,7 +5894,8 @@ static trx_t *lock_rec_convert_impl_to_expl_for_trx(trx_t *trx,
|
||||||
ut_ad(page_rec_is_leaf(rec));
|
ut_ad(page_rec_is_leaf(rec));
|
||||||
ut_ad(!rec_is_metadata(rec, *index));
|
ut_ad(!rec_is_metadata(rec, *index));
|
||||||
|
|
||||||
ulint heap_no= page_rec_get_heap_no(rec);
|
const ulint heap_no= lock_get_heap_no(block, rec);
|
||||||
|
const page_id_t id{block.page.id()};
|
||||||
|
|
||||||
{
|
{
|
||||||
LockGuard g{lock_sys.rec_hash, id};
|
LockGuard g{lock_sys.rec_hash, id};
|
||||||
|
|
@ -5962,7 +6000,7 @@ should be created.
|
||||||
|
|
||||||
@tparam is_primary whether the index is the primary key
|
@tparam is_primary whether the index is the primary key
|
||||||
@param[in,out] caller_trx current transaction
|
@param[in,out] caller_trx current transaction
|
||||||
@param[in] id index tree leaf page identifier
|
@param[in] block index tree leaf page
|
||||||
@param[in] rec record on the leaf page
|
@param[in] rec record on the leaf page
|
||||||
@param[in] index the index of the record
|
@param[in] index the index of the record
|
||||||
@param[in] offsets rec_get_offsets(rec,index)
|
@param[in] offsets rec_get_offsets(rec,index)
|
||||||
|
|
@ -5973,7 +6011,7 @@ static
|
||||||
const trx_t *
|
const trx_t *
|
||||||
lock_rec_convert_impl_to_expl(
|
lock_rec_convert_impl_to_expl(
|
||||||
trx_t* caller_trx,
|
trx_t* caller_trx,
|
||||||
page_id_t id,
|
const buf_block_t& block,
|
||||||
const rec_t* rec,
|
const rec_t* rec,
|
||||||
dict_index_t* index,
|
dict_index_t* index,
|
||||||
const rec_offs* offsets)
|
const rec_offs* offsets)
|
||||||
|
|
@ -6011,10 +6049,11 @@ lock_rec_convert_impl_to_expl(
|
||||||
return trx;
|
return trx;
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_d(lock_rec_other_trx_holds_expl(caller_trx, trx, rec, id));
|
ut_d(lock_rec_other_trx_holds_expl(caller_trx, trx, rec,
|
||||||
|
block.page.id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return lock_rec_convert_impl_to_expl_for_trx(trx, id, rec, index);
|
return lock_rec_convert_impl_to_expl_for_trx(trx, block, rec, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
|
|
@ -6055,7 +6094,7 @@ lock_clust_rec_modify_check_and_lock(
|
||||||
|
|
||||||
trx_t *trx = thr_get_trx(thr);
|
trx_t *trx = thr_get_trx(thr);
|
||||||
if (const trx_t *owner =
|
if (const trx_t *owner =
|
||||||
lock_rec_convert_impl_to_expl<true>(trx, block->page.id(),
|
lock_rec_convert_impl_to_expl<true>(trx, *block,
|
||||||
rec, index, offsets)) {
|
rec, index, offsets)) {
|
||||||
if (owner == trx) {
|
if (owner == trx) {
|
||||||
/* We already hold an exclusive lock. */
|
/* We already hold an exclusive lock. */
|
||||||
|
|
@ -6105,7 +6144,6 @@ lock_sec_rec_modify_check_and_lock(
|
||||||
|
|
||||||
ut_ad(!dict_index_is_clust(index));
|
ut_ad(!dict_index_is_clust(index));
|
||||||
ut_ad(!dict_index_is_online_ddl(index) || (flags & BTR_CREATE_FLAG));
|
ut_ad(!dict_index_is_online_ddl(index) || (flags & BTR_CREATE_FLAG));
|
||||||
ut_ad(block->page.frame == page_align(rec));
|
|
||||||
ut_ad(mtr->is_named_space(index->table->space));
|
ut_ad(mtr->is_named_space(index->table->space));
|
||||||
ut_ad(page_rec_is_leaf(rec));
|
ut_ad(page_rec_is_leaf(rec));
|
||||||
ut_ad(!rec_is_metadata(rec, *index));
|
ut_ad(!rec_is_metadata(rec, *index));
|
||||||
|
|
@ -6116,7 +6154,7 @@ lock_sec_rec_modify_check_and_lock(
|
||||||
}
|
}
|
||||||
ut_ad(!index->table->is_temporary());
|
ut_ad(!index->table->is_temporary());
|
||||||
|
|
||||||
heap_no = page_rec_get_heap_no(rec);
|
heap_no = lock_get_heap_no(*block, rec);
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
trx_t *trx= thr_get_trx(thr);
|
trx_t *trx= thr_get_trx(thr);
|
||||||
|
|
@ -6229,7 +6267,7 @@ lock_sec_rec_read_check_and_lock(
|
||||||
|
|
||||||
if (page_rec_is_supremum(rec)) {
|
if (page_rec_is_supremum(rec)) {
|
||||||
} else if (const trx_t *owner =
|
} else if (const trx_t *owner =
|
||||||
lock_rec_convert_impl_to_expl<false>(trx, block->page.id(),
|
lock_rec_convert_impl_to_expl<false>(trx, *block,
|
||||||
rec, index, offsets)) {
|
rec, index, offsets)) {
|
||||||
if (owner == trx) {
|
if (owner == trx) {
|
||||||
if (gap_mode == LOCK_REC_NOT_GAP) {
|
if (gap_mode == LOCK_REC_NOT_GAP) {
|
||||||
|
|
@ -6255,7 +6293,7 @@ lock_sec_rec_read_check_and_lock(
|
||||||
#endif /* WITH_WSREP */
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
err = lock_rec_lock(false, gap_mode | mode,
|
err = lock_rec_lock(false, gap_mode | mode,
|
||||||
block, page_rec_get_heap_no(rec), index, thr);
|
block, lock_get_heap_no(*block, rec), index, thr);
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if (trx->wsrep == 3) trx->wsrep = 1;
|
if (trx->wsrep == 3) trx->wsrep = 1;
|
||||||
|
|
@ -6314,15 +6352,13 @@ lock_clust_rec_read_check_and_lock(
|
||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
const page_id_t id{block->page.id()};
|
const ulint heap_no = lock_get_heap_no(*block, rec);
|
||||||
|
|
||||||
ulint heap_no = page_rec_get_heap_no(rec);
|
|
||||||
|
|
||||||
trx_t *trx = thr_get_trx(thr);
|
trx_t *trx = thr_get_trx(thr);
|
||||||
if (lock_table_has(trx, index->table, LOCK_X)
|
if (lock_table_has(trx, index->table, LOCK_X)
|
||||||
|| heap_no == PAGE_HEAP_NO_SUPREMUM) {
|
|| heap_no == PAGE_HEAP_NO_SUPREMUM) {
|
||||||
} else if (const trx_t *owner =
|
} else if (const trx_t *owner =
|
||||||
lock_rec_convert_impl_to_expl<true>(trx, id,
|
lock_rec_convert_impl_to_expl<true>(trx, *block,
|
||||||
rec, index, offsets)) {
|
rec, index, offsets)) {
|
||||||
if (owner == trx) {
|
if (owner == trx) {
|
||||||
if (gap_mode == LOCK_REC_NOT_GAP) {
|
if (gap_mode == LOCK_REC_NOT_GAP) {
|
||||||
|
|
@ -6346,7 +6382,8 @@ lock_clust_rec_read_check_and_lock(
|
||||||
dberr_t err = lock_rec_lock(false, gap_mode | mode,
|
dberr_t err = lock_rec_lock(false, gap_mode | mode,
|
||||||
block, heap_no, index, thr);
|
block, heap_no, index, thr);
|
||||||
|
|
||||||
ut_ad(lock_rec_queue_validate(false, id, rec, index, offsets));
|
ut_ad(lock_rec_queue_validate(false, block->page.id(),
|
||||||
|
rec, index, offsets));
|
||||||
|
|
||||||
DEBUG_SYNC_C("after_lock_clust_rec_read_check_and_lock");
|
DEBUG_SYNC_C("after_lock_clust_rec_read_check_and_lock");
|
||||||
|
|
||||||
|
|
@ -7234,16 +7271,42 @@ void lock_update_split_and_merge(
|
||||||
ut_ad(page_is_leaf(left_block->page.frame));
|
ut_ad(page_is_leaf(left_block->page.frame));
|
||||||
ut_ad(page_is_leaf(right_block->page.frame));
|
ut_ad(page_is_leaf(right_block->page.frame));
|
||||||
ut_ad(page_align(orig_pred) == left_block->page.frame);
|
ut_ad(page_align(orig_pred) == left_block->page.frame);
|
||||||
|
const auto comp= page_is_comp(left_block->page.frame);
|
||||||
|
|
||||||
const page_id_t l{left_block->page.id()};
|
const page_id_t l{left_block->page.id()};
|
||||||
const page_id_t r{right_block->page.id()};
|
const page_id_t r{right_block->page.id()};
|
||||||
const rec_t *left_next_rec= page_rec_get_next_const(orig_pred);
|
const rec_t *left_next_rec;
|
||||||
if (UNIV_UNLIKELY(!left_next_rec))
|
ulint left_heap_no, right_heap_no;
|
||||||
|
if (UNIV_LIKELY(comp != 0))
|
||||||
{
|
{
|
||||||
ut_ad("corrupted page" == 0);
|
left_next_rec= page_rec_next_get<true>(left_block->page.frame, orig_pred);
|
||||||
return;
|
if (UNIV_UNLIKELY(!left_next_rec))
|
||||||
|
{
|
||||||
|
ut_ad("corrupted page" == 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ut_ad(!rec_is_metadata(left_next_rec, comp));
|
||||||
|
left_heap_no= rec_get_heap_no_new(left_next_rec);
|
||||||
|
right_heap_no=
|
||||||
|
rec_get_heap_no_new(right_block->page.frame +
|
||||||
|
rec_get_next_offs(right_block->page.frame +
|
||||||
|
PAGE_NEW_INFIMUM, TRUE));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
left_next_rec= page_rec_next_get<false>(left_block->page.frame, orig_pred);
|
||||||
|
if (UNIV_UNLIKELY(!left_next_rec))
|
||||||
|
{
|
||||||
|
ut_ad("corrupted page" == 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ut_ad(!rec_is_metadata(left_next_rec, comp));
|
||||||
|
left_heap_no= rec_get_heap_no_old(left_next_rec);
|
||||||
|
right_heap_no=
|
||||||
|
rec_get_heap_no_old(right_block->page.frame +
|
||||||
|
rec_get_next_offs(right_block->page.frame +
|
||||||
|
PAGE_OLD_INFIMUM, FALSE));
|
||||||
}
|
}
|
||||||
ut_ad(!page_rec_is_metadata(left_next_rec));
|
|
||||||
|
|
||||||
/* This would likely be too large for a memory transaction. */
|
/* This would likely be too large for a memory transaction. */
|
||||||
LockMultiGuard g{lock_sys.rec_hash, l, r};
|
LockMultiGuard g{lock_sys.rec_hash, l, r};
|
||||||
|
|
@ -7251,8 +7314,7 @@ void lock_update_split_and_merge(
|
||||||
/* Inherit the locks on the supremum of the left page to the
|
/* Inherit the locks on the supremum of the left page to the
|
||||||
first record which was moved from the right page */
|
first record which was moved from the right page */
|
||||||
lock_rec_inherit_to_gap(g.cell1(), l, g.cell1(), l, left_block->page.frame,
|
lock_rec_inherit_to_gap(g.cell1(), l, g.cell1(), l, left_block->page.frame,
|
||||||
page_rec_get_heap_no(left_next_rec),
|
left_heap_no, PAGE_HEAP_NO_SUPREMUM);
|
||||||
PAGE_HEAP_NO_SUPREMUM);
|
|
||||||
|
|
||||||
/* Reset the locks on the supremum of the left page,
|
/* Reset the locks on the supremum of the left page,
|
||||||
releasing waiting transactions */
|
releasing waiting transactions */
|
||||||
|
|
@ -7261,6 +7323,5 @@ void lock_update_split_and_merge(
|
||||||
/* Inherit the locks to the supremum of the left page from the
|
/* Inherit the locks to the supremum of the left page from the
|
||||||
successor of the infimum on the right page */
|
successor of the infimum on the right page */
|
||||||
lock_rec_inherit_to_gap(g.cell1(), l, g.cell2(), r, left_block->page.frame,
|
lock_rec_inherit_to_gap(g.cell1(), l, g.cell2(), r, left_block->page.frame,
|
||||||
PAGE_HEAP_NO_SUPREMUM,
|
PAGE_HEAP_NO_SUPREMUM, right_heap_no);
|
||||||
lock_get_min_heap_no(right_block));
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1516,7 +1516,6 @@ void recv_sys_t::debug_free()
|
||||||
inline void recv_sys_t::free(const void *data)
|
inline void recv_sys_t::free(const void *data)
|
||||||
{
|
{
|
||||||
ut_ad(!ut_align_offset(data, ALIGNMENT));
|
ut_ad(!ut_align_offset(data, ALIGNMENT));
|
||||||
data= page_align(data);
|
|
||||||
mysql_mutex_assert_owner(&mutex);
|
mysql_mutex_assert_owner(&mutex);
|
||||||
|
|
||||||
/* MDEV-14481 FIXME: To prevent race condition with buf_pool.resize(),
|
/* MDEV-14481 FIXME: To prevent race condition with buf_pool.resize(),
|
||||||
|
|
@ -1533,7 +1532,7 @@ inline void recv_sys_t::free(const void *data)
|
||||||
if (offs >= chunk->size)
|
if (offs >= chunk->size)
|
||||||
continue;
|
continue;
|
||||||
buf_block_t *block= &chunk->blocks[offs];
|
buf_block_t *block= &chunk->blocks[offs];
|
||||||
ut_ad(block->page.frame == data);
|
ut_ad(block->page.frame == page_align(data));
|
||||||
ut_ad(block->page.state() == buf_page_t::MEMORY);
|
ut_ad(block->page.state() == buf_page_t::MEMORY);
|
||||||
ut_ad(static_cast<uint16_t>(block->page.access_time - 1) <
|
ut_ad(static_cast<uint16_t>(block->page.access_time - 1) <
|
||||||
srv_page_size);
|
srv_page_size);
|
||||||
|
|
|
||||||
|
|
@ -925,7 +925,7 @@ static void page_zip_dir_split_slot(buf_block_t *block, ulint s, mtr_t* mtr)
|
||||||
|
|
||||||
/* Log changes to the compressed page header and the dense page directory. */
|
/* Log changes to the compressed page header and the dense page directory. */
|
||||||
memcpy_aligned<2>(&block->page.zip.data[n_slots_f], n_slots_p, 2);
|
memcpy_aligned<2>(&block->page.zip.data[n_slots_f], n_slots_p, 2);
|
||||||
mach_write_to_2(slot, page_offset(rec));
|
mach_write_to_2(slot, rec - block->page.frame);
|
||||||
page_rec_set_n_owned<true>(block, page_dir_slot_get_rec(slot), half_owned,
|
page_rec_set_n_owned<true>(block, page_dir_slot_get_rec(slot), half_owned,
|
||||||
true, mtr);
|
true, mtr);
|
||||||
page_rec_set_n_owned<true>(block,
|
page_rec_set_n_owned<true>(block,
|
||||||
|
|
@ -990,7 +990,8 @@ static void page_zip_dir_balance_slot(buf_block_t *block, ulint s, mtr_t *mtr)
|
||||||
|
|
||||||
/* Transfer one record to the underfilled slot */
|
/* Transfer one record to the underfilled slot */
|
||||||
page_rec_set_n_owned<true>(block, slot_rec, 0, true, mtr);
|
page_rec_set_n_owned<true>(block, slot_rec, 0, true, mtr);
|
||||||
const rec_t* new_rec = page_rec_get_next_low(slot_rec, TRUE);
|
const rec_t* new_rec = page_rec_next_get<true>(block->page.frame,
|
||||||
|
slot_rec);
|
||||||
/* We do not try to prevent crash on corruption here.
|
/* We do not try to prevent crash on corruption here.
|
||||||
For ROW_FORMAT=COMPRESSED pages, the next-record links should
|
For ROW_FORMAT=COMPRESSED pages, the next-record links should
|
||||||
be validated in page_zip_decompress(). Corruption should only
|
be validated in page_zip_decompress(). Corruption should only
|
||||||
|
|
@ -998,7 +999,7 @@ static void page_zip_dir_balance_slot(buf_block_t *block, ulint s, mtr_t *mtr)
|
||||||
page_rec_set_n_owned<true>(block, const_cast<rec_t*>(new_rec),
|
page_rec_set_n_owned<true>(block, const_cast<rec_t*>(new_rec),
|
||||||
PAGE_DIR_SLOT_MIN_N_OWNED,
|
PAGE_DIR_SLOT_MIN_N_OWNED,
|
||||||
true, mtr);
|
true, mtr);
|
||||||
mach_write_to_2(slot, page_offset(new_rec));
|
mach_write_to_2(slot, new_rec - block->page.frame);
|
||||||
page_rec_set_n_owned(up_rec, up_n_owned - 1, true);
|
page_rec_set_n_owned(up_rec, up_n_owned - 1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1060,7 +1061,8 @@ static void page_dir_balance_slot(const buf_block_t &block, ulint s)
|
||||||
|
|
||||||
if (comp) {
|
if (comp) {
|
||||||
if (UNIV_UNLIKELY(!(new_rec =
|
if (UNIV_UNLIKELY(!(new_rec =
|
||||||
page_rec_get_next_low(slot_rec, true)))) {
|
page_rec_next_get<true>(block.page.frame,
|
||||||
|
slot_rec)))) {
|
||||||
ut_ad("corrupted page" == 0);
|
ut_ad("corrupted page" == 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1070,7 +1072,8 @@ static void page_dir_balance_slot(const buf_block_t &block, ulint s)
|
||||||
page_rec_set_n_owned(up_rec, up_n_owned - 1, true);
|
page_rec_set_n_owned(up_rec, up_n_owned - 1, true);
|
||||||
} else {
|
} else {
|
||||||
if (UNIV_UNLIKELY(!(new_rec =
|
if (UNIV_UNLIKELY(!(new_rec =
|
||||||
page_rec_get_next_low(slot_rec, false)))) {
|
page_rec_next_get<false>(block.page.frame,
|
||||||
|
slot_rec)))) {
|
||||||
ut_ad("corrupted page" == 0);
|
ut_ad("corrupted page" == 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1080,7 +1083,7 @@ static void page_dir_balance_slot(const buf_block_t &block, ulint s)
|
||||||
page_rec_set_n_owned(up_rec, up_n_owned - 1, false);
|
page_rec_set_n_owned(up_rec, up_n_owned - 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mach_write_to_2(slot, page_offset(new_rec));
|
mach_write_to_2(slot, new_rec - block.page.frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allocate space for inserting an index record.
|
/** Allocate space for inserting an index record.
|
||||||
|
|
@ -1476,7 +1479,8 @@ use_heap:
|
||||||
rec_get_node_ptr_flag(rec));
|
rec_get_node_ptr_flag(rec));
|
||||||
|
|
||||||
/* Write PAGE_LAST_INSERT */
|
/* Write PAGE_LAST_INSERT */
|
||||||
mach_write_to_2(page_last_insert, page_offset(insert_buf + extra_size));
|
mach_write_to_2(page_last_insert,
|
||||||
|
insert_buf + extra_size - block->page.frame);
|
||||||
|
|
||||||
/* Update PAGE_DIRECTION_B, PAGE_N_DIRECTION if needed */
|
/* Update PAGE_DIRECTION_B, PAGE_N_DIRECTION if needed */
|
||||||
if (block->page.frame[FIL_PAGE_TYPE + 1] != byte(FIL_PAGE_RTREE))
|
if (block->page.frame[FIL_PAGE_TYPE + 1] != byte(FIL_PAGE_RTREE))
|
||||||
|
|
@ -1609,7 +1613,7 @@ inc_dir:
|
||||||
rec_set_bit_field_2(insert_rec, heap_no,
|
rec_set_bit_field_2(insert_rec, heap_no,
|
||||||
REC_OLD_HEAP_NO, REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT);
|
REC_OLD_HEAP_NO, REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT);
|
||||||
memcpy(insert_rec - REC_NEXT, cur->rec - REC_NEXT, 2);
|
memcpy(insert_rec - REC_NEXT, cur->rec - REC_NEXT, 2);
|
||||||
mach_write_to_2(cur->rec - REC_NEXT, page_offset(insert_rec));
|
mach_write_to_2(cur->rec - REC_NEXT, insert_rec - block->page.frame);
|
||||||
while (!(n_owned= rec_get_n_owned_old(next_rec)))
|
while (!(n_owned= rec_get_n_owned_old(next_rec)))
|
||||||
{
|
{
|
||||||
next_rec= block->page.frame + rec_get_next_offs(next_rec, false);
|
next_rec= block->page.frame + rec_get_next_offs(next_rec, false);
|
||||||
|
|
@ -2049,7 +2053,7 @@ use_heap:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* next record after current before the insertion */
|
/* next record after current before the insertion */
|
||||||
const rec_t *next_rec = page_rec_get_next_low(cursor->rec, TRUE);
|
const rec_t *next_rec = page_rec_next_get<true>(page, cursor->rec);
|
||||||
if (UNIV_UNLIKELY(!next_rec ||
|
if (UNIV_UNLIKELY(!next_rec ||
|
||||||
rec_get_status(next_rec) == REC_STATUS_INFIMUM ||
|
rec_get_status(next_rec) == REC_STATUS_INFIMUM ||
|
||||||
rec_get_status(cursor->rec) > REC_STATUS_INFIMUM))
|
rec_get_status(cursor->rec) > REC_STATUS_INFIMUM))
|
||||||
|
|
@ -2088,7 +2092,7 @@ use_heap:
|
||||||
ut_ad(!last_insert_rec ||
|
ut_ad(!last_insert_rec ||
|
||||||
rec_get_node_ptr_flag(page + last_insert_rec) ==
|
rec_get_node_ptr_flag(page + last_insert_rec) ==
|
||||||
rec_get_node_ptr_flag(insert_rec));
|
rec_get_node_ptr_flag(insert_rec));
|
||||||
mach_write_to_2(last_insert, page_offset(insert_rec));
|
mach_write_to_2(last_insert, insert_rec - page);
|
||||||
|
|
||||||
if (!index->is_spatial())
|
if (!index->is_spatial())
|
||||||
{
|
{
|
||||||
|
|
@ -2108,7 +2112,7 @@ no_direction:
|
||||||
inc_dir:
|
inc_dir:
|
||||||
mach_write_to_2(n, mach_read_from_2(n) + 1);
|
mach_write_to_2(n, mach_read_from_2(n) + 1);
|
||||||
}
|
}
|
||||||
else if (*dir != PAGE_RIGHT && page_rec_get_next(insert_rec) ==
|
else if (*dir != PAGE_RIGHT && page_rec_next_get<true>(page, insert_rec) ==
|
||||||
page + last_insert_rec)
|
page + last_insert_rec)
|
||||||
{
|
{
|
||||||
*dir= PAGE_LEFT;
|
*dir= PAGE_LEFT;
|
||||||
|
|
@ -2129,7 +2133,7 @@ inc_dir:
|
||||||
ulint n_owned;
|
ulint n_owned;
|
||||||
|
|
||||||
while (!(n_owned= rec_get_n_owned_new(next_rec)))
|
while (!(n_owned= rec_get_n_owned_new(next_rec)))
|
||||||
if (!(next_rec= page_rec_get_next_low(next_rec, true)))
|
if (!(next_rec= page_rec_next_get<true>(page, next_rec)))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
rec_set_bit_field_1(const_cast<rec_t*>(next_rec), n_owned + 1,
|
rec_set_bit_field_1(const_cast<rec_t*>(next_rec), n_owned + 1,
|
||||||
|
|
@ -2179,12 +2183,13 @@ static void page_mem_free(const buf_block_t &block, rec_t *rec,
|
||||||
byte *page_heap_top= my_assume_aligned<2>(PAGE_HEAP_TOP + PAGE_HEADER +
|
byte *page_heap_top= my_assume_aligned<2>(PAGE_HEAP_TOP + PAGE_HEADER +
|
||||||
block.page.frame);
|
block.page.frame);
|
||||||
const uint16_t heap_top= mach_read_from_2(page_heap_top);
|
const uint16_t heap_top= mach_read_from_2(page_heap_top);
|
||||||
const size_t extra_savings= heap_top - page_offset(rec + data_size);
|
const size_t extra_savings= heap_top -
|
||||||
|
(rec + data_size - block.page.frame);
|
||||||
ut_ad(extra_savings < heap_top);
|
ut_ad(extra_savings < heap_top);
|
||||||
|
|
||||||
/* When deleting the last record, do not add it to the PAGE_FREE list.
|
/* When deleting the last record, do not add it to the PAGE_FREE list.
|
||||||
Instead, decrement PAGE_HEAP_TOP and PAGE_N_HEAP. */
|
Instead, decrement PAGE_HEAP_TOP and PAGE_N_HEAP. */
|
||||||
mach_write_to_2(page_heap_top, page_offset(rec - extra_size));
|
mach_write_to_2(page_heap_top, rec - extra_size - block.page.frame);
|
||||||
mach_write_to_2(my_assume_aligned<2>(page_heap_top + 2), n_heap);
|
mach_write_to_2(my_assume_aligned<2>(page_heap_top + 2), n_heap);
|
||||||
static_assert(PAGE_N_HEAP == PAGE_HEAP_TOP + 2, "compatibility");
|
static_assert(PAGE_N_HEAP == PAGE_HEAP_TOP + 2, "compatibility");
|
||||||
if (extra_savings)
|
if (extra_savings)
|
||||||
|
|
@ -2202,7 +2207,7 @@ static void page_mem_free(const buf_block_t &block, rec_t *rec,
|
||||||
block.page.frame);
|
block.page.frame);
|
||||||
byte *page_garbage= my_assume_aligned<2>(PAGE_GARBAGE + PAGE_HEADER +
|
byte *page_garbage= my_assume_aligned<2>(PAGE_GARBAGE + PAGE_HEADER +
|
||||||
block.page.frame);
|
block.page.frame);
|
||||||
mach_write_to_2(page_free, page_offset(rec));
|
mach_write_to_2(page_free, rec - block.page.frame);
|
||||||
mach_write_to_2(page_garbage, mach_read_from_2(page_garbage) +
|
mach_write_to_2(page_garbage, mach_read_from_2(page_garbage) +
|
||||||
extra_size + data_size);
|
extra_size + data_size);
|
||||||
}
|
}
|
||||||
|
|
@ -2346,7 +2351,8 @@ page_cur_delete_rec(
|
||||||
page_zip_rec_set_owned(block, prev_rec, 1, mtr);
|
page_zip_rec_set_owned(block, prev_rec, 1, mtr);
|
||||||
page_zip_rec_set_owned(block, slot_rec, 0, mtr);
|
page_zip_rec_set_owned(block, slot_rec, 0, mtr);
|
||||||
slot_rec = prev_rec;
|
slot_rec = prev_rec;
|
||||||
mach_write_to_2(cur_dir_slot, page_offset(slot_rec));
|
mach_write_to_2(cur_dir_slot,
|
||||||
|
slot_rec - block->page.frame);
|
||||||
} else if (cur_n_owned == 1
|
} else if (cur_n_owned == 1
|
||||||
&& !page_rec_is_supremum(slot_rec)) {
|
&& !page_rec_is_supremum(slot_rec)) {
|
||||||
page_zip_rec_set_owned(block, slot_rec, 0, mtr);
|
page_zip_rec_set_owned(block, slot_rec, 0, mtr);
|
||||||
|
|
@ -2371,14 +2377,14 @@ page_cur_delete_rec(
|
||||||
|
|
||||||
if (current_rec == slot_rec) {
|
if (current_rec == slot_rec) {
|
||||||
slot_rec = prev_rec;
|
slot_rec = prev_rec;
|
||||||
mach_write_to_2(cur_dir_slot, page_offset(slot_rec));
|
mach_write_to_2(cur_dir_slot, slot_rec - block->page.frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t data_size = rec_offs_data_size(offsets);
|
const size_t data_size = rec_offs_data_size(offsets);
|
||||||
const size_t extra_size = rec_offs_extra_size(offsets);
|
const size_t extra_size = rec_offs_extra_size(offsets);
|
||||||
|
|
||||||
if (page_is_comp(block->page.frame)) {
|
if (page_is_comp(block->page.frame)) {
|
||||||
mtr->page_delete(*block, page_offset(prev_rec)
|
mtr->page_delete(*block, prev_rec - block->page.frame
|
||||||
- PAGE_NEW_INFIMUM,
|
- PAGE_NEW_INFIMUM,
|
||||||
extra_size - REC_N_NEW_EXTRA_BYTES,
|
extra_size - REC_N_NEW_EXTRA_BYTES,
|
||||||
data_size);
|
data_size);
|
||||||
|
|
@ -2388,7 +2394,7 @@ page_cur_delete_rec(
|
||||||
(slot_rec[-REC_NEW_N_OWNED] & ~REC_N_OWNED_MASK)
|
(slot_rec[-REC_NEW_N_OWNED] & ~REC_N_OWNED_MASK)
|
||||||
| (cur_n_owned - 1) << REC_N_OWNED_SHIFT);
|
| (cur_n_owned - 1) << REC_N_OWNED_SHIFT);
|
||||||
} else {
|
} else {
|
||||||
mtr->page_delete(*block, page_offset(prev_rec)
|
mtr->page_delete(*block, prev_rec - block->page.frame
|
||||||
- PAGE_OLD_INFIMUM);
|
- PAGE_OLD_INFIMUM);
|
||||||
memcpy(prev_rec - REC_NEXT, current_rec - REC_NEXT, 2);
|
memcpy(prev_rec - REC_NEXT, current_rec - REC_NEXT, 2);
|
||||||
slot_rec[-REC_OLD_N_OWNED] = static_cast<byte>(
|
slot_rec[-REC_OLD_N_OWNED] = static_cast<byte>(
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ page_dir_find_owner_slot(
|
||||||
|
|
||||||
if (page_is_comp(page)) {
|
if (page_is_comp(page)) {
|
||||||
while (rec_get_n_owned_new(r) == 0) {
|
while (rec_get_n_owned_new(r) == 0) {
|
||||||
r = page_rec_get_next_low(r, true);
|
r = page_rec_next_get<true>(page, r);
|
||||||
if (UNIV_UNLIKELY(r < page + PAGE_NEW_SUPREMUM
|
if (UNIV_UNLIKELY(r < page + PAGE_NEW_SUPREMUM
|
||||||
|| r >= slot)) {
|
|| r >= slot)) {
|
||||||
return ULINT_UNDEFINED;
|
return ULINT_UNDEFINED;
|
||||||
|
|
@ -107,7 +107,7 @@ page_dir_find_owner_slot(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (rec_get_n_owned_old(r) == 0) {
|
while (rec_get_n_owned_old(r) == 0) {
|
||||||
r = page_rec_get_next_low(r, false);
|
r = page_rec_next_get<false>(page, r);
|
||||||
if (UNIV_UNLIKELY(r < page + PAGE_OLD_SUPREMUM
|
if (UNIV_UNLIKELY(r < page + PAGE_OLD_SUPREMUM
|
||||||
|| r >= slot)) {
|
|| r >= slot)) {
|
||||||
return ULINT_UNDEFINED;
|
return ULINT_UNDEFINED;
|
||||||
|
|
@ -465,7 +465,8 @@ page_copy_rec_list_end_no_locks(
|
||||||
return DB_CORRUPTION;
|
return DB_CORRUPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(page_is_comp(new_page) != page_rec_is_comp(rec)
|
if (UNIV_UNLIKELY(page_is_comp(new_page)
|
||||||
|
!= page_is_comp(block->page.frame)
|
||||||
|| mach_read_from_2(new_page + srv_page_size - 10)
|
|| mach_read_from_2(new_page + srv_page_size - 10)
|
||||||
!= ulint(page_is_comp(new_page)
|
!= ulint(page_is_comp(new_page)
|
||||||
? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM))) {
|
? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM))) {
|
||||||
|
|
@ -893,11 +894,12 @@ page_delete_rec_list_end(
|
||||||
return DB_SUCCESS;
|
return DB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_rec_is_infimum(rec) ||
|
if (n_recs == page_get_n_recs(page) ||
|
||||||
n_recs == page_get_n_recs(page) ||
|
(page_is_comp(page)
|
||||||
rec == (page_is_comp(page)
|
? (rec == page + PAGE_NEW_INFIMUM ||
|
||||||
? page_rec_get_next_low(page + PAGE_NEW_INFIMUM, 1)
|
rec == page_rec_next_get<true>(page, page + PAGE_NEW_INFIMUM))
|
||||||
: page_rec_get_next_low(page + PAGE_OLD_INFIMUM, 0)))
|
: (rec == page + PAGE_OLD_INFIMUM ||
|
||||||
|
rec == page_rec_next_get<false>(page, page + PAGE_OLD_INFIMUM))))
|
||||||
{
|
{
|
||||||
/* We are deleting all records. */
|
/* We are deleting all records. */
|
||||||
page_create_empty(block, index, mtr);
|
page_create_empty(block, index, mtr);
|
||||||
|
|
@ -933,13 +935,13 @@ page_delete_rec_list_end(
|
||||||
cur.index= index;
|
cur.index= index;
|
||||||
offsets= rec_get_offsets(rec, index, offsets, n_core,
|
offsets= rec_get_offsets(rec, index, offsets, n_core,
|
||||||
ULINT_UNDEFINED, &heap);
|
ULINT_UNDEFINED, &heap);
|
||||||
rec= const_cast<rec_t*>(page_rec_get_next_low(rec, true));
|
rec= const_cast<rec_t*>(page_rec_next_get<true>(page, rec));
|
||||||
#ifdef UNIV_ZIP_DEBUG
|
#ifdef UNIV_ZIP_DEBUG
|
||||||
ut_a(page_zip_validate(&block->page.zip, page, index));
|
ut_a(page_zip_validate(&block->page.zip, page, index));
|
||||||
#endif /* UNIV_ZIP_DEBUG */
|
#endif /* UNIV_ZIP_DEBUG */
|
||||||
page_cur_delete_rec(&cur, offsets, mtr);
|
page_cur_delete_rec(&cur, offsets, mtr);
|
||||||
}
|
}
|
||||||
while (page_offset(rec) != PAGE_NEW_SUPREMUM);
|
while (rec - page != PAGE_NEW_SUPREMUM);
|
||||||
|
|
||||||
if (UNIV_LIKELY_NULL(heap))
|
if (UNIV_LIKELY_NULL(heap))
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
@ -976,7 +978,7 @@ page_delete_rec_list_end(
|
||||||
n_recs++;
|
n_recs++;
|
||||||
|
|
||||||
if (scrub)
|
if (scrub)
|
||||||
mtr->memset(block, page_offset(rec2), rec_offs_data_size(offsets), 0);
|
mtr->memset(block, rec2 - page, rec_offs_data_size(offsets), 0);
|
||||||
|
|
||||||
rec2= page_rec_get_next(rec2);
|
rec2= page_rec_get_next(rec2);
|
||||||
}
|
}
|
||||||
|
|
@ -1000,14 +1002,14 @@ page_delete_rec_list_end(
|
||||||
while (!(n_owned= rec_get_n_owned_new(owner_rec)))
|
while (!(n_owned= rec_get_n_owned_new(owner_rec)))
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
if (!(owner_rec= page_rec_get_next_low(owner_rec, true)))
|
if (!(owner_rec= page_rec_next_get<true>(page, owner_rec)))
|
||||||
return DB_CORRUPTION;
|
return DB_CORRUPTION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
while (!(n_owned= rec_get_n_owned_old(owner_rec)))
|
while (!(n_owned= rec_get_n_owned_old(owner_rec)))
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
if (!(owner_rec= page_rec_get_next_low(owner_rec, false)))
|
if (!(owner_rec= page_rec_next_get<false>(page, owner_rec)))
|
||||||
return DB_CORRUPTION;
|
return DB_CORRUPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1030,7 +1032,7 @@ page_delete_rec_list_end(
|
||||||
const uint16_t free= page_header_get_field(page, PAGE_FREE);
|
const uint16_t free= page_header_get_field(page, PAGE_FREE);
|
||||||
static_assert(PAGE_FREE + 2 == PAGE_GARBAGE, "compatibility");
|
static_assert(PAGE_FREE + 2 == PAGE_GARBAGE, "compatibility");
|
||||||
|
|
||||||
mach_write_to_2(page_header, page_offset(rec));
|
mach_write_to_2(page_header, rec - page);
|
||||||
mach_write_to_2(my_assume_aligned<2>(page_header + 2),
|
mach_write_to_2(my_assume_aligned<2>(page_header + 2),
|
||||||
mach_read_from_2(my_assume_aligned<2>(page_free + 2)) +
|
mach_read_from_2(my_assume_aligned<2>(page_free + 2)) +
|
||||||
size);
|
size);
|
||||||
|
|
@ -1060,19 +1062,17 @@ page_delete_rec_list_end(
|
||||||
PAGE_N_RECS + 2 - PAGE_N_DIR_SLOTS);
|
PAGE_N_RECS + 2 - PAGE_N_DIR_SLOTS);
|
||||||
// TODO: the equivalent of page_zip_dir_delete() for all records
|
// TODO: the equivalent of page_zip_dir_delete() for all records
|
||||||
mach_write_to_2(prev_rec - REC_NEXT, static_cast<uint16_t>
|
mach_write_to_2(prev_rec - REC_NEXT, static_cast<uint16_t>
|
||||||
(PAGE_NEW_SUPREMUM - page_offset(prev_rec)));
|
(PAGE_NEW_SUPREMUM - (prev_rec - page)));
|
||||||
mach_write_to_2(last_rec - REC_NEXT, free
|
mach_write_to_2(last_rec - REC_NEXT, free
|
||||||
? static_cast<uint16_t>(free - page_offset(last_rec))
|
? uint16_t(free - (last_rec - block->page.frame)) : 0U);
|
||||||
: 0U);
|
|
||||||
return DB_SUCCESS;
|
return DB_SUCCESS;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
mtr->write<1,mtr_t::MAYBE_NOP>(*block, owned, new_owned);
|
mtr->write<1,mtr_t::MAYBE_NOP>(*block, owned, new_owned);
|
||||||
mtr->write<2>(*block, prev_rec - REC_NEXT, static_cast<uint16_t>
|
mtr->write<2>(*block, prev_rec - REC_NEXT, static_cast<uint16_t>
|
||||||
(PAGE_NEW_SUPREMUM - page_offset(prev_rec)));
|
(PAGE_NEW_SUPREMUM - (prev_rec - block->page.frame)));
|
||||||
mtr->write<2>(*block, last_rec - REC_NEXT, free
|
mtr->write<2>(*block, last_rec - REC_NEXT, free
|
||||||
? static_cast<uint16_t>(free - page_offset(last_rec))
|
? uint16_t(free - (last_rec - block->page.frame)) : 0U);
|
||||||
: 0U);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1196,11 +1196,11 @@ page_rec_get_nth_const(
|
||||||
|
|
||||||
if (page_is_comp(page)) {
|
if (page_is_comp(page)) {
|
||||||
do {
|
do {
|
||||||
rec = page_rec_get_next_low(rec, TRUE);
|
rec = page_rec_next_get<true>(page, rec);
|
||||||
} while (rec && nth--);
|
} while (rec && nth--);
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
rec = page_rec_get_next_low(rec, FALSE);
|
rec = page_rec_next_get<false>(page, rec);
|
||||||
} while (rec && nth--);
|
} while (rec && nth--);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1300,7 +1300,7 @@ ulint page_rec_get_n_recs_before(const rec_t *rec)
|
||||||
if (page_is_comp(page))
|
if (page_is_comp(page))
|
||||||
{
|
{
|
||||||
for (; rec_get_n_owned_new(rec) == 0; n--)
|
for (; rec_get_n_owned_new(rec) == 0; n--)
|
||||||
if (UNIV_UNLIKELY(!(rec= page_rec_get_next_low(rec, true))))
|
if (UNIV_UNLIKELY(!(rec= page_rec_next_get<true>(page, rec))))
|
||||||
return ULINT_UNDEFINED;
|
return ULINT_UNDEFINED;
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|
@ -1318,7 +1318,7 @@ ulint page_rec_get_n_recs_before(const rec_t *rec)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (; rec_get_n_owned_old(rec) == 0; n--)
|
for (; rec_get_n_owned_old(rec) == 0; n--)
|
||||||
if (UNIV_UNLIKELY(!(rec= page_rec_get_next_low(rec, false))))
|
if (UNIV_UNLIKELY(!(rec= page_rec_next_get<false>(page, rec))))
|
||||||
return ULINT_UNDEFINED;
|
return ULINT_UNDEFINED;
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|
@ -1383,9 +1383,8 @@ page_dir_print(
|
||||||
fprintf(stderr, "--------------------------------\n"
|
fprintf(stderr, "--------------------------------\n"
|
||||||
"PAGE DIRECTORY\n"
|
"PAGE DIRECTORY\n"
|
||||||
"Page address %p\n"
|
"Page address %p\n"
|
||||||
"Directory stack top at offs: %lu; number of slots: %lu\n",
|
"Directory stack top at offs: %zu; number of slots: %zu\n",
|
||||||
page, (ulong) page_offset(page_dir_get_nth_slot(page, n - 1)),
|
page, page_dir_get_nth_slot(page, n - 1) - page, n);
|
||||||
(ulong) n);
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
slot = page_dir_get_nth_slot(page, i);
|
slot = page_dir_get_nth_slot(page, i);
|
||||||
if ((i == pr_n) && (i < n - pr_n)) {
|
if ((i == pr_n) && (i < n - pr_n)) {
|
||||||
|
|
@ -1393,17 +1392,16 @@ page_dir_print(
|
||||||
}
|
}
|
||||||
if ((i < pr_n) || (i >= n - pr_n)) {
|
if ((i < pr_n) || (i >= n - pr_n)) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Contents of slot: %lu: n_owned: %lu,"
|
"Contents of slot: %zu: n_owned: %zu,"
|
||||||
" rec offs: %lu\n",
|
" rec offs: %zu\n",
|
||||||
(ulong) i,
|
i,
|
||||||
(ulong) page_dir_slot_get_n_owned(slot),
|
page_dir_slot_get_n_owned(slot),
|
||||||
(ulong)
|
page_dir_slot_get_rec(slot) - page);
|
||||||
page_offset(page_dir_slot_get_rec(slot)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Total of %lu records\n"
|
fprintf(stderr, "Total of %zu records\n"
|
||||||
"--------------------------------\n",
|
"--------------------------------\n",
|
||||||
(ulong) (PAGE_HEAP_NO_USER_LOW + page_get_n_recs(page)));
|
PAGE_HEAP_NO_USER_LOW + page_get_n_recs(page));
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************//**
|
/***************************************************************//**
|
||||||
|
|
@ -1546,7 +1544,7 @@ page_rec_validate(
|
||||||
page_rec_check(rec);
|
page_rec_check(rec);
|
||||||
rec_validate(rec, offsets);
|
rec_validate(rec, offsets);
|
||||||
|
|
||||||
if (page_rec_is_comp(rec)) {
|
if (page_is_comp(page)) {
|
||||||
n_owned = rec_get_n_owned_new(rec);
|
n_owned = rec_get_n_owned_new(rec);
|
||||||
heap_no = rec_get_heap_no_new(rec);
|
heap_no = rec_get_heap_no_new(rec);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1555,13 +1553,13 @@ page_rec_validate(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(!(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED))) {
|
if (UNIV_UNLIKELY(!(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED))) {
|
||||||
ib::warn() << "Dir slot of rec " << page_offset(rec)
|
ib::warn() << "Dir slot of rec " << rec - page
|
||||||
<< ", n owned too big " << n_owned;
|
<< ", n owned too big " << n_owned;
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(!(heap_no < page_dir_get_n_heap(page)))) {
|
if (UNIV_UNLIKELY(!(heap_no < page_dir_get_n_heap(page)))) {
|
||||||
ib::warn() << "Heap no of rec " << page_offset(rec)
|
ib::warn() << "Heap no of rec " << rec - page
|
||||||
<< " too big " << heap_no << " "
|
<< " too big " << heap_no << " "
|
||||||
<< page_dir_get_n_heap(page);
|
<< page_dir_get_n_heap(page);
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
|
|
@ -1643,8 +1641,7 @@ page_simple_validate_old(
|
||||||
<< "Record heap and dir overlap on a page, heap top "
|
<< "Record heap and dir overlap on a page, heap top "
|
||||||
<< page_header_get_field(page, PAGE_HEAP_TOP)
|
<< page_header_get_field(page, PAGE_HEAP_TOP)
|
||||||
<< ", dir "
|
<< ", dir "
|
||||||
<< page_offset(page_dir_get_nth_slot(page,
|
<< page_dir_get_nth_slot(page, n_slots - 1) - page;
|
||||||
n_slots - 1));
|
|
||||||
|
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
@ -1721,7 +1718,7 @@ page_simple_validate_old(
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = page_rec_get_next_const(rec);
|
rec = page_rec_next_get<false>(page, rec);
|
||||||
own_count++;
|
own_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1841,9 +1838,9 @@ page_simple_validate_new(
|
||||||
|
|
||||||
ib::error() << "Record heap and dir overlap on a page,"
|
ib::error() << "Record heap and dir overlap on a page,"
|
||||||
" heap top "
|
" heap top "
|
||||||
<< page_header_get_field(page, PAGE_HEAP_TOP)
|
<< page_header_get_field(page, PAGE_HEAP_TOP)
|
||||||
<< ", dir " << page_offset(
|
<< ", dir "
|
||||||
page_dir_get_nth_slot(page, n_slots - 1));
|
<< page_dir_get_nth_slot(page, n_slots - 1) - page;
|
||||||
|
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
@ -1861,9 +1858,9 @@ page_simple_validate_new(
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (UNIV_UNLIKELY(rec < page + PAGE_NEW_INFIMUM
|
if (UNIV_UNLIKELY(rec < page + PAGE_NEW_INFIMUM
|
||||||
|| rec > rec_heap_top)) {
|
|| rec > rec_heap_top)) {
|
||||||
ib::error() << "Record " << page_offset(rec)
|
ib::error() << "Record " << rec - page
|
||||||
<< " is out of bounds: "
|
<< " is out of bounds: "
|
||||||
<< page_offset(rec_heap_top);
|
<< rec_heap_top - page;
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1875,7 +1872,7 @@ page_simple_validate_new(
|
||||||
ib::error() << "Wrong owned count "
|
ib::error() << "Wrong owned count "
|
||||||
<< rec_get_n_owned_new(rec) << ", "
|
<< rec_get_n_owned_new(rec) << ", "
|
||||||
<< own_count << ", rec "
|
<< own_count << ", rec "
|
||||||
<< page_offset(rec);
|
<< rec - page;
|
||||||
|
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
@ -1883,7 +1880,7 @@ page_simple_validate_new(
|
||||||
if (UNIV_UNLIKELY
|
if (UNIV_UNLIKELY
|
||||||
(page_dir_slot_get_rec(slot) != rec)) {
|
(page_dir_slot_get_rec(slot) != rec)) {
|
||||||
ib::error() << "Dir slot does not point"
|
ib::error() << "Dir slot does not point"
|
||||||
" to right rec " << page_offset(rec);
|
" to right rec " << rec - page;
|
||||||
|
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
@ -1907,7 +1904,7 @@ page_simple_validate_new(
|
||||||
|
|
||||||
ib::error() << "Next record offset nonsensical "
|
ib::error() << "Next record offset nonsensical "
|
||||||
<< rec_get_next_offs(rec, TRUE)
|
<< rec_get_next_offs(rec, TRUE)
|
||||||
<< " for rec " << page_offset(rec);
|
<< " for rec " << rec - page;
|
||||||
|
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
@ -1920,7 +1917,7 @@ page_simple_validate_new(
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = page_rec_get_next_const(rec);
|
rec = page_rec_next_get<true>(page, rec);
|
||||||
own_count++;
|
own_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1954,15 +1951,15 @@ page_simple_validate_new(
|
||||||
|| rec >= page + srv_page_size)) {
|
|| rec >= page + srv_page_size)) {
|
||||||
|
|
||||||
ib::error() << "Free list record has"
|
ib::error() << "Free list record has"
|
||||||
" a nonsensical offset " << page_offset(rec);
|
" a nonsensical offset " << rec - page;
|
||||||
|
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(rec > rec_heap_top)) {
|
if (UNIV_UNLIKELY(rec > rec_heap_top)) {
|
||||||
ib::error() << "Free list record " << page_offset(rec)
|
ib::error() << "Free list record " << rec - page
|
||||||
<< " is above rec heap top "
|
<< " is above rec heap top "
|
||||||
<< page_offset(rec_heap_top);
|
<< rec_heap_top - page;
|
||||||
|
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
@ -2272,7 +2269,7 @@ wrong_page_type:
|
||||||
#endif /* UNIV_GIS_DEBUG */
|
#endif /* UNIV_GIS_DEBUG */
|
||||||
}
|
}
|
||||||
|
|
||||||
offs = page_offset(rec_get_start(rec, offsets));
|
offs = rec_get_start(rec, offsets) - page;
|
||||||
i = rec_offs_size(offsets);
|
i = rec_offs_size(offsets);
|
||||||
if (UNIV_UNLIKELY(offs + i >= srv_page_size)) {
|
if (UNIV_UNLIKELY(offs + i >= srv_page_size)) {
|
||||||
ib::error() << "Record offset out of bounds: "
|
ib::error() << "Record offset out of bounds: "
|
||||||
|
|
@ -2402,7 +2399,7 @@ next_free:
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
offs = page_offset(rec_get_start(rec, offsets));
|
offs = rec_get_start(rec, offsets) - page;
|
||||||
i = rec_offs_size(offsets);
|
i = rec_offs_size(offsets);
|
||||||
if (UNIV_UNLIKELY(offs + i >= srv_page_size)) {
|
if (UNIV_UNLIKELY(offs + i >= srv_page_size)) {
|
||||||
ib::error() << "Free record offset out of bounds: "
|
ib::error() << "Free record offset out of bounds: "
|
||||||
|
|
@ -2501,7 +2498,7 @@ const rec_t *page_find_rec_max_not_deleted(const page_t *page)
|
||||||
if (!(rec[-REC_NEW_INFO_BITS] &
|
if (!(rec[-REC_NEW_INFO_BITS] &
|
||||||
(REC_INFO_DELETED_FLAG | REC_INFO_MIN_REC_FLAG)))
|
(REC_INFO_DELETED_FLAG | REC_INFO_MIN_REC_FLAG)))
|
||||||
prev_rec= rec;
|
prev_rec= rec;
|
||||||
if (!(rec= page_rec_get_next_low(rec, true)))
|
if (!(rec= page_rec_next_get<true>(page, rec)))
|
||||||
return page + PAGE_NEW_INFIMUM;
|
return page + PAGE_NEW_INFIMUM;
|
||||||
} while (rec != page + PAGE_NEW_SUPREMUM);
|
} while (rec != page + PAGE_NEW_SUPREMUM);
|
||||||
return prev_rec;
|
return prev_rec;
|
||||||
|
|
@ -2515,7 +2512,7 @@ const rec_t *page_find_rec_max_not_deleted(const page_t *page)
|
||||||
if (!(rec[-REC_OLD_INFO_BITS] &
|
if (!(rec[-REC_OLD_INFO_BITS] &
|
||||||
(REC_INFO_DELETED_FLAG | REC_INFO_MIN_REC_FLAG)))
|
(REC_INFO_DELETED_FLAG | REC_INFO_MIN_REC_FLAG)))
|
||||||
prev_rec= rec;
|
prev_rec= rec;
|
||||||
if (!(rec= page_rec_get_next_low(rec, false)))
|
if (!(rec= page_rec_next_get<false>(page, rec)))
|
||||||
return page + PAGE_OLD_INFIMUM;
|
return page + PAGE_OLD_INFIMUM;
|
||||||
} while (rec != page + PAGE_OLD_SUPREMUM);
|
} while (rec != page + PAGE_OLD_SUPREMUM);
|
||||||
return prev_rec;
|
return prev_rec;
|
||||||
|
|
|
||||||
|
|
@ -3405,17 +3405,16 @@ page_zip_validate_low(
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = page_rec_get_next_low(rec, TRUE);
|
rec = page_rec_next_get<true>(page, rec);
|
||||||
trec = page_rec_get_next_low(trec, TRUE);
|
trec = page_rec_next_get<true>(temp_page, trec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare the records. */
|
/* Compare the records. */
|
||||||
heap = NULL;
|
heap = NULL;
|
||||||
offsets = NULL;
|
offsets = NULL;
|
||||||
rec = page_rec_get_next_low(
|
rec = page_rec_next_get<true>(page, page + PAGE_NEW_INFIMUM);
|
||||||
page + PAGE_NEW_INFIMUM, TRUE);
|
trec = page_rec_next_get<true>(temp_page,
|
||||||
trec = page_rec_get_next_low(
|
temp_page + PAGE_NEW_INFIMUM);
|
||||||
temp_page + PAGE_NEW_INFIMUM, TRUE);
|
|
||||||
const ulint n_core = (index && page_is_leaf(page))
|
const ulint n_core = (index && page_is_leaf(page))
|
||||||
? index->n_fields : 0;
|
? index->n_fields : 0;
|
||||||
|
|
||||||
|
|
@ -3447,8 +3446,8 @@ page_zip_validate_low(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = page_rec_get_next_low(rec, TRUE);
|
rec = page_rec_next_get<true>(page, rec);
|
||||||
trec = page_rec_get_next_low(trec, TRUE);
|
trec = page_rec_next_get<true>(temp_page, trec);
|
||||||
} while (rec || trec);
|
} while (rec || trec);
|
||||||
|
|
||||||
if (heap) {
|
if (heap) {
|
||||||
|
|
|
||||||
|
|
@ -1635,7 +1635,7 @@ row_ins_check_foreign_constraint(
|
||||||
const rec_t* rec = btr_pcur_get_rec(&pcur);
|
const rec_t* rec = btr_pcur_get_rec(&pcur);
|
||||||
const buf_block_t* block = btr_pcur_get_block(&pcur);
|
const buf_block_t* block = btr_pcur_get_block(&pcur);
|
||||||
|
|
||||||
if (page_rec_is_infimum(rec)) {
|
if (page_rec_is_infimum_low(rec - block->page.frame)) {
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -1644,7 +1644,7 @@ row_ins_check_foreign_constraint(
|
||||||
check_index->n_core_fields,
|
check_index->n_core_fields,
|
||||||
ULINT_UNDEFINED, &heap);
|
ULINT_UNDEFINED, &heap);
|
||||||
|
|
||||||
if (page_rec_is_supremum(rec)) {
|
if (page_rec_is_supremum_low(rec - block->page.frame)) {
|
||||||
|
|
||||||
if (skip_gap_lock) {
|
if (skip_gap_lock) {
|
||||||
|
|
||||||
|
|
@ -2125,7 +2125,7 @@ row_ins_scan_sec_index_for_duplicate(
|
||||||
const buf_block_t* block = btr_pcur_get_block(&pcur);
|
const buf_block_t* block = btr_pcur_get_block(&pcur);
|
||||||
const ulint lock_type = LOCK_ORDINARY;
|
const ulint lock_type = LOCK_ORDINARY;
|
||||||
|
|
||||||
if (page_rec_is_infimum(rec)) {
|
if (page_rec_is_infimum_low(rec - block->page.frame)) {
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -2161,7 +2161,7 @@ row_ins_scan_sec_index_for_duplicate(
|
||||||
goto end_scan;
|
goto end_scan;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_rec_is_supremum(rec)) {
|
if (page_rec_is_supremum_low(rec - block->page.frame)) {
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -2276,7 +2276,8 @@ row_ins_duplicate_error_in_clust_online(
|
||||||
|
|
||||||
ut_ad(!cursor->index()->is_instant());
|
ut_ad(!cursor->index()->is_instant());
|
||||||
|
|
||||||
if (cursor->low_match >= n_uniq && !page_rec_is_infimum(rec)) {
|
if (cursor->low_match >= n_uniq
|
||||||
|
&& !page_rec_is_infimum_low(rec - btr_cur_get_page(cursor))) {
|
||||||
*offsets = rec_get_offsets(rec, cursor->index(), *offsets,
|
*offsets = rec_get_offsets(rec, cursor->index(), *offsets,
|
||||||
cursor->index()->n_fields,
|
cursor->index()->n_fields,
|
||||||
ULINT_UNDEFINED, heap);
|
ULINT_UNDEFINED, heap);
|
||||||
|
|
@ -2286,7 +2287,7 @@ row_ins_duplicate_error_in_clust_online(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(rec = page_rec_get_next_const(btr_cur_get_rec(cursor)))) {
|
if (!(rec = page_rec_get_next_const(rec))) {
|
||||||
return DB_CORRUPTION;
|
return DB_CORRUPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2346,7 +2347,7 @@ row_ins_duplicate_error_in_clust(
|
||||||
|
|
||||||
rec = btr_cur_get_rec(cursor);
|
rec = btr_cur_get_rec(cursor);
|
||||||
|
|
||||||
if (!page_rec_is_infimum(rec)) {
|
if (!page_rec_is_infimum_low(rec - btr_cur_get_page(cursor))) {
|
||||||
offsets = rec_get_offsets(rec, cursor->index(),
|
offsets = rec_get_offsets(rec, cursor->index(),
|
||||||
offsets,
|
offsets,
|
||||||
cursor->index()
|
cursor->index()
|
||||||
|
|
@ -2759,7 +2760,8 @@ skip_bulk_insert:
|
||||||
if (UNIV_UNLIKELY(entry->info_bits != 0)) {
|
if (UNIV_UNLIKELY(entry->info_bits != 0)) {
|
||||||
const rec_t* rec = btr_pcur_get_rec(&pcur);
|
const rec_t* rec = btr_pcur_get_rec(&pcur);
|
||||||
|
|
||||||
if (rec_get_info_bits(rec, page_rec_is_comp(rec))
|
if (rec_get_info_bits(rec,
|
||||||
|
page_is_comp(btr_pcur_get_page(&pcur)))
|
||||||
& REC_INFO_MIN_REC_FLAG) {
|
& REC_INFO_MIN_REC_FLAG) {
|
||||||
trx->error_info = index;
|
trx->error_info = index;
|
||||||
err = DB_DUPLICATE_KEY;
|
err = DB_DUPLICATE_KEY;
|
||||||
|
|
|
||||||
|
|
@ -1821,23 +1821,29 @@ err_exit:
|
||||||
trx->error_key_num = 0;
|
trx->error_key_num = 0;
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
} else {
|
} else {
|
||||||
rec_t* rec = page_rec_get_next(btr_pcur_get_rec(&pcur));
|
const page_t* const page = btr_pcur_get_page(&pcur);
|
||||||
|
const auto comp = page_is_comp(page);
|
||||||
|
const rec_t* const rec = comp
|
||||||
|
? page_rec_next_get<true>(page,
|
||||||
|
btr_pcur_get_rec(&pcur))
|
||||||
|
: page_rec_next_get<false>(page,
|
||||||
|
btr_pcur_get_rec(&pcur));
|
||||||
if (!rec) {
|
if (!rec) {
|
||||||
corrupted_metadata:
|
corrupted_metadata:
|
||||||
err = DB_CORRUPTION;
|
err = DB_CORRUPTION;
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
}
|
}
|
||||||
if (rec_get_info_bits(rec, page_rec_is_comp(rec))
|
if (rec_get_info_bits(rec, comp) & REC_INFO_MIN_REC_FLAG) {
|
||||||
& REC_INFO_MIN_REC_FLAG) {
|
|
||||||
if (!clust_index->is_instant()) {
|
if (!clust_index->is_instant()) {
|
||||||
goto corrupted_metadata;
|
goto corrupted_metadata;
|
||||||
}
|
}
|
||||||
if (page_rec_is_comp(rec)
|
if (comp
|
||||||
&& rec_get_status(rec) != REC_STATUS_INSTANT) {
|
&& rec_get_status(rec) != REC_STATUS_INSTANT) {
|
||||||
goto corrupted_metadata;
|
goto corrupted_metadata;
|
||||||
}
|
}
|
||||||
/* Skip the metadata pseudo-record. */
|
/* Skip the metadata pseudo-record. */
|
||||||
btr_pcur_get_page_cur(&pcur)->rec = rec;
|
btr_pcur_get_page_cur(&pcur)->rec =
|
||||||
|
const_cast<rec_t*>(rec);
|
||||||
} else if (clust_index->is_instant()) {
|
} else if (clust_index->is_instant()) {
|
||||||
goto corrupted_metadata;
|
goto corrupted_metadata;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1811,7 +1811,7 @@ row_unlock_for_mysql(
|
||||||
|
|
||||||
lock_rec_unlock(
|
lock_rec_unlock(
|
||||||
trx,
|
trx,
|
||||||
btr_pcur_get_block(pcur)->page.id(),
|
*btr_pcur_get_block(pcur),
|
||||||
rec,
|
rec,
|
||||||
static_cast<enum lock_mode>(
|
static_cast<enum lock_mode>(
|
||||||
prebuilt->select_lock_type));
|
prebuilt->select_lock_type));
|
||||||
|
|
|
||||||
|
|
@ -1098,7 +1098,7 @@ static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr)
|
||||||
byte* ptr = rec_get_nth_field(
|
byte* ptr = rec_get_nth_field(
|
||||||
rec, offsets, trx_id_pos, &len);
|
rec, offsets, trx_id_pos, &len);
|
||||||
ut_ad(len == DATA_TRX_ID_LEN);
|
ut_ad(len == DATA_TRX_ID_LEN);
|
||||||
size_t offs = page_offset(ptr);
|
size_t offs = ptr - block->page.frame;
|
||||||
mtr->memset(block, offs, DATA_TRX_ID_LEN, 0);
|
mtr->memset(block, offs, DATA_TRX_ID_LEN, 0);
|
||||||
offs += DATA_TRX_ID_LEN;
|
offs += DATA_TRX_ID_LEN;
|
||||||
mtr->write<1,mtr_t::MAYBE_NOP>(
|
mtr->write<1,mtr_t::MAYBE_NOP>(
|
||||||
|
|
|
||||||
|
|
@ -1620,7 +1620,8 @@ row_sel_try_search_shortcut(
|
||||||
return SEL_RETRY;
|
return SEL_RETRY;
|
||||||
}
|
}
|
||||||
} else if (!srv_read_only_mode) {
|
} else if (!srv_read_only_mode) {
|
||||||
trx_id_t trx_id = page_get_max_trx_id(page_align(rec));
|
trx_id_t trx_id =
|
||||||
|
page_get_max_trx_id(btr_pcur_get_page(&plan->pcur));
|
||||||
ut_ad(trx_id);
|
ut_ad(trx_id);
|
||||||
if (!node->read_view->sees(trx_id)) {
|
if (!node->read_view->sees(trx_id)) {
|
||||||
return SEL_RETRY;
|
return SEL_RETRY;
|
||||||
|
|
@ -2041,7 +2042,8 @@ skip_lock:
|
||||||
rec = old_vers;
|
rec = old_vers;
|
||||||
}
|
}
|
||||||
} else if (!srv_read_only_mode) {
|
} else if (!srv_read_only_mode) {
|
||||||
trx_id_t trx_id = page_get_max_trx_id(page_align(rec));
|
trx_id_t trx_id = page_get_max_trx_id(
|
||||||
|
btr_pcur_get_page(&plan->pcur));
|
||||||
ut_ad(trx_id);
|
ut_ad(trx_id);
|
||||||
if (!node->read_view->sees(trx_id)) {
|
if (!node->read_view->sees(trx_id)) {
|
||||||
cons_read_requires_clust_rec = TRUE;
|
cons_read_requires_clust_rec = TRUE;
|
||||||
|
|
@ -3411,8 +3413,9 @@ Row_sel_get_clust_rec_for_mysql::operator()(
|
||||||
page and verify that */
|
page and verify that */
|
||||||
if (dict_index_is_spatial(sec_index)
|
if (dict_index_is_spatial(sec_index)
|
||||||
&& btr_cur->rtr_info->matches
|
&& btr_cur->rtr_info->matches
|
||||||
&& (page_align(rec)
|
&& (!(ulint(rec
|
||||||
== btr_cur->rtr_info->matches->block->page.frame
|
- btr_cur->rtr_info->matches->block->page.frame)
|
||||||
|
>> srv_page_size_shift)
|
||||||
|| rec != btr_pcur_get_rec(prebuilt->pcur))) {
|
|| rec != btr_pcur_get_rec(prebuilt->pcur))) {
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
rtr_info_t* rtr_info = btr_cur->rtr_info;
|
rtr_info_t* rtr_info = btr_cur->rtr_info;
|
||||||
|
|
@ -3539,7 +3542,7 @@ Row_sel_get_clust_rec_for_mysql::operator()(
|
||||||
prebuilt->clust_pcur)->page;
|
prebuilt->clust_pcur)->page;
|
||||||
|
|
||||||
const lsn_t lsn = mach_read_from_8(
|
const lsn_t lsn = mach_read_from_8(
|
||||||
page_align(clust_rec) + FIL_PAGE_LSN);
|
bpage.frame + FIL_PAGE_LSN);
|
||||||
|
|
||||||
if (lsn != cached_lsn
|
if (lsn != cached_lsn
|
||||||
|| bpage.id() != cached_page_id
|
|| bpage.id() != cached_page_id
|
||||||
|
|
@ -5008,7 +5011,8 @@ wrong_offs:
|
||||||
.buf_fix_count();
|
.buf_fix_count();
|
||||||
|
|
||||||
ib::error() << "Index corruption: rec offs "
|
ib::error() << "Index corruption: rec offs "
|
||||||
<< page_offset(rec) << " next offs "
|
<< rec - btr_pcur_get_page(pcur)
|
||||||
|
<< " next offs "
|
||||||
<< next_offs
|
<< next_offs
|
||||||
<< btr_pcur_get_block(pcur)->page.id()
|
<< btr_pcur_get_block(pcur)->page.id()
|
||||||
<< ", index " << index->name
|
<< ", index " << index->name
|
||||||
|
|
@ -5025,7 +5029,8 @@ wrong_offs:
|
||||||
over the corruption to recover as much as possible. */
|
over the corruption to recover as much as possible. */
|
||||||
|
|
||||||
ib::info() << "Index corruption: rec offs "
|
ib::info() << "Index corruption: rec offs "
|
||||||
<< page_offset(rec) << " next offs "
|
<< rec - btr_pcur_get_page(pcur)
|
||||||
|
<< " next offs "
|
||||||
<< next_offs
|
<< next_offs
|
||||||
<< btr_pcur_get_block(pcur)->page.id()
|
<< btr_pcur_get_block(pcur)->page.id()
|
||||||
<< ", index " << index->name
|
<< ", index " << index->name
|
||||||
|
|
@ -5050,10 +5055,12 @@ wrong_offs:
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
|
if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
|
||||||
if (!rec_validate(rec, offsets)
|
if (!rec_validate(rec, offsets)
|
||||||
|| !btr_index_rec_validate(rec, index, FALSE)) {
|
|| !btr_index_rec_validate(pcur->btr_cur.page_cur,
|
||||||
|
index, FALSE)) {
|
||||||
|
|
||||||
ib::error() << "Index corruption: rec offs "
|
ib::error() << "Index corruption: rec offs "
|
||||||
<< page_offset(rec) << " next offs "
|
<< rec - btr_pcur_get_page(pcur)
|
||||||
|
<< " next offs "
|
||||||
<< next_offs
|
<< next_offs
|
||||||
<< btr_pcur_get_block(pcur)->page.id()
|
<< btr_pcur_get_block(pcur)->page.id()
|
||||||
<< ", index " << index->name
|
<< ", index " << index->name
|
||||||
|
|
@ -5416,7 +5423,7 @@ no_gap_lock:
|
||||||
|
|
||||||
if (!srv_read_only_mode) {
|
if (!srv_read_only_mode) {
|
||||||
trx_id_t trx_id = page_get_max_trx_id(
|
trx_id_t trx_id = page_get_max_trx_id(
|
||||||
page_align(rec));
|
btr_pcur_get_page(pcur));
|
||||||
ut_ad(trx_id);
|
ut_ad(trx_id);
|
||||||
if (trx->read_view.sees(trx_id)) {
|
if (trx->read_view.sees(trx_id)) {
|
||||||
goto locks_ok;
|
goto locks_ok;
|
||||||
|
|
@ -6399,7 +6406,8 @@ rec_loop:
|
||||||
|
|
||||||
goto count_or_not;
|
goto count_or_not;
|
||||||
}
|
}
|
||||||
else if (const trx_id_t page_trx_id= page_get_max_trx_id(page_align(rec)))
|
else if (const trx_id_t page_trx_id=
|
||||||
|
page_get_max_trx_id(btr_pcur_get_page(prebuilt->pcur)))
|
||||||
{
|
{
|
||||||
if (page_trx_id >= trx_sys.get_max_trx_id())
|
if (page_trx_id >= trx_sys.get_max_trx_id())
|
||||||
goto invalid_PAGE_MAX_TRX_ID;
|
goto invalid_PAGE_MAX_TRX_ID;
|
||||||
|
|
|
||||||
|
|
@ -445,7 +445,8 @@ row_undo_mod_clust(
|
||||||
0, 1ULL << ROLL_PTR_INSERT_FLAG_POS,
|
0, 1ULL << ROLL_PTR_INSERT_FLAG_POS,
|
||||||
&mtr);
|
&mtr);
|
||||||
} else {
|
} else {
|
||||||
size_t offs = page_offset(rec + trx_id_offset);
|
size_t offs = rec + trx_id_offset
|
||||||
|
- block->page.frame;
|
||||||
mtr.memset(block, offs, DATA_TRX_ID_LEN, 0);
|
mtr.memset(block, offs, DATA_TRX_ID_LEN, 0);
|
||||||
offs += DATA_TRX_ID_LEN;
|
offs += DATA_TRX_ID_LEN;
|
||||||
mtr.write<1,mtr_t::MAYBE_NOP>(*block,
|
mtr.write<1,mtr_t::MAYBE_NOP>(*block,
|
||||||
|
|
@ -489,15 +490,14 @@ static bool row_undo_mod_sec_is_unsafe(const rec_t *rec, dict_index_t *index,
|
||||||
mem_heap_t* heap2;
|
mem_heap_t* heap2;
|
||||||
dtuple_t* row;
|
dtuple_t* row;
|
||||||
const dtuple_t* entry;
|
const dtuple_t* entry;
|
||||||
ulint comp;
|
|
||||||
dtuple_t* vrow = NULL;
|
dtuple_t* vrow = NULL;
|
||||||
mem_heap_t* v_heap = NULL;
|
mem_heap_t* v_heap = NULL;
|
||||||
dtuple_t* cur_vrow = NULL;
|
dtuple_t* cur_vrow = NULL;
|
||||||
|
|
||||||
|
const bool comp = index->table->not_redundant();
|
||||||
clust_index = dict_table_get_first_index(index->table);
|
clust_index = dict_table_get_first_index(index->table);
|
||||||
|
|
||||||
comp = page_rec_is_comp(rec);
|
ut_ad(!!page_rec_is_comp(rec) == comp);
|
||||||
ut_ad(!dict_table_is_comp(index->table) == !comp);
|
|
||||||
heap = mem_heap_create(1024);
|
heap = mem_heap_create(1024);
|
||||||
clust_offsets = rec_get_offsets(rec, clust_index, NULL,
|
clust_offsets = rec_get_offsets(rec, clust_index, NULL,
|
||||||
clust_index->n_core_fields,
|
clust_index->n_core_fields,
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,9 @@ static buf_block_t* row_undo_rec_get(undo_node_t* node)
|
||||||
}
|
}
|
||||||
|
|
||||||
undo->top_page_no = prev_page->page.id().page_no();
|
undo->top_page_no = prev_page->page.id().page_no();
|
||||||
undo->top_offset = page_offset(prev_rec);
|
undo->top_offset = uint16_t(prev_rec - prev_page->page.frame);
|
||||||
|
ut_ad(prev_rec - prev_page->page.frame
|
||||||
|
== page_offset(prev_rec));
|
||||||
undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec);
|
undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec);
|
||||||
ut_ad(!undo->empty());
|
ut_ad(!undo->empty());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -149,9 +149,9 @@ row_vers_impl_x_locked_low(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ulint comp = page_rec_is_comp(rec);
|
const bool comp = index->table->not_redundant();
|
||||||
|
ut_ad(!!page_rec_is_comp(rec) == comp);
|
||||||
ut_ad(index->table == clust_index->table);
|
ut_ad(index->table == clust_index->table);
|
||||||
ut_ad(!!comp == dict_table_is_comp(index->table));
|
|
||||||
ut_ad(!comp == !page_rec_is_comp(clust_rec));
|
ut_ad(!comp == !page_rec_is_comp(clust_rec));
|
||||||
|
|
||||||
const ulint rec_del = rec_get_deleted_flag(rec, comp);
|
const ulint rec_del = rec_get_deleted_flag(rec, comp);
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,8 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
|
||||||
/* This function is invoked during transaction commit, which is not
|
/* This function is invoked during transaction commit, which is not
|
||||||
allowed to fail. If we get a corrupted undo header, we will crash here. */
|
allowed to fail. If we get a corrupted undo header, we will crash here. */
|
||||||
ut_a(undo_page);
|
ut_a(undo_page);
|
||||||
trx_ulogf_t *undo_header= undo_page->page.frame + undo->hdr_offset;
|
const uint16_t undo_header_offset= undo->hdr_offset;
|
||||||
|
trx_ulogf_t *undo_header= undo_page->page.frame + undo_header_offset;
|
||||||
|
|
||||||
ut_ad(mach_read_from_2(undo_header + TRX_UNDO_NEEDS_PURGE) <= 1);
|
ut_ad(mach_read_from_2(undo_header + TRX_UNDO_NEEDS_PURGE) <= 1);
|
||||||
ut_ad(rseg->needs_purge > trx->id);
|
ut_ad(rseg->needs_purge > trx->id);
|
||||||
|
|
@ -265,9 +266,8 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
|
||||||
than to intentionally violate ACID by committing something
|
than to intentionally violate ACID by committing something
|
||||||
that is known to be corrupted. */
|
that is known to be corrupted. */
|
||||||
ut_a(flst_add_first(rseg_header, TRX_RSEG + TRX_RSEG_HISTORY, undo_page,
|
ut_a(flst_add_first(rseg_header, TRX_RSEG + TRX_RSEG_HISTORY, undo_page,
|
||||||
uint16_t(page_offset(undo_header) +
|
uint16_t(undo_header_offset + TRX_UNDO_HISTORY_NODE),
|
||||||
TRX_UNDO_HISTORY_NODE), rseg->space->free_limit,
|
rseg->space->free_limit, mtr) == DB_SUCCESS);
|
||||||
mtr) == DB_SUCCESS);
|
|
||||||
|
|
||||||
mtr->write<2>(*undo_page, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE +
|
mtr->write<2>(*undo_page, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE +
|
||||||
undo_page->page.frame, undo_state);
|
undo_page->page.frame, undo_state);
|
||||||
|
|
@ -287,8 +287,9 @@ static void trx_purge_free_segment(buf_block_t *rseg_hdr, buf_block_t *block,
|
||||||
ut_ad(mtr.memo_contains_flagged(rseg_hdr, MTR_MEMO_PAGE_X_FIX));
|
ut_ad(mtr.memo_contains_flagged(rseg_hdr, MTR_MEMO_PAGE_X_FIX));
|
||||||
ut_ad(mtr.memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
|
ut_ad(mtr.memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
|
||||||
|
|
||||||
while (!fseg_free_step_not_header(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER +
|
while (!fseg_free_step_not_header(block,
|
||||||
block->page.frame, &mtr))
|
TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER,
|
||||||
|
&mtr))
|
||||||
{
|
{
|
||||||
rseg_hdr->fix();
|
rseg_hdr->fix();
|
||||||
block->fix();
|
block->fix();
|
||||||
|
|
@ -311,8 +312,8 @@ static void trx_purge_free_segment(buf_block_t *rseg_hdr, buf_block_t *block,
|
||||||
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
|
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER +
|
while (!fseg_free_step(block, TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER,
|
||||||
block->page.frame, &mtr));
|
&mtr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void purge_sys_t::rseg_enable(trx_rseg_t &rseg)
|
void purge_sys_t::rseg_enable(trx_rseg_t &rseg)
|
||||||
|
|
@ -926,7 +927,8 @@ bool purge_sys_t::choose_next_log()
|
||||||
goto purge_nothing;
|
goto purge_nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset= page_offset(undo_rec);
|
offset= uint16_t(undo_rec - b->page.frame);
|
||||||
|
ut_ad(undo_rec - b->page.frame == page_offset(undo_rec));
|
||||||
tail.undo_no= trx_undo_rec_get_undo_no(undo_rec);
|
tail.undo_no= trx_undo_rec_get_undo_no(undo_rec);
|
||||||
page_no= id.page_no();
|
page_no= id.page_no();
|
||||||
}
|
}
|
||||||
|
|
@ -968,12 +970,14 @@ inline trx_purge_rec_t purge_sys_t::get_next_rec(roll_ptr_t roll_ptr)
|
||||||
return {nullptr, 0};
|
return {nullptr, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf_block_t *rec2_page= b;
|
||||||
if (const trx_undo_rec_t *rec2=
|
if (const trx_undo_rec_t *rec2=
|
||||||
trx_undo_page_get_next_rec(b, offset, hdr_page_no, hdr_offset))
|
trx_undo_page_get_next_rec(b, offset, hdr_page_no, hdr_offset))
|
||||||
{
|
{
|
||||||
got_rec:
|
got_rec:
|
||||||
ut_ad(page_no == page_id.page_no());
|
ut_ad(page_no == page_id.page_no());
|
||||||
offset= page_offset(rec2);
|
ut_ad(page_offset(rec2) == rec2 - rec2_page->page.frame);
|
||||||
|
offset= uint16_t(rec2 - rec2_page->page.frame);
|
||||||
tail.undo_no= trx_undo_rec_get_undo_no(rec2);
|
tail.undo_no= trx_undo_rec_get_undo_no(rec2);
|
||||||
}
|
}
|
||||||
else if (hdr_page_no != page_no ||
|
else if (hdr_page_no != page_no ||
|
||||||
|
|
@ -989,6 +993,7 @@ inline trx_purge_rec_t purge_sys_t::get_next_rec(roll_ptr_t roll_ptr)
|
||||||
rec2= trx_undo_page_get_first_rec(next_page, hdr_page_no, hdr_offset);
|
rec2= trx_undo_page_get_first_rec(next_page, hdr_page_no, hdr_offset);
|
||||||
if (rec2)
|
if (rec2)
|
||||||
{
|
{
|
||||||
|
rec2_page= next_page;
|
||||||
page_no= next;
|
page_no= next;
|
||||||
goto got_rec;
|
goto got_rec;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -588,9 +588,8 @@ static dberr_t trx_resurrect_table_locks(trx_t *trx, const trx_undo_t &undo)
|
||||||
{
|
{
|
||||||
buf_page_make_young_if_needed(&block->page);
|
buf_page_make_young_if_needed(&block->page);
|
||||||
buf_block_t *undo_block= block;
|
buf_block_t *undo_block= block;
|
||||||
const trx_undo_rec_t *undo_rec= block->page.frame + undo.top_offset;
|
uint16_t undo_rec_offset= undo.top_offset;
|
||||||
|
for (const trx_undo_rec_t *undo_rec= block->page.frame + undo_rec_offset;;)
|
||||||
do
|
|
||||||
{
|
{
|
||||||
byte type;
|
byte type;
|
||||||
byte cmpl_info;
|
byte cmpl_info;
|
||||||
|
|
@ -606,11 +605,14 @@ static dberr_t trx_resurrect_table_locks(trx_t *trx, const trx_undo_t &undo)
|
||||||
trx_undo_rec_get_pars(undo_rec, &type, &cmpl_info,
|
trx_undo_rec_get_pars(undo_rec, &type, &cmpl_info,
|
||||||
&updated_extern, &undo_no, &table_id);
|
&updated_extern, &undo_no, &table_id);
|
||||||
tables.emplace(table_id, type == TRX_UNDO_EMPTY);
|
tables.emplace(table_id, type == TRX_UNDO_EMPTY);
|
||||||
undo_rec= trx_undo_get_prev_rec(block, page_offset(undo_rec),
|
ut_ad(page_offset(undo_rec) == undo_rec_offset);
|
||||||
|
undo_rec= trx_undo_get_prev_rec(block, undo_rec_offset,
|
||||||
undo.hdr_page_no, undo.hdr_offset,
|
undo.hdr_page_no, undo.hdr_offset,
|
||||||
true, &mtr);
|
true, &mtr);
|
||||||
|
if (!undo_rec)
|
||||||
|
break;
|
||||||
|
undo_rec_offset= uint16_t(undo_rec - block->page.frame);
|
||||||
}
|
}
|
||||||
while (undo_rec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mtr.commit();
|
mtr.commit();
|
||||||
|
|
@ -1050,13 +1052,13 @@ void trx_t::commit_empty(mtr_t *mtr)
|
||||||
{
|
{
|
||||||
mtr->memcpy(*u, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_START +
|
mtr->memcpy(*u, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_START +
|
||||||
u->page.frame, prev + TRX_UNDO_LOG_START, 2);
|
u->page.frame, prev + TRX_UNDO_LOG_START, 2);
|
||||||
const ulint free= page_offset(last);
|
const ulint free= last - u->page.frame;
|
||||||
mtr->write<2>(*u, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE +
|
mtr->write<2>(*u, TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE +
|
||||||
u->page.frame, free);
|
u->page.frame, free);
|
||||||
mtr->write<2>(*u, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + u->page.frame,
|
mtr->write<2>(*u, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + u->page.frame,
|
||||||
TRX_UNDO_CACHED);
|
TRX_UNDO_CACHED);
|
||||||
mtr->write<2>(*u, TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG + u->page.frame,
|
mtr->write<2>(*u, TRX_UNDO_SEG_HDR + TRX_UNDO_LAST_LOG + u->page.frame,
|
||||||
page_offset(prev));
|
uintptr_t(prev - u->page.frame));
|
||||||
mtr->write<2>(*u, prev + TRX_UNDO_NEXT_LOG, 0U);
|
mtr->write<2>(*u, prev + TRX_UNDO_NEXT_LOG, 0U);
|
||||||
mtr->memset(u, free, srv_page_size - FIL_PAGE_DATA_END - free, 0);
|
mtr->memset(u, free, srv_page_size - FIL_PAGE_DATA_END - free, 0);
|
||||||
|
|
||||||
|
|
@ -1352,10 +1354,8 @@ ATTRIBUTE_NOINLINE static void trx_commit_cleanup(trx_undo_t *&undo)
|
||||||
buf_page_get(page_id_t(SRV_TMP_SPACE_ID, undo->hdr_page_no), 0,
|
buf_page_get(page_id_t(SRV_TMP_SPACE_ID, undo->hdr_page_no), 0,
|
||||||
RW_X_LATCH, &mtr))
|
RW_X_LATCH, &mtr))
|
||||||
{
|
{
|
||||||
fseg_header_t *file_seg= TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER +
|
finished= fseg_free_step(block, TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER,
|
||||||
block->page.frame;
|
&mtr);
|
||||||
|
|
||||||
finished= fseg_free_step(file_seg, &mtr);
|
|
||||||
|
|
||||||
if (!finished);
|
if (!finished);
|
||||||
else if (buf_block_t *rseg_header= rseg->get(&mtr, nullptr))
|
else if (buf_block_t *rseg_header= rseg->get(&mtr, nullptr))
|
||||||
|
|
|
||||||
|
|
@ -292,12 +292,12 @@ trx_undo_get_first_rec(const fil_space_t &space, uint32_t page_no,
|
||||||
mtr);
|
mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void UndorecApplier::apply_undo_rec(const trx_undo_rec_t *rec)
|
inline
|
||||||
|
void UndorecApplier::apply_undo_rec(const trx_undo_rec_t *rec, uint16_t offset)
|
||||||
{
|
{
|
||||||
undo_rec= rec;
|
undo_rec= rec;
|
||||||
if (!undo_rec)
|
ut_ad(page_offset(undo_rec) == offset);
|
||||||
return;
|
this->offset= offset;
|
||||||
offset= page_offset(undo_rec);
|
|
||||||
|
|
||||||
bool updated_extern= false;
|
bool updated_extern= false;
|
||||||
undo_no_t undo_no= 0;
|
undo_no_t undo_no= 0;
|
||||||
|
|
@ -365,10 +365,11 @@ ATTRIBUTE_COLD void trx_t::apply_log()
|
||||||
undo->hdr_offset);
|
undo->hdr_offset);
|
||||||
while (rec)
|
while (rec)
|
||||||
{
|
{
|
||||||
|
const uint16_t offset= uint16_t(rec - block->page.frame);
|
||||||
/* Since we are the only thread who could write to this undo page,
|
/* Since we are the only thread who could write to this undo page,
|
||||||
it is safe to dereference rec while only holding a buffer-fix. */
|
it is safe to dereference rec while only holding a buffer-fix. */
|
||||||
log_applier.apply_undo_rec(rec);
|
log_applier.apply_undo_rec(rec, offset);
|
||||||
rec= trx_undo_page_get_next_rec(block, page_offset(rec),
|
rec= trx_undo_page_get_next_rec(block, offset,
|
||||||
page_id.page_no(), undo->hdr_offset);
|
page_id.page_no(), undo->hdr_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue