Skip to content

Commit fa32d28

Browse files
committed
MDEV-20852 BtrBulk is unnecessarily holding dict_index_t::lock
The BtrBulk class, which was introduced in MySQL 5.7, is by design the exclusive writer to an index. It is therefore unnecessary to acquire the dict_index_t::lock in that code. Holding the dict_index_t::lock would unnecessarily block other threads (SQL connections and the InnoDB purge threads) from buffering concurrent modifications to being-created secondary indexes. This fix is motivated by a change in MySQL 5.7.28: Bug #29008298 MYSQLD CRASHES ITSELF WHEN CREATING INDEX mysql/mysql-server@f9fb96c PageBulk::init(), PageBulk::latch(): Never acquire m_index->lock. PageBulk::storeExt(): Remove some pointer indirection, and improve a debug assertion that seems to prove that some code is redundant. BtrBulk::pageCommit(): Assert that m_index->lock is not being held. btr_blob_log_check_t: Do not acquire m_index->lock if m_op == BTR_STORE_INSERT_BULK. Add UNIV_UNLIKELY hints around that condition. btr_store_big_rec_extern_fields(): Allow index->lock not to be held while op == BTR_STORE_INSERT_BULK. Add UNIV_UNLIKELY hints around that condition.
1 parent 3ce14a6 commit fa32d28

File tree

2 files changed

+29
-25
lines changed

2 files changed

+29
-25
lines changed

storage/innobase/btr/btr0bulk.cc

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 2014, 2019, Oracle and/or its affiliates. All Rights Reserved.
44
Copyright (c) 2017, 2019, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
@@ -51,7 +51,7 @@ PageBulk::init()
5151
m_heap = mem_heap_create(1000);
5252

