MySQL  8.0.19
Source Code Documentation
btr0bulk.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 2014, 2019, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License, version 2.0, as published by the
7 Free Software Foundation.
8 
9 This program is also distributed with certain software (including but not
10 limited to OpenSSL) that is licensed under separate terms, as designated in a
11 particular file or component or in included license documentation. The authors
12 of MySQL hereby grant you an additional permission to link the program and
13 your derivative works with the separately licensed software that they have
14 included with MySQL.
15 
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19 for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 
25 *****************************************************************************/
26 
27 /** @file include/btr0bulk.h
28  The B-tree bulk load
29 
30  Created 03/11/2014 Shaohua Wang
31  *************************************************************************/
32 
33 #ifndef btr0bulk_h
34 #define btr0bulk_h
35 
36 #include <stddef.h>
37 #include <vector>
38 
39 #include "dict0dict.h"
40 #include "page0cur.h"
41 #include "ut0new.h"
42 
43 /** Innodb B-tree index fill factor for bulk load. */
44 extern long innobase_fill_factor;
45 
46 /*
47 The proper function call sequence of PageBulk is as below:
48 -- PageBulk::init
49 -- PageBulk::insert
50 -- PageBulk::finish
51 -- PageBulk::compress(COMPRESSED table only)
52 -- PageBulk::pageSplit(COMPRESSED table only)
53 -- PageBulk::commit
54 */
55 
56 class PageBulk {
57  public:
58  /** Page split point descriptor. */
59  struct SplitPoint {
60  /** Record being the point of split.
61  * All records before this record should stay on current on page.
62  * This record and all following records should be moved to new page. */
64  /** Number of records before this record. */
66  };
67 
68  /** Constructor
69  @param[in] index B-tree index
70  @param[in] page_no page number
71  @param[in] level page level
72  @param[in] trx_id transaction id
73  @param[in] observer flush observer */
74  PageBulk(dict_index_t *index, trx_id_t trx_id, page_no_t page_no, ulint level,
75  FlushObserver *observer)
76  : m_heap(nullptr),
77  m_index(index),
78  m_mtr(nullptr),
79  m_trx_id(trx_id),
80  m_block(nullptr),
81  m_page(nullptr),
82  m_page_zip(nullptr),
83  m_cur_rec(nullptr),
84  m_page_no(page_no),
85  m_level(level),
87  m_heap_top(nullptr),
88  m_rec_no(0),
89  m_free_space(0),
91  m_padding_space(0),
92 #ifdef UNIV_DEBUG
93  m_total_data(0),
94 #endif /* UNIV_DEBUG */
95  m_modify_clock(0),
96  m_flush_observer(observer),
97  m_last_slotted_rec(nullptr),
99  m_modified(false) {
101  }
102 
103  /** Destructor */
105  if (m_heap) {
107  }
108  }
109 
110  /** Initialize members and allocate page if needed and start mtr.
111  @note Must be called and only once right after constructor.
112  @return error code */
113  dberr_t init() MY_ATTRIBUTE((warn_unused_result));
114 
115  /** Insert a tuple in the page.
116  @param[in] tuple tuple to insert
117  @param[in] big_rec external record
118  @param[in] rec_size record size
119  @param[in] n_ext number of externally stored columns
120  @return error code */
121  dberr_t insert(const dtuple_t *tuple, const big_rec_t *big_rec,
122  ulint rec_size, ulint n_ext)
123  MY_ATTRIBUTE((warn_unused_result));
124 
125  /** Mark end of insertion to the page. Scan records to set page dirs,
126  and set page header members. The scan is incremental (slots and records
127  which assignment could be "finalized" are not checked again. Check the
128  m_slotted_rec_no usage, note it could be reset in some cases like
129  during split.
130  Note: we refer to page_copy_rec_list_end_to_created_page. */
131  void finish();
132 
133  /** Commit mtr for a page
134  @param[in] success Flag whether all inserts succeed. */
135  void commit(bool success);
136 
137  /** Compress if it is compressed table
138  @return true compress successfully or no need to compress
139  @return false compress failed. */
140  bool compress() MY_ATTRIBUTE((warn_unused_result));
141 
142  /** Check whether the record needs to be stored externally.
143  @return false if the entire record can be stored locally on the page */
144  bool needExt(const dtuple_t *tuple, ulint rec_size) const
145  MY_ATTRIBUTE((warn_unused_result));
146 
147  /** Get node pointer
148  @return node pointer */
149  dtuple_t *getNodePtr();
150 
151  /** Split the page records between this and given bulk.
152  * @param new_page_bulk The new bulk to store split records. */
153  void split(PageBulk &new_page_bulk);
154 
155  /** Copy all records from page.
156  @param[in] src_page Page with records to copy. */
157  void copyAll(const page_t *src_page);
158 
159  /** Set next page
160  @param[in] next_page_no next page no */
161  void setNext(page_no_t next_page_no);
162 
163  /** Set previous page
164  @param[in] prev_page_no previous page no */
165  void setPrev(page_no_t prev_page_no);
166 
167  /** Release block by committing mtr */
168  inline void release();
169 
170  /** Start mtr and latch block */
171  inline void latch();
172 
173  /** Check if required space is available in the page for the rec
174  to be inserted. We check fill factor & padding here.
175  @param[in] rec_size required space
176  @return true if space is available */
177  inline bool isSpaceAvailable(ulint rec_size) const;
178 
179  /** Get page no */
180  page_no_t getPageNo() const { return (m_page_no); }
181 
182  /** Get page level */
183  ulint getLevel() const { return (m_level); }
184 
185  /** Get record no */
186  ulint getRecNo() const { return (m_rec_no); }
187 
188  /** Get page */
189  const page_t *getPage() const { return (m_page); }
190 
191  /** Check if table is compressed.
192  @return true if table is compressed, false otherwise. */
193  bool isTableCompressed() const { return (m_page_zip != nullptr); }
194 
195 #ifdef UNIV_DEBUG
196  /** Check if index is X locked */
197  bool isIndexXLocked();
198 #endif // UNIV_DEBUG
199 
200  private:
201  /** Get page split point. We split a page in half when compression
202  fails, and the split record and all following records should be copied
203  to the new page.
204  @return split record descriptor */
205  SplitPoint getSplitRec();
206 
207  /** Copy given and all following records.
208  @param[in] first_rec first record to copy */
209  void copyRecords(const rec_t *first_rec);
210 
211  /** Remove all records after split rec including itself.
212  @param[in] split_point split point descriptor */
213  void splitTrim(const SplitPoint &split_point);
214 
215  /** Insert a record in the page.
216  @param[in] rec record
217  @param[in] offsets record offsets */
218  void insert(const rec_t *rec, ulint *offsets);
219 
220  /** Store external record
221  Since the record is not logged yet, so we don't log update to the record.
222  the blob data is logged first, then the record is logged in bulk mode.
223  @param[in] big_rec external record
224  @param[in] offsets record offsets
225  @return error code */
226  dberr_t storeExt(const big_rec_t *big_rec, ulint *offsets)
227  MY_ATTRIBUTE((warn_unused_result));
228 
229  /** Memory heap for internal allocation */
231 
232  /** The index B-tree */
234 
235  /** The min-transaction */
237 
238  /** The transaction id */
240 
241  /** The buffer block */
243 
244  /** The page */
246 
247  /** The page zip descriptor */
249 
250  /** The current rec, just before the next insert rec */
252 
253  /** The page no */
255 
256  /** The page level in B-tree */
257  ulint m_level;
258 
259  /** Flag: is page in compact format */
260  const bool m_is_comp;
261 
262  /** The heap top in page for next insert */
263  byte *m_heap_top;
264 
265  /** User record no */
266  ulint m_rec_no;
267 
268  /** The free space left in the page */
270 
271  /** The reserved space for fill factor */
273 
274  /** The padding space for compressed page */
276 
277 #ifdef UNIV_DEBUG
278  /** Total data in the page */
280 #endif /* UNIV_DEBUG */
281 
282  /** The modify clock value of the buffer block
283  when the block is re-pinned */
284  ib_uint64_t m_modify_clock;
285 
286  /** Flush observer */
288 
289  /** Last record assigned to a slot. */
291 
292  /** Number of records assigned to slots. */
294 
295  /** Page modified flag. */
297 };
298 
299 class BtrBulk {
300  public:
301  using page_bulk_vector = std::vector<PageBulk *, ut_allocator<PageBulk *>>;
302 
303  /** Constructor
304  @param[in] index B-tree index
305  @param[in] trx_id transaction id
306  @param[in] observer flush observer */
307  BtrBulk(dict_index_t *index, trx_id_t trx_id, FlushObserver *observer);
308 
309  /** Destructor */
310  ~BtrBulk();
311 
312  /** Initialization
313  @note Must be called right after constructor. */
314  dberr_t init() MY_ATTRIBUTE((warn_unused_result));
315 
316  /** Insert a tuple
317  @param[in] tuple tuple to insert.
318  @return error code */
319  dberr_t insert(dtuple_t *tuple) MY_ATTRIBUTE((warn_unused_result)) {
320  return (insert(tuple, 0));
321  }
322 
323  /** Btree bulk load finish. We commit the last page in each level
324  and copy the last page in top level to the root page of the index
325  if no error occurs.
326  @param[in] err whether bulk load was successful until now
327  @return error code */
328  dberr_t finish(dberr_t err) MY_ATTRIBUTE((warn_unused_result));
329 
330  /** Release all latches */
331  void release();
332 
333  /** Re-latch all latches */
334  void latch();
335 
336  private:
337  /** Insert a tuple to a page in a level
338  @param[in] tuple tuple to insert
339  @param[in] level B-tree level
340  @return error code */
341  dberr_t insert(dtuple_t *tuple, ulint level)
342  MY_ATTRIBUTE((warn_unused_result));
343 
344  /** Split a page
345  @param[in] page_bulk page to split
346  @param[in] next_page_bulk next page
347  @return error code */
348  dberr_t pageSplit(PageBulk *page_bulk, PageBulk *next_page_bulk)
349  MY_ATTRIBUTE((warn_unused_result));
350 
351  /** Commit(finish) a page. We set next/prev page no, compress a page of
352  compressed table and split the page if compression fails, insert a node
353  pointer to father page if needed, and commit mini-transaction.
354  @param[in] page_bulk page to commit
355  @param[in] next_page_bulk next page
356  @param[in] insert_father flag whether need to insert node ptr
357  @return error code */
358  dberr_t pageCommit(PageBulk *page_bulk, PageBulk *next_page_bulk,
359  bool insert_father) MY_ATTRIBUTE((warn_unused_result));
360 
361  /** Abort a page when an error occurs
362  @param[in] page_bulk page bulk object
363  @note We should call pageAbort for a PageBulk object, which is not in
364  m_page_bulks after pageCommit, and we will commit or abort PageBulk
365  objects in function "finish". */
366  void pageAbort(PageBulk *page_bulk) { page_bulk->commit(false); }
367 
368  /** Prepare space to insert a tuple.
369  @param[in,out] page_bulk page bulk that will be used to store the record.
370  It may be replaced if there is not enough space
371  to hold the record.
372  @param[in] level B-tree level
373  @param[in] rec_size record size
374  @return error code */
375  dberr_t prepareSpace(PageBulk *&page_bulk, ulint level, ulint rec_size)
376  MY_ATTRIBUTE((warn_unused_result));
377 
378  /** Insert a tuple to a page.
379  @param[in] page_bulk page bulk object
380  @param[in] tuple tuple to insert
381  @param[in] big_rec big record vector, maybe NULL if there is no
382  data to be stored externally.
383  @param[in] rec_size record size
384  @param[in] n_ext number of externally stored columns
385  @return error code */
386  dberr_t insert(PageBulk *page_bulk, dtuple_t *tuple, big_rec_t *big_rec,
387  ulint rec_size, ulint n_ext)
388  MY_ATTRIBUTE((warn_unused_result));
389 
390  /** Log free check */
391  void logFreeCheck();
392 
393  /** Btree page bulk load finish. Commits the last page in each level
394  if no error occurs. Also releases all page bulks.
395  @param[in] err whether bulk load was successful until now
396  @param[out] last_page_no last page number
397  @return error code */
399  MY_ATTRIBUTE((warn_unused_result));
400 
401  private:
402  /** B-tree index */
404 
405  /** Transaction id */
407 
408  /** Root page level */
410 
411  /** Flush observer */
413 
414  /** Page cursor vector for all level */
416 
417 #ifdef UNIV_DEBUG
418  /** State of the index. Used for asserting at the end of a
419  bulk load operation to ensure that the online status of the
420  index does not change */
421  unsigned m_index_online;
422 #endif // UNIV_DEBUG
423 };
424 
425 #endif
page_no_t
uint32 page_no_t
Page number.
Definition: api0api.h:57
BtrBulk::finishAllPageBulks
dberr_t finishAllPageBulks(dberr_t err, page_no_t &last_page_no)
Btree page bulk load finish.
Definition: btr0bulk.cc:1013
PageBulk::m_level
ulint m_level
The page level in B-tree.
Definition: btr0bulk.h:257
PageBulk::copyRecords
void copyRecords(const rec_t *first_rec)
Copy given and all following records.
Definition: btr0bulk.cc:438
PageBulk::m_page_no
page_no_t m_page_no
The page no.
Definition: btr0bulk.h:254
dtuple_t
Structure for an SQL data tuple of fields (logical record)
Definition: data0data.h:716
PageBulk::setPrev
void setPrev(page_no_t prev_page_no)
Set previous page.
Definition: btr0bulk.cc:517
page_t
byte page_t
Type of the index page.
Definition: page0types.h:133
BtrBulk::~BtrBulk
~BtrBulk()
Destructor.
Definition: btr0bulk.cc:778
PageBulk::isSpaceAvailable
bool isSpaceAvailable(ulint rec_size) const
Check if required space is available in the page for the rec to be inserted.
Definition: btr0bulk.cc:525
BtrBulk::latch
void latch()
Re-latch all latches.
Definition: btr0bulk.cc:814
PageBulk::getPageNo
page_no_t getPageNo() const
Get page no.
Definition: btr0bulk.h:180
trx_id_t
ib_id_t trx_id_t
Transaction identifier (DB_TRX_ID, DATA_TRX_ID)
Definition: trx0types.h:148
PageBulk::m_modified
bool m_modified
Page modified flag.
Definition: btr0bulk.h:296
PageBulk::init
dberr_t init()
Initialize members and allocate page if needed and start mtr.
Definition: btr0bulk.cc:46
PageBulk::m_mtr
mtr_t * m_mtr
The min-transaction.
Definition: btr0bulk.h:236
PageBulk::getRecNo
ulint getRecNo() const
Get record no.
Definition: btr0bulk.h:186
PageBulk::m_heap
mem_heap_t * m_heap
Memory heap for internal allocation.
Definition: btr0bulk.h:230
ut_ad
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:65
PageBulk::insert
dberr_t insert(const dtuple_t *tuple, const big_rec_t *big_rec, ulint rec_size, ulint n_ext)
Insert a tuple in the page.
Definition: btr0bulk.cc:172
dict_index_t
Data structure for an index.
Definition: dict0mem.h:869
PageBulk::finish
void finish()
Mark end of insertion to the page.
Definition: btr0bulk.cc:271
mtr_t
Mini-transaction handle and buffer.
Definition: mtr0mtr.h:169
PageBulk::needExt
bool needExt(const dtuple_t *tuple, ulint rec_size) const
Check whether the record needs to be stored externally.
Definition: btr0bulk.cc:551
PageBulk::m_page_zip
page_zip_des_t * m_page_zip
The page zip descriptor.
Definition: btr0bulk.h:248
PageBulk::setNext
void setNext(page_no_t next_page_no)
Set next page.
Definition: btr0bulk.cc:511
BtrBulk::pageSplit
dberr_t pageSplit(PageBulk *page_bulk, PageBulk *next_page_bulk)
Split a page.
Definition: btr0bulk.cc:657
PageBulk::m_modify_clock
ib_uint64_t m_modify_clock
The modify clock value of the buffer block when the block is re-pinned.
Definition: btr0bulk.h:284
PageBulk::copyAll
void copyAll(const page_t *src_page)
Copy all records from page.
Definition: btr0bulk.cc:425
dberr_t
dberr_t
Definition: db0err.h:38
PageBulk::~PageBulk
~PageBulk()
Destructor.
Definition: btr0bulk.h:104
BtrBulk::m_trx_id
trx_id_t m_trx_id
Transaction id.
Definition: btr0bulk.h:406
buf_block_t
The buffer control block structure.
Definition: buf0buf.h:1318
PageBulk::split
void split(PageBulk &new_page_bulk)
Split the page records between this and given bulk.
Definition: btr0bulk.cc:371
PageBulk::m_padding_space
ulint m_padding_space
The padding space for compressed page.
Definition: btr0bulk.h:275
PageBulk::getSplitRec
SplitPoint getSplitRec()
Get page split point.
Definition: btr0bulk.cc:385
BtrBulk::init
dberr_t init()
Initialization.
Definition: btr0bulk.cc:790
PageBulk::m_last_slotted_rec
rec_t * m_last_slotted_rec
Last record assigned to a slot.
Definition: btr0bulk.h:290
PageBulk::m_rec_no
ulint m_rec_no
User record no.
Definition: btr0bulk.h:266
json_binary::err
static Value err()
Create a Value object that represents an error condition.
Definition: json_binary.cc:908
PageBulk::m_heap_top
byte * m_heap_top
The heap top in page for next insert.
Definition: btr0bulk.h:263
PageBulk::m_flush_observer
FlushObserver * m_flush_observer
Flush observer.
Definition: btr0bulk.h:287
rec_t
byte rec_t
Definition: rem0types.h:39
big_rec_t
Storage format for overflow data in a big record, that is, a clustered index record which needs exter...
Definition: data0data.h:853
mem_block_info_t
The info structure stored at the beginning of a heap block.
Definition: mem0mem.h:337
page_zip_des_t
Compressed page descriptor.
Definition: page0types.h:182
BtrBulk::m_root_level
ulint m_root_level
Root page level.
Definition: btr0bulk.h:409
BtrBulk::insert
dberr_t insert(dtuple_t *tuple)
Insert a tuple.
Definition: btr0bulk.h:319
PageBulk::getNodePtr
dtuple_t * getNodePtr()
Get node pointer.
Definition: btr0bulk.cc:359
PageBulk::isIndexXLocked
bool isIndexXLocked()
Check if index is X locked.
Definition: btr0bulk.cc:646
dict_index_is_spatial
UNIV_INLINE ulint dict_index_is_spatial(const dict_index_t *index)
Check whether the index is a Spatial Index.
PageBulk::compress
bool compress()
Compress if it is compressed table.
Definition: btr0bulk.cc:349
PageBulk::m_page
page_t * m_page
The page.
Definition: btr0bulk.h:245
BtrBulk::release
void release()
Release all latches.
Definition: btr0bulk.cc:802
PageBulk::commit
void commit(bool success)
Commit mtr for a page.
Definition: btr0bulk.cc:328
PageBulk::m_index
dict_index_t * m_index
The index B-tree.
Definition: btr0bulk.h:233
page0cur.h
BtrBulk::m_flush_observer
FlushObserver * m_flush_observer
Flush observer.
Definition: btr0bulk.h:412
PageBulk::m_free_space
ulint m_free_space
The free space left in the page.
Definition: btr0bulk.h:269
BtrBulk::BtrBulk
BtrBulk(dict_index_t *index, trx_id_t trx_id, FlushObserver *observer)
Constructor.
Definition: btr0bulk.cc:764
BtrBulk::m_index
dict_index_t * m_index
B-tree index.
Definition: btr0bulk.h:403
PageBulk::SplitPoint::m_n_rec_before
ulint m_n_rec_before
Number of records before this record.
Definition: btr0bulk.h:65
innobase_fill_factor
long innobase_fill_factor
Innodb B-tree index fill factor for bulk load.
Definition: btr0bulk.cc:41
mem_heap_free
UNIV_INLINE void mem_heap_free(mem_heap_t *heap)
Frees the space occupied by a memory heap.
BtrBulk::m_page_bulks
page_bulk_vector * m_page_bulks
Page cursor vector for all level.
Definition: btr0bulk.h:415
ut0new.h
PageBulk::PageBulk
PageBulk(dict_index_t *index, trx_id_t trx_id, page_no_t page_no, ulint level, FlushObserver *observer)
Constructor.
Definition: btr0bulk.h:74
PageBulk::m_slotted_rec_no
ulint m_slotted_rec_no
Number of records assigned to slots.
Definition: btr0bulk.h:293
dict_table_is_comp
UNIV_INLINE ibool dict_table_is_comp(const dict_table_t *table)
Check whether the table uses the compact page format.
PageBulk
Definition: btr0bulk.h:56
PageBulk::latch
void latch()
Start mtr and latch block.
Definition: btr0bulk.cc:614
PageBulk::m_reserved_space
ulint m_reserved_space
The reserved space for fill factor.
Definition: btr0bulk.h:272
BtrBulk::pageCommit
dberr_t pageCommit(PageBulk *page_bulk, PageBulk *next_page_bulk, bool insert_father)
Commit(finish) a page.
Definition: btr0bulk.cc:705
PageBulk::m_total_data
ulint m_total_data
Total data in the page.
Definition: btr0bulk.h:279
PageBulk::m_trx_id
trx_id_t m_trx_id
The transaction id.
Definition: btr0bulk.h:239
PageBulk::m_is_comp
const bool m_is_comp
Flag: is page in compact format.
Definition: btr0bulk.h:260
PageBulk::m_block
buf_block_t * m_block
The buffer block.
Definition: btr0bulk.h:242
PageBulk::SplitPoint::m_rec
rec_t * m_rec
Record being the point of split.
Definition: btr0bulk.h:63
BtrBulk::prepareSpace
dberr_t prepareSpace(PageBulk *&page_bulk, ulint level, ulint rec_size)
Prepare space to insert a tuple.
Definition: btr0bulk.cc:831
PageBulk::release
void release()
Release block by committing mtr.
Definition: btr0bulk.cc:594
PageBulk::splitTrim
void splitTrim(const SplitPoint &split_point)
Remove all records after split rec including itself.
Definition: btr0bulk.cc:459
PageBulk::SplitPoint
Page split point descriptor.
Definition: btr0bulk.h:59
PageBulk::m_cur_rec
rec_t * m_cur_rec
The current rec, just before the next insert rec.
Definition: btr0bulk.h:251
BtrBulk::page_bulk_vector
std::vector< PageBulk *, ut_allocator< PageBulk * > > page_bulk_vector
Definition: btr0bulk.h:301
BtrBulk::m_index_online
unsigned m_index_online
State of the index.
Definition: btr0bulk.h:421
BtrBulk::pageAbort
void pageAbort(PageBulk *page_bulk)
Abort a page when an error occurs.
Definition: btr0bulk.h:366
PageBulk::getLevel
ulint getLevel() const
Get page level.
Definition: btr0bulk.h:183
BtrBulk::logFreeCheck
void logFreeCheck()
Log free check.
Definition: btr0bulk.cc:750
FlushObserver
We use FlushObserver to track flushing of non-redo logged pages in bulk create index(BtrBulk....
Definition: buf0flu.h:269
PageBulk::isTableCompressed
bool isTableCompressed() const
Check if table is compressed.
Definition: btr0bulk.h:193
dict0dict.h
index
char * index(const char *, int c)
Definition: mysql.cc:2875
PageBulk::storeExt
dberr_t storeExt(const big_rec_t *big_rec, ulint *offsets)
Store external record Since the record is not logged yet, so we don't log update to the record.
Definition: btr0bulk.cc:562
PageBulk::getPage
const page_t * getPage() const
Get page.
Definition: btr0bulk.h:189
BtrBulk
Definition: btr0bulk.h:299
BtrBulk::finish
dberr_t finish(dberr_t err)
Btree bulk load finish.
Definition: btr0bulk.cc:1045
false
#define false
Definition: config_static.h:43