Skip to content

Commit 73aa31f

Browse files
committed
Merge 10.2 into 10.3
2 parents 8a09440 + 147d4b1 commit 73aa31f

File tree

7 files changed

+91
-62
lines changed

7 files changed

+91
-62
lines changed

storage/innobase/btr/btr0bulk.cc

Lines changed: 80 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 2014, 2019, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2017, 2019, MariaDB Corporation.
4+
Copyright (c) 2017, 2020, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -29,6 +29,7 @@ Created 03/11/2014 Shaohua Wang
2929
#include "btr0cur.h"
3030
#include "btr0pcur.h"
3131
#include "ibuf0ibuf.h"
32+
#include "page0page.h"
3233
#include "trx0trx.h"
3334

3435
/** Innodb B-tree index fill factor for bulk load. */
@@ -140,7 +141,6 @@ PageBulk::init()
140141
}
141142

142143
m_block = new_block;
143-
m_block->skip_flush_check = true;
144144
m_page = new_page;
145145
m_page_zip = new_page_zip;
146146
m_page_no = new_page_no;
@@ -160,7 +160,11 @@ PageBulk::init()
160160
srv_page_size - dict_index_zip_pad_optimal_page_size(m_index);
161161
m_heap_top = page_header_get_ptr(new_page, PAGE_HEAP_TOP);
162162
m_rec_no = page_header_get_field(new_page, PAGE_N_RECS);
163-
163+
/* Temporarily reset PAGE_DIRECTION_B from PAGE_NO_DIRECTION to 0,
164+
without writing redo log, to ensure that needs_finish() will hold
165+
on an empty page. */
166+
ut_ad(m_page[PAGE_HEADER + PAGE_DIRECTION_B] == PAGE_NO_DIRECTION);
167+
m_page[PAGE_HEADER + PAGE_DIRECTION_B] = 0;
164168
ut_d(m_total_data = 0);
165169
/* See page_copy_rec_list_end_to_created_page() */
166170
ut_d(page_header_set_field(m_page, NULL, PAGE_HEAP_TOP,
@@ -186,7 +190,7 @@ PageBulk::insert(
186190

187191
#ifdef UNIV_DEBUG
188192
/* Check whether records are in order. */
189-
if (!page_rec_is_infimum(m_cur_rec)) {
193+
if (!page_rec_is_infimum_low(page_offset(m_cur_rec))) {
190194
rec_t* old_rec = m_cur_rec;
191195
rec_offs* old_offsets = rec_get_offsets(
192196
old_rec, m_index, NULL, is_leaf,
@@ -204,18 +208,21 @@ PageBulk::insert(
204208
rec_offs_make_valid(insert_rec, m_index, is_leaf, offsets);
205209

206210
/* 2. Insert the record in the linked list. */
207-
rec_t* next_rec = page_rec_get_next(m_cur_rec);
208-
209-
page_rec_set_next(insert_rec, next_rec);
210-
page_rec_set_next(m_cur_rec, insert_rec);
211-
212211
/* 3. Set the n_owned field in the inserted record to zero,
213212
and set the heap_no field. */
214213
if (m_is_comp) {
214+
ulint next_offs = rec_get_next_offs(m_cur_rec, TRUE);
215+
rec_set_next_offs_new(insert_rec, next_offs);
216+
rec_set_next_offs_new(m_cur_rec, page_offset(insert_rec));
217+
215218
rec_set_n_owned_new(insert_rec, NULL, 0);
216219
rec_set_heap_no_new(insert_rec,
217220
PAGE_HEAP_NO_USER_LOW + m_rec_no);
218221
} else {
222+
ulint next_offs = rec_get_next_offs(m_cur_rec, FALSE);
223+
rec_set_next_offs_old(insert_rec, next_offs);
224+
rec_set_next_offs_old(m_cur_rec, page_offset(insert_rec));
225+
219226
rec_set_n_owned_old(insert_rec, 0);
220227
rec_set_heap_no_old(insert_rec,
221228
PAGE_HEAP_NO_USER_LOW + m_rec_no);
@@ -243,17 +250,54 @@ PageBulk::insert(
243250
m_cur_rec = insert_rec;
244251
}
245252

253+
inline bool PageBulk::needs_finish() const
254+
{
255+
ut_ad(page_align(m_cur_rec) == m_block->frame);
256+
ut_ad(m_page == m_block->frame);
257+
if (!m_page[PAGE_HEADER + PAGE_DIRECTION_B])
258+
return true;
259+
ulint heap_no, n_heap= page_header_get_field(m_page, PAGE_N_HEAP);
260+
ut_ad((n_heap & 0x7fff) >= PAGE_HEAP_NO_USER_LOW);
261+
if (n_heap & 0x8000)
262+
{
263+
n_heap&= 0x7fff;
264+
heap_no= rec_get_heap_no_new(m_cur_rec);
265+
if (heap_no == PAGE_HEAP_NO_INFIMUM &&
266+
page_header_get_field(m_page, PAGE_HEAP_TOP) == PAGE_NEW_SUPREMUM_END)
267+
return false;
268+
}
269+
else
270+
{
271+
heap_no= rec_get_heap_no_old(m_cur_rec);
272+
if (heap_no == PAGE_HEAP_NO_INFIMUM &&
273+
page_header_get_field(m_page, PAGE_HEAP_TOP) == PAGE_OLD_SUPREMUM_END)
274+
return false;
275+
}
276+
return heap_no != n_heap - 1;
277+
}
278+
246279
/** Mark end of insertion to the page. Scan all records to set page dirs,
247280
and set page header members.
248281
Note: we refer to page_copy_rec_list_end_to_created_page. */
249282
void
250283
PageBulk::finish()
251284
{
252-
ut_ad(m_rec_no > 0);
285+
ut_ad(!dict_index_is_spatial(m_index));
286+
287+
if (!needs_finish()) {
288+
return;
289+
}
290+
253291
ut_ad(m_total_data + page_dir_calc_reserved_space(m_rec_no)
254292
<= page_get_free_space_of_empty(m_is_comp));
293+
#ifdef UNIV_DEBUG
255294
/* See page_copy_rec_list_end_to_created_page() */
256-
ut_d(page_dir_set_n_slots(m_page, NULL, srv_page_size / 2));
295+
if (m_rec_no) {
296+
page_dir_set_n_slots(m_page, NULL, srv_page_size / 2);
297+
}
298+
mach_write_to_2(PAGE_HEADER + PAGE_HEAP_TOP + m_page,
299+
ulint(m_heap_top - m_page));
300+
#endif
257301

258302
ulint count = 0;
259303
ulint n_recs = 0;
@@ -262,8 +306,7 @@ PageBulk::finish()
262306
page_dir_slot_t* slot = NULL;
263307

264308
/* Set owner & dir. */
265-
do {
266-
309+
while (!page_rec_is_supremum(insert_rec)) {
267310
count++;
268311
n_recs++;
269312

@@ -280,7 +323,7 @@ PageBulk::finish()
280323
}
281324

282325
insert_rec = page_rec_get_next(insert_rec);
283-
} while (!page_rec_is_supremum(insert_rec));
326+
}
284327

285328
if (slot_index > 0
286329
&& (count + 1 + (PAGE_DIR_SLOT_MAX_N_OWNED + 1) / 2
@@ -303,10 +346,14 @@ PageBulk::finish()
303346
page_dir_slot_set_rec(slot, page_get_supremum_rec(m_page));
304347
page_dir_slot_set_n_owned(slot, NULL, count + 1);
305348

306-
ut_ad(!dict_index_is_spatial(m_index));
307349
ut_ad(!page_get_instant(m_page));
308350

309-
if (!m_flush_observer && !m_page_zip) {
351+
if (!m_rec_no) {
352+
/* Restore PAGE_DIRECTION_B from 0 to
353+
PAGE_NO_DIRECTION like it should be on an empty page,
354+
again without writing redo log. */
355+
m_page[PAGE_HEADER + PAGE_DIRECTION_B] = PAGE_NO_DIRECTION;
356+
} else if (!m_flush_observer && !m_page_zip) {
310357
mlog_write_ulint(PAGE_HEADER + PAGE_N_DIR_SLOTS + m_page,
311358
2 + slot_index, MLOG_2BYTES, &m_mtr);
312359
mlog_write_ulint(PAGE_HEADER + PAGE_HEAP_TOP + m_page,
@@ -343,26 +390,18 @@ PageBulk::finish()
343390
mach_write_to_2(PAGE_HEADER + PAGE_N_DIRECTION + m_page, 0);
344391
}
345392

346-
m_block->skip_flush_check = false;
393+
ut_ad(!needs_finish());
394+
ut_ad(page_validate(m_page, m_index));
347395
}
348396

349397
/** Commit inserts done to the page
350398
@param[in] success Flag whether all inserts succeed. */
351-
void
352-
PageBulk::commit(
353-
bool success)
399+
void PageBulk::commit(bool success)
354400
{
355-
if (success) {
356-
ut_ad(page_validate(m_page, m_index));
357-
358-
/* Set no free space left and no buffered changes in ibuf. */
359-
if (!dict_index_is_clust(m_index) && page_is_leaf(m_page)) {
360-
ibuf_set_bitmap_for_bulk_load(
361-
m_block, innobase_fill_factor == 100);
362-
}
363-
}
364-
365-
m_mtr.commit();
401+
finish();
402+
if (success && !dict_index_is_clust(m_index) && page_is_leaf(m_page))
403+
ibuf_set_bitmap_for_bulk_load(m_block, innobase_fill_factor == 100);
404+
m_mtr.commit();
366405
}
367406

368407
/** Compress a page of compressed table
@@ -604,7 +643,9 @@ PageBulk::storeExt(
604643
const big_rec_t* big_rec,
605644
rec_offs* offsets)
606645
{
607-
/* Note: not all fileds are initialized in btr_pcur. */
646+
finish();
647+
648+
/* Note: not all fields are initialized in btr_pcur. */
608649
btr_pcur_t btr_pcur;
609650
btr_pcur.pos_state = BTR_PCUR_IS_POSITIONED;
610651
btr_pcur.latch_mode = BTR_MODIFY_LEAF;
@@ -633,7 +674,7 @@ Note: log_free_check requires holding no lock/latch in current thread. */
633674
void
634675
PageBulk::release()
635676
{
636-
ut_ad(!dict_index_is_spatial(m_index));
677+
finish();
637678

638679
/* We fix the block because we will re-pin it soon. */
639680
buf_block_buf_fix_inc(m_block, __FILE__, __LINE__);
@@ -691,32 +732,30 @@ BtrBulk::pageSplit(
691732
{
692733
ut_ad(page_bulk->getPageZip() != NULL);
693734

694-
/* 1. Check if we have only one user record on the page. */
695735
if (page_bulk->getRecNo() <= 1) {
696736
return(DB_TOO_BIG_RECORD);
697737
}
698738

699-
/* 2. create a new page. */
739+
/* Initialize a new page */
700740
PageBulk new_page_bulk(m_index, m_trx->id, FIL_NULL,
701741
page_bulk->getLevel(), m_flush_observer);
702742
dberr_t err = new_page_bulk.init();
703743
if (err != DB_SUCCESS) {
704744
return(err);
705745
}
706746

707-
/* 3. copy the upper half to new page. */
747+
/* Copy the upper half to the new page. */
708748
rec_t* split_rec = page_bulk->getSplitRec();
709749
new_page_bulk.copyIn(split_rec);
710750
page_bulk->copyOut(split_rec);
711751

712-
/* 4. commit the splitted page. */
752+
/* Commit the pages after split. */
713753
err = pageCommit(page_bulk, &new_page_bulk, true);
714754
if (err != DB_SUCCESS) {
715755
pageAbort(&new_page_bulk);
716756
return(err);
717757
}
718758

719-
/* 5. commit the new page. */
720759
err = pageCommit(&new_page_bulk, next_page_bulk, true);
721760
if (err != DB_SUCCESS) {
722761
pageAbort(&new_page_bulk);
@@ -942,11 +981,9 @@ BtrBulk::insert(
942981
ut_ad(page_bulk->getLevel() == 0);
943982
ut_ad(page_bulk == m_page_bulks.at(0));
944983

945-
/* Release all latched but leaf node. */
984+
/* Release all pages above the leaf level */
946985
for (ulint level = 1; level <= m_root_level; level++) {
947-
PageBulk* page_bulk = m_page_bulks.at(level);
948-
949-
page_bulk->release();
986+
m_page_bulks.at(level)->release();
950987
}
951988

952989
err = page_bulk->storeExt(big_rec, offsets);
@@ -1032,6 +1069,7 @@ BtrBulk::finish(dberr_t err)
10321069
return(err);
10331070
}
10341071
root_page_bulk.copyIn(first_rec);
1072+
root_page_bulk.finish();
10351073

10361074
/* Remove last page. */
10371075
btr_page_free(m_index, last_block, &mtr);

storage/innobase/buf/buf0buf.cc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,8 +1548,6 @@ buf_block_init(
15481548
#ifdef BTR_CUR_HASH_ADAPT
15491549
block->index = NULL;
15501550
#endif /* BTR_CUR_HASH_ADAPT */
1551-
block->skip_flush_check = false;
1552-
15531551
ut_d(block->page.in_page_hash = FALSE);
15541552
ut_d(block->page.in_zip_hash = FALSE);
15551553
ut_d(block->page.in_flush_list = FALSE);
@@ -3882,7 +3880,6 @@ buf_block_init_low(
38823880
/*===============*/
38833881
buf_block_t* block) /*!< in: block to init */
38843882
{
3885-
block->skip_flush_check = false;
38863883
#ifdef BTR_CUR_HASH_ADAPT
38873884
/* No adaptive hash index entries may point to a previously
38883885
unused (and now freshly allocated) block. */

storage/innobase/buf/buf0dblwr.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -849,10 +849,6 @@ buf_dblwr_check_block(
849849
{
850850
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
851851

852-
if (block->skip_flush_check) {
853-
return;
854-
}
855-
856852
switch (fil_page_get_type(block->frame)) {
857853
case FIL_PAGE_INDEX:
858854
case FIL_PAGE_TYPE_INSTANT:

storage/innobase/buf/buf0lru.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,6 @@ buf_LRU_get_free_block(
951951
ut_ad(buf_pool_from_block(block) == buf_pool);
952952
memset(&block->page.zip, 0, sizeof block->page.zip);
953953

954-
block->skip_flush_check = false;
955954
block->page.flush_observer = NULL;
956955
return(block);
957956
}

storage/innobase/include/btr0bulk.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 2014, 2015, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2019, MariaDB Corporation.
4+
Copyright (c) 2019, 2020, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -110,6 +110,9 @@ class PageBulk
110110
dirs, and set page header members. */
111111
void finish();
112112

113+
/** @return whether finish() actually needs to do something */
114+
inline bool needs_finish() const;
115+
113116
/** Commit mtr for a page
114117
@param[in] success Flag whether all inserts succeed. */
115118
void commit(bool success);

storage/innobase/include/buf0buf.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,9 +1768,6 @@ struct buf_block_t{
17681768
# define assert_block_ahi_empty_on_init(block) /* nothing */
17691769
# define assert_block_ahi_valid(block) /* nothing */
17701770
#endif /* BTR_CUR_HASH_ADAPT */
1771-
bool skip_flush_check;
1772-
/*!< Skip check in buf_dblwr_check_block
1773-
during bulk load, protected by lock.*/
17741771
# ifdef UNIV_DEBUG
17751772
/** @name Debug fields */
17761773
/* @{ */

storage/innobase/page/page0page.cc

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2023,10 +2023,9 @@ page_simple_validate_old(
20232023

20242024
n_slots = page_dir_get_n_slots(page);
20252025

2026-
if (UNIV_UNLIKELY(n_slots > srv_page_size / 4)) {
2027-
ib::error() << "Nonsensical number " << n_slots
2028-
<< " of page dir slots";
2029-
2026+
if (UNIV_UNLIKELY(n_slots < 2 || n_slots > srv_page_size / 4)) {
2027+
ib::error() << "Nonsensical number of page dir slots: "
2028+
<< n_slots;
20302029
goto func_exit;
20312030
}
20322031

@@ -2223,10 +2222,9 @@ page_simple_validate_new(
22232222

22242223
n_slots = page_dir_get_n_slots(page);
22252224

2226-
if (UNIV_UNLIKELY(n_slots > srv_page_size / 4)) {
2227-
ib::error() << "Nonsensical number " << n_slots
2228-
<< " of page dir slots";
2229-
2225+
if (UNIV_UNLIKELY(n_slots < 2 || n_slots > srv_page_size / 4)) {
2226+
ib::error() << "Nonsensical number of page dir slots: "
2227+
<< n_slots;
22302228
goto func_exit;
22312229
}
22322230

@@ -2438,6 +2436,7 @@ bool page_validate(const page_t* page, const dict_index_t* index)
24382436
<< " of table " << index->table->name;
24392437
return FALSE;
24402438
}
2439+
24412440
if (page_is_comp(page)) {
24422441
if (UNIV_UNLIKELY(!page_simple_validate_new(page))) {
24432442
goto func_exit2;

0 commit comments

Comments
 (0)