5353
m_mtr.start();
54-
mtr_x_lock(&m_index->lock, &m_mtr);
54+
5555
if (m_flush_observer) {
5656
m_mtr.set_log_mode(MTR_LOG_NO_REDO);
5757
m_mtr.set_flush_observer(m_flush_observer);
@@ -611,22 +611,20 @@ PageBulk::storeExt(
611611
btr_pcur.pos_state = BTR_PCUR_IS_POSITIONED;
612612
btr_pcur.latch_mode = BTR_MODIFY_LEAF;
613613
btr_pcur.btr_cur.index = m_index;
614-
615-
page_cur_t* page_cur = &btr_pcur.btr_cur.page_cur;
616-
page_cur->index = m_index;
617-
page_cur->rec = m_cur_rec;
618-
page_cur->offsets = offsets;
619-
page_cur->block = m_block;
614+
btr_pcur.btr_cur.page_cur.index = m_index;
615+
btr_pcur.btr_cur.page_cur.rec = m_cur_rec;
616+
btr_pcur.btr_cur.page_cur.offsets = offsets;
617+
btr_pcur.btr_cur.page_cur.block = m_block;
620618

621619
dberr_t err = btr_store_big_rec_extern_fields(
622620
&btr_pcur, offsets, big_rec, &m_mtr, BTR_STORE_INSERT_BULK);
623621

624-
ut_ad(page_offset(m_cur_rec) == page_offset(page_cur->rec));
625-
626622
/* Reset m_block and m_cur_rec from page cursor, because
627-
block may be changed during blob insert. */
628-
m_block = page_cur->block;
629-
m_cur_rec = page_cur->rec;
623+
block may be changed during blob insert. (FIXME: Can it really?) */
624+
ut_ad(m_block == btr_pcur.btr_cur.page_cur.block);
625+
626+
m_block = btr_pcur.btr_cur.page_cur.block;
627+
m_cur_rec = btr_pcur.btr_cur.page_cur.rec;
630628
m_page = buf_block_get_frame(m_block);
631629

632630
return(err);
@@ -653,7 +651,7 @@ dberr_t
653651
PageBulk::latch()
654652
{
655653
m_mtr.start();
656-
mtr_x_lock(&m_index->lock, &m_mtr);
654+
657655
if (m_flush_observer) {
658656
m_mtr.set_log_mode(MTR_LOG_NO_REDO);
659657
m_mtr.set_flush_observer(m_flush_observer);
@@ -758,6 +756,10 @@ BtrBulk::pageCommit(
758756
page_bulk->setNext(FIL_NULL);
759757
}
760758

759+
ut_ad(!rw_lock_own_flagged(&m_index->lock,
760+
RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX
761+
| RW_LOCK_FLAG_S));
762+
761763
/* Compress page if it's a compressed table. */
762764
if (page_bulk->getPageZip() != NULL && !page_bulk->compress()) {
763765
return(pageSplit(page_bulk, next_page_bulk));

storage/innobase/btr/btr0cur.cc

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6775,7 +6775,7 @@ struct btr_blob_log_check_t {
67756775
ulint page_no = ULINT_UNDEFINED;
67766776
FlushObserver* observer = m_mtr->get_flush_observer();
67776777

6778-
if (m_op == BTR_STORE_INSERT_BULK) {
6778+
if (UNIV_UNLIKELY(m_op == BTR_STORE_INSERT_BULK)) {
67796779
offs = page_offset(*m_rec);
67806780
page_no = page_get_page_no(
67816781
buf_block_get_frame(*m_block));
@@ -6798,14 +6798,13 @@ struct btr_blob_log_check_t {
67986798
m_mtr->set_named_space(index->space);
67996799
m_mtr->set_flush_observer(observer);
68006800

6801-
if (m_op == BTR_STORE_INSERT_BULK) {
6801+
if (UNIV_UNLIKELY(m_op == BTR_STORE_INSERT_BULK)) {
68026802
page_id_t page_id(dict_index_get_space(index),
68036803
page_no);
68046804
page_size_t page_size(dict_table_page_size(
68056805
index->table));
68066806
page_cur_t* page_cur = &m_pcur->btr_cur.page_cur;
68076807

6808-
mtr_x_lock(dict_index_get_lock(index), m_mtr);
68096808
page_cur->block = btr_block_get(
68106809
page_id, page_size, RW_X_LATCH, index, m_mtr);
68116810
page_cur->rec = buf_block_get_frame(page_cur->block)
@@ -6831,9 +6830,10 @@ struct btr_blob_log_check_t {
68316830
*m_rec,
68326831
MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
68336832

6834-
ut_ad(mtr_memo_contains_flagged(m_mtr,
6835-
dict_index_get_lock(index),
6836-
MTR_MEMO_SX_LOCK | MTR_MEMO_X_LOCK));
6833+
ut_ad((m_op == BTR_STORE_INSERT_BULK)
6834+
== !mtr_memo_contains_flagged(m_mtr, &index->lock,
6835+
MTR_MEMO_SX_LOCK
6836+
| MTR_MEMO_X_LOCK));
68376837
}
68386838
};
68396839

@@ -6887,8 +6887,10 @@ btr_store_big_rec_extern_fields(
68876887

68886888
ut_ad(rec_offs_validate(rec, index, offsets));
68896889
ut_ad(rec_offs_any_extern(offsets));
6890-
ut_ad(mtr_memo_contains_flagged(btr_mtr, dict_index_get_lock(index),
6891-
MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK));
6890+
ut_ad(op == BTR_STORE_INSERT_BULK
6891+
|| mtr_memo_contains_flagged(btr_mtr, &index->lock,
6892+
MTR_MEMO_X_LOCK
6893+
| MTR_MEMO_SX_LOCK));
68926894
ut_ad(mtr_is_block_fix(
68936895
btr_mtr, rec_block, MTR_MEMO_PAGE_X_FIX, index->table));
68946896
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
@@ -7014,7 +7016,7 @@ btr_store_big_rec_extern_fields(
70147016

70157017
mtr_t *alloc_mtr;
70167018

7017-
if (op == BTR_STORE_INSERT_BULK) {
7019+
if (UNIV_UNLIKELY(op == BTR_STORE_INSERT_BULK)) {
70187020
mtr_start(&mtr_bulk);
70197021
mtr_bulk.set_spaces(mtr);
70207022
alloc_mtr = &mtr_bulk;
@@ -7036,7 +7038,7 @@ btr_store_big_rec_extern_fields(
70367038

70377039
alloc_mtr->release_free_extents(r_extents);
70387040

7039-
if (op == BTR_STORE_INSERT_BULK) {
7041+
if (UNIV_UNLIKELY(op == BTR_STORE_INSERT_BULK)) {
70407042
mtr_commit(&mtr_bulk);
70417043
}
70427044

@@ -7192,7 +7194,7 @@ btr_store_big_rec_extern_fields(
71927194
}
71937195

71947196
/* We compress a page when finish bulk insert.*/
7195-
if (op != BTR_STORE_INSERT_BULK) {
7197+
if (UNIV_LIKELY(op != BTR_STORE_INSERT_BULK)) {
71967198
page_zip_write_blob_ptr(
71977199
page_zip, rec, index, offsets,
71987200
field_no, &mtr);

0 commit comments

Comments
 (0)