MySQL 26.7.0
Source Code Documentation
row0pread.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2018, 2026, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is designed to work with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation. The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have either included with
15the program or referenced in the documentation.
16
17This program is distributed in the hope that it will be useful, but WITHOUT
18ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
20for more details.
21
22You should have received a copy of the GNU General Public License along with
23this program; if not, write to the Free Software Foundation, Inc.,
2451 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
26*****************************************************************************/
27
28/** @file include/row0pread.h
29Parallel read interface.
30
31Created 2018-01-27 by Sunny Bains. */
32
33#ifndef row0par_read_h
34#define row0par_read_h
35
36#include <functional>
37#include <vector>
38
39#include "os0thread-create.h"
40#include "row0sel.h"
41
42// Forward declarations
43struct trx_t;
44struct mtr_t;
45class PCursor;
46struct btr_pcur_t;
47struct buf_block_t;
48struct dict_table_t;
49
50#include "btr0cur.h"
51#include "db0err.h"
52#include "fil0fil.h"
53#include "os0event.h"
54#include "page0size.h"
55#include "rem0types.h"
56#include "ut0mpmcbq.h"
57
58/** The core idea is to find the left and right paths down the B+Tree.These
59paths correspond to the scan start and scan end search. Follow the links
60at the appropriate btree level from the left to right and split the scan
61on each of these sub-tree root nodes.
62
63If the user has set the maximum number of threads to use at say 4 threads
64and there are 5 sub-trees at the selected level then we will split the 5th
65sub-tree dynamically when it is ready for scan.
66
67We want to allow multiple parallel range scans on different indexes at the
68same time. To achieve this split out the scan context (Scan_ctx) from the
69execution context (Ctx). The Scan_ctx has the index and transaction
70information and the Ctx keeps track of the cursor for a specific thread
71during the scan.
72
73To start a scan we need to instantiate a Parallel_reader. A parallel reader
74can contain several Scan_ctx instances and a Scan_ctx can contain several
75Ctx instances. Its' the Ctx instances that are eventually executed.
76
77This design allows for a single Parallel_reader to scan multiple indexes
78at once. Each index range scan has to be added via its add_scan() method.
79This functionality is required to handle parallel partition scans because
80partitions are separate indexes. This can be used to scan completely
81different indexes and tables by one instance of a Parallel_reader.
82
83To solve the imbalance problem we dynamically split the sub-trees as and
84when required. e.g., If you have 5 sub-trees to scan and 4 threads then
85it will tag the 5th sub-tree as "to_be_split" during phase I (add_scan()),
86the first thread that finishes scanning the first set of 4 partitions will
87then dynamically split the 5th sub-tree and add the newly created sub-trees
88to the execution context (Ctx) run queue in the Parallel_reader. As the
89other threads complete their sub-tree scans they will pick up more execution
90contexts (Ctx) from the Parallel_reader run queue and start scanning the
91sub-partitions as normal.
92
93Note: The Ctx instances are in a virtual list. Each Ctx instance has a
94range to scan. The start point of this range instance is the end point
95of the Ctx instance scanning values less than its start point. A Ctx
96will scan from [Start, End) rows. We use std::shared_ptr to manage the
97reference counting, this allows us to dispose of the Ctx instances
98without worrying about dangling pointers.
99
100NOTE: Secondary index scans are not supported currently. */
102 public:
103 /** Maximum value for innodb-parallel-read-threads. */
104 constexpr static size_t MAX_THREADS{256};
105
106 /** Maximum value for reserved parallel read threads for data load so that
107 at least this many threads are always available for data load. */
108 constexpr static size_t MAX_RESERVED_THREADS{16};
109
110 /** Maximum value for at most number of parallel read threads that can be
111 spawned. */
113
114 using Links = std::vector<page_no_t, ut::allocator<page_no_t>>;
115
116 // Forward declaration.
117 class Ctx;
118 class Scan_ctx;
119 struct Thread_ctx;
120
121 /** Scan state. */
122 enum class State : uint8_t {
123 /** Unknown state. */
124 UNKNOWN,
125
126 /** Start/Finish thread state. */
127 THREAD,
128
129 /** Start/Finish Ctx state. */
130 CTX,
131
132 /** Start/Finish page read. */
133 PAGE
134 };
135
136 /** Callback to initialise callers state. */
137 using Start = std::function<dberr_t(Thread_ctx *thread_ctx)>;
138
139 /** Callback to finalise callers state. */
140 using Finish = std::function<dberr_t(Thread_ctx *thread_ctx)>;
141
142 /** Callback to process the rows. */
143 using F = std::function<dberr_t(const Ctx *)>;
144
145 /** Specifies the range from where to start the scan and where to end it. */
146 struct Scan_range {
147 /** Default constructor. */
149
150 /** Copy constructor.
151 @param[in] scan_range Instance to copy from. */
152 Scan_range(const Scan_range &scan_range) = default;
153
154 /** Constructor.
155 @param[in] start Start key
156 @param[in] end End key. */
158 : m_start(start), m_end(end) {}
159
160 /** Start of the scan, can be nullptr for -infinity. */
162
163 /** End of the scan, can be null for +infinity. */
164 const dtuple_t *m_end{};
165
166 /** Convert the instance to a string representation. */
167 [[nodiscard]] std::string to_string() const;
168 };
169
170 /** Scan (Scan_ctx) configuration. */
171 struct Config {
172 /** Constructor.
173 @param[in] scan_range Range to scan.
174 @param[in] index Cluster index to scan.
175 @param[in] read_level Btree level from which records need to be read.
176 @param[in] partition_id Partition id if the index to be scanned.
177 belongs to a partitioned table. */
178 Config(const Scan_range &scan_range, dict_index_t *index,
179 size_t read_level = 0,
180 size_t partition_id = std::numeric_limits<size_t>::max())
181 : m_scan_range(scan_range),
182 m_index(index),
185 m_read_level(read_level),
186 m_partition_id(partition_id) {}
187
188 /** Copy constructor.
189 @param[in] config Instance to copy from. */
190 Config(const Config &config)
191
192 = default;
193
194 /** Range to scan. */
196
197 /** (Cluster) Index in table to scan. */
199
200 /** Row format of table. */
201 const bool m_is_compact{};
202
203 /** Tablespace page size. */
205
206 /** Btree level from which records need to be read. */
207 size_t m_read_level{0};
208
209 /** Partition id if the index to be scanned belongs to a partitioned table,
210 else std::numeric_limits<size_t>::max(). */
212 };
213
214 /** Thread related context information. */
215 struct Thread_ctx {
216 /** Constructor.
217 @param[in] id Thread ID */
218 explicit Thread_ctx(size_t id) noexcept : m_thread_id(id) {}
219
220 /** Destructor. */
222 ut_a(m_callback_ctx == nullptr);
223
224 if (m_blob_heap != nullptr) {
226 }
227 }
228
229 /** Set thread related callback information.
230 @param[in] ctx callback context */
231 template <typename T>
232 void set_callback_ctx(T *ctx) noexcept {
233 ut_ad(m_callback_ctx == nullptr || ctx == nullptr);
234 m_callback_ctx = ctx;
235 }
236
237 /** Get the thread related callback information/
238 @return return context. */
239 template <typename T>
241 return static_cast<T *>(m_callback_ctx);
242 }
243
244 /** Create BLOB heap. */
246 ut_a(m_blob_heap == nullptr);
248 }
249
250 /** @return the worker thread state. */
251 State get_state() const noexcept { return m_state; }
252
253 /** @see PCursor::save_current_user_record_as_last_processed */
255
256 /** @see PCursor::restore_to_last_processed_user_record */
258
259 /** @see PCursor::save_previous_user_record_as_last_processed */
261
262 /** @see PCursor::restore_to_first_unprocessed */
264
265 /** Thread ID. */
267
268 /** Callback information related to the thread.
269 @note Needs to be created and destroyed by the callback itself. */
271
272 /** BLOB heap per thread. */
274
275 /** Worker thread state. */
277
278 /** Current persistent cursor. */
280
281 Thread_ctx(Thread_ctx &&) = delete;
282 Thread_ctx(const Thread_ctx &) = delete;
284 Thread_ctx &operator=(const Thread_ctx &) = delete;
285 };
286
287 /** Constructor.
288 @param[in] max_threads Maximum number of threads to use. */
289 explicit Parallel_reader(size_t max_threads);
290
291 /** Destructor. */
293
294 /** Check how many threads are available for parallel reads.
295 @param[in] n_required Number of threads required.
296 @param[in] use_reserved true if reserved threads needs to be considered
297 while checking for availability of threads
298 @return number of threads available. */
299 [[nodiscard]] static size_t available_threads(size_t n_required,
300 bool use_reserved);
301
302 /** Release the parallel read threads. */
303 static void release_threads(size_t n_threads) {
304 const auto SEQ_CST = std::memory_order_seq_cst;
305 auto active = s_active_threads.fetch_sub(n_threads, SEQ_CST);
306 ut_a(active >= n_threads);
307 }
308
309 /** Add scan context.
310 @param[in,out] trx Covering transaction.
311 @param[in] config Scan condfiguration.
312 @param[in] f Callback function.
313 (default is 0 which is leaf level)
314 @return error. */
315 [[nodiscard]] dberr_t add_scan(trx_t *trx, const Config &config, F &&f);
316
317 /** Wait for the join of threads spawned by the parallel reader. */
318 void join() {
319 for (auto &t : m_parallel_read_threads) {
320 t.wait();
321 }
322 }
323
324 /** Get the error stored in the global error state.
325 @return global error state. */
326 [[nodiscard]] dberr_t get_error_state() const { return m_err; }
327
328 /** @return true if the tree is empty, else false. */
329 [[nodiscard]] bool is_tree_empty() const {
330 return m_ctx_id.load(std::memory_order_relaxed) == 0;
331 }
332
333 /** Set the callback that must be called before any processing.
334 @param[in] f Call before first row is processed.*/
335 void set_start_callback(Start &&f) { m_start_callback = std::move(f); }
336
337 /** Set the callback that must be called after all processing.
338 @param[in] f Call after last row is processed.*/
339 void set_finish_callback(Finish &&f) { m_finish_callback = std::move(f); }
340
341 /** Spawn the threads to do the parallel read for the specified range.
342 Don't wait for the spawned to threads to complete.
343 @param[in] n_threads number of threads that *need* to be spawned
344 @return DB_SUCCESS or error code. */
345 [[nodiscard]] dberr_t spawn(size_t n_threads) noexcept;
346
347 /** Start the threads to do the parallel read for the specified range.
348 @param[in] n_threads Number of threads to use for the scan.
349 @return DB_SUCCESS or error code. */
350 [[nodiscard]] dberr_t run(size_t n_threads);
351
352 /** @return the configured max threads size. */
353 [[nodiscard]] size_t max_threads() const { return m_max_threads; }
354
355 /** @return true iff this reader runs worker() on the caller's thread. */
356 [[nodiscard]] bool is_sync() const noexcept { return m_sync; }
357
358 /** @return true if in error state. */
359 [[nodiscard]] bool is_error_set() const {
360 return m_err.load(std::memory_order_relaxed) != DB_SUCCESS;
361 }
362
363 /** Set the error state.
364 @param[in] err Error state to set to. */
366 m_err.store(err, std::memory_order_relaxed);
367 }
368
369 /** Set the number of threads to be spawned.
370 @param[in] n_threads number of threads to be spawned. */
371 void set_n_threads(size_t n_threads) {
372 ut_ad(n_threads <= m_max_threads);
373 m_n_threads = n_threads;
374 }
375
376 // Disable copying.
381
382 private:
383 /** Release unused threads back to the pool.
384 @param[in] unused_threads Number of threads to "release". */
385 void release_unused_threads(size_t unused_threads) {
386 ut_a(m_max_threads >= unused_threads);
387 release_threads(unused_threads);
388 }
389
390 /** Add an execution context to the run queue.
391 @param[in] ctx Execution context to add to the queue. */
392 void enqueue(std::shared_ptr<Ctx> ctx);
393
394 /** Fetch the next job execute.
395 @return job to execute or nullptr. */
396 [[nodiscard]] std::shared_ptr<Ctx> dequeue();
397
398 /** @return true if job queue is empty. */
399 [[nodiscard]] bool is_queue_empty() const;
400
401 /** Poll for requests and execute.
402 @param[in] thread_ctx thread related context information */
403 void worker(Thread_ctx *thread_ctx);
404
405 /** Create the threads and do a parallel read across the partitions. */
406 void parallel_read();
407
408 /** @return true if tasks are still executing. */
409 [[nodiscard]] bool is_active() const {
410 return m_n_completed.load(std::memory_order_relaxed) <
411 m_ctx_id.load(std::memory_order_relaxed);
412 }
413
414 private:
415 // clang-format off
416 using Ctxs =
417 std::list<std::shared_ptr<Ctx>,
419
420 using Scan_ctxs =
421 std::list<std::shared_ptr<Scan_ctx>,
423
424 // clang-format on
425
426 /** Maximum number of worker threads to use. */
428
429 /** Number of worker threads that will be spawned. */
430 size_t m_n_threads{0};
431
432 /** Mutex protecting m_ctxs. */
433 mutable ib_mutex_t m_mutex;
434
435 /** Contexts that must be executed. */
437
438 /** Scan contexts. */
440
441 /** For signalling worker threads about events. */
443
444 /** Value returned by previous call of os_event_reset() on m_event. */
445 uint64_t m_sig_count;
446
447 /** Counter for allocating scan context IDs. */
449
450 /** Context ID. Monotonically increasing ID. */
451 std::atomic_size_t m_ctx_id{};
452
453 /** Total tasks executed so far. */
454 std::atomic_size_t m_n_completed{};
455
456 /** Callback at start (before processing any rows). */
458
459 /** Callback at end (adter processing all rows). */
461
462 /** Error during parallel read. */
463 std::atomic<dberr_t> m_err{DB_SUCCESS};
464
465 /** List of threads used for paralle_read purpose. */
466 std::vector<IB_thread, ut::allocator<IB_thread>> m_parallel_read_threads;
467
468 /** Number of threads currently doing parallel reads. */
469 static std::atomic_size_t s_active_threads;
470
471 /** If the caller wants to wait for the parallel_read to finish it's run */
472 bool m_sync;
473
474 /** Context information related to each parallel reader thread. */
475 std::vector<Thread_ctx *, ut::allocator<Thread_ctx *>> m_thread_ctxs;
476};
477
478/** Parallel reader context. */
480 public:
481 /** Constructor.
482 @param[in] reader Parallel reader that owns this context.
483 @param[in] id ID of this scan context.
484 @param[in] trx Transaction covering the scan.
485 @param[in] config Range scan config.
486 @param[in] f Callback function. */
487 Scan_ctx(Parallel_reader *reader, size_t id, trx_t *trx,
488 const Parallel_reader::Config &config, F &&f);
489
490 /** Destructor. */
491 ~Scan_ctx() = default;
492
493 private:
494 /** Boundary of the range to scan. */
495 struct Iter {
496 /** Destructor. */
497 ~Iter();
498
499 /** Heap used to allocate m_rec, m_tuple and m_pcur. */
501
502 /** m_rec column offsets. */
503 const ulint *m_offsets{};
504
505 /** Start scanning from this key. Raw data of the row. */
506 const rec_t *m_rec{};
507
508 /** Tuple representation inside m_rec, for two Iter instances in a range
509 m_tuple will be [first->m_tuple, second->m_tuple). */
511
512 /** Persistent cursor.*/
514 };
515
516 /** mtr_t savepoint. */
517 using Savepoint = std::pair<ulint, buf_block_t *>;
518
519 /** For releasing the S latches after processing the blocks. */
520 using Savepoints = std::vector<Savepoint, ut::allocator<Savepoint>>;
521
522 /** The first cursor should read up to the second cursor [f, s). */
523 using Range = std::pair<std::shared_ptr<Iter>, std::shared_ptr<Iter>>;
524
525 using Ranges = std::vector<Range, ut::allocator<Range>>;
526
527 /** @return the scan context ID. */
528 [[nodiscard]] size_t id() const { return m_id; }
529
530 /** Set the error state.
531 @param[in] err Error state to set to. */
533 m_err.store(err, std::memory_order_relaxed);
534 }
535
536 /** @return true if in error state. */
537 [[nodiscard]] bool is_error_set() const {
538 return m_err.load(std::memory_order_relaxed) != DB_SUCCESS;
539 }
540
541 /** Fetch a block from the buffer pool and acquire an S latch on it.
542 @param[in] page_id Page ID.
543 @param[in,out] mtr Mini-transaction covering the fetch.
544 @param[in] line Line from where called.
545 @return the block fetched from the buffer pool. */
546 [[nodiscard]] buf_block_t *block_get_s_latched(const page_id_t &page_id,
547 mtr_t *mtr, size_t line) const;
548
549 /** Partition the B+Tree for parallel read.
550 @param[in] scan_range Range for partitioning.
551 @param[in,out] ranges Ranges to scan.
552 @param[in] split_level Sub-range required level (0 == root).
553 @return the partition scan ranges. */
554 dberr_t partition(const Scan_range &scan_range, Ranges &ranges,
555 size_t split_level);
556
557 /** Find the page number of the node that contains the search key. If the
558 key is null then we assume -infinity.
559 @param[in] block Page to look in.
560 @param[in] key Key of the first record in the range.
561 @return the left child page number. */
562 [[nodiscard]] page_no_t search(const buf_block_t *block,
563 const dtuple_t *key) const;
564
565 /** Traverse from given sub-tree page number to start of the scan range
566 from the given page number.
567 @param[in] page_no Page number of sub-tree.
568 @param[in,out] mtr Mini-transaction.
569 @param[in] key Key of the first record in the range.
570 @param[in,out] savepoints Blocks S latched and accessed.
571 @return the leaf node page cursor. */
572 [[nodiscard]] page_cur_t start_range(page_no_t page_no, mtr_t *mtr,
573 const dtuple_t *key,
574 Savepoints &savepoints) const;
575
576 /** Create and add the range to the scan ranges.
577 @param[in,out] ranges Ranges to scan.
578 @param[in,out] leaf_page_cursor Leaf page cursor on which to create the
579 persistent cursor.
580 @param[in,out] mtr Mini-transaction */
581 void create_range(Ranges &ranges, page_cur_t &leaf_page_cursor,
582 mtr_t *mtr) const;
583
584 /** Find the subtrees to scan in a block.
585 @param[in] scan_range Partition based on this scan range.
586 @param[in] page_no Page to partition at if at required level.
587 @param[in] depth Sub-range current level.
588 @param[in] split_level Sub-range starting level (0 == root).
589 @param[in,out] ranges Ranges to scan.
590 @param[in,out] mtr Mini-transaction */
591 dberr_t create_ranges(const Scan_range &scan_range, page_no_t page_no,
592 size_t depth, const size_t split_level, Ranges &ranges,
593 mtr_t *mtr);
594
595 /** Build a dtuple_t from rec_t.
596 @param[in] rec Build the dtuple from this record.
597 @param[in,out] iter Build in this iterator. */
598 void copy_row(const rec_t *rec, Iter *iter) const;
599
600 /** Create the persistent cursor that will be used to traverse the
601 partition and position on the start row.
602 @param[in] page_cursor Current page cursor
603 @param[in] mtr Mini-transaction covering the read.
604 @return Start iterator. */
605 [[nodiscard]] std::shared_ptr<Iter> create_persistent_cursor(
606 const page_cur_t &page_cursor, mtr_t *mtr) const;
607
608 /** Build an old version of the row if required.
609 @param[in,out] rec Current row read from the index. This can
610 be modified by this method if an older version
611 needs to be built.
612 @param[in,out] offsets Same as above but pertains to the rec offsets
613 @param[in,out] heap Heap to use if a previous version needs to be
614 built from the undo log.
615 @param[in,out] mtr Mini-transaction covering the read.
616 @return true if row is visible to the transaction. */
617 [[nodiscard]] bool check_visibility(const rec_t *&rec, ulint *&offsets,
618 mem_heap_t *&heap, mtr_t *mtr);
619
620 /** Create an execution context for a range and add it to
621 the Parallel_reader's run queue.
622 @param[in] range Range for which to create the context.
623 @param[in] split true if the sub-tree should be split further.
624 @return DB_SUCCESS or error code. */
625 [[nodiscard]] dberr_t create_context(const Range &range, bool split);
626
627 /** Create the execution contexts based on the ranges.
628 @param[in] ranges Ranges for which to create the contexts.
629 @return DB_SUCCESS or error code. */
630 [[nodiscard]] dberr_t create_contexts(const Ranges &ranges);
631
632 /** @return the maximum number of threads configured. */
633 [[nodiscard]] size_t max_threads() const { return m_reader->max_threads(); }
634
635 /** Release unused threads back to the pool.
636 @param[in] unused_threads Number of threads to "release". */
637 void release_threads(size_t unused_threads) {
638 m_reader->release_threads(unused_threads);
639 }
640
641 /** S lock the index. */
642 void index_s_lock();
643
644 /** S unlock the index. */
645 void index_s_unlock();
646
647 /** @return true if at least one thread owns the S latch on the index. */
648 bool index_s_own() const {
649 return m_s_locks.load(std::memory_order_acquire) > 0;
650 }
651
652 private:
654
655 /** Context ID. */
657
658 /** Parallel scan configuration. */
660
661 /** Covering transaction. */
662 const trx_t *m_trx{};
663
664 /** Callback function. */
666
667 /** Depth of the Btree. */
668 size_t m_depth{};
669
670 /** The parallel reader. */
672
673 /** Error during parallel read. */
674 mutable std::atomic<dberr_t> m_err{DB_SUCCESS};
675
676 /** Number of threads that have S locked the index. */
677 std::atomic_size_t m_s_locks{};
678
679 friend class Parallel_reader;
680
681 Scan_ctx(Scan_ctx &&) = delete;
682 Scan_ctx(const Scan_ctx &) = delete;
684 Scan_ctx &operator=(const Scan_ctx &) = delete;
685};
686
687/** Parallel reader execution context. */
689 public:
690 /** Constructor.
691 @param[in] id Thread ID.
692 @param[in] scan_ctx Scan context.
693 @param[in] range Range that the thread has to read. */
694 Ctx(size_t id, Scan_ctx *scan_ctx, const Scan_ctx::Range &range)
695 : m_id(id), m_range(range), m_scan_ctx(scan_ctx) {}
696
697 /** Destructor. */
698 ~Ctx() = default;
699
700 public:
701 /** @return the context ID. */
702 [[nodiscard]] size_t id() const { return m_id; }
703
704 /** The scan ID of the scan context this belongs to. */
705 [[nodiscard]] size_t scan_id() const { return m_scan_ctx->id(); }
706
707 /** @return the covering transaction. */
708 [[nodiscard]] const trx_t *trx() const { return m_scan_ctx->m_trx; }
709
710 /** @return the index being scanned. */
711 [[nodiscard]] const dict_index_t *index() const {
713 }
714
715 /** @return ID of the thread processing this context */
716 [[nodiscard]] size_t thread_id() const { return m_thread_ctx->m_thread_id; }
717
718 /** @return the thread context of the reader thread. */
719 [[nodiscard]] Thread_ctx *thread_ctx() const { return m_thread_ctx; }
720
721 /** @return the partition id of the index.
722 @note this is std::numeric_limits<size_t>::max() if the index does not
723 belong to a partition. */
724 [[nodiscard]] size_t partition_id() const {
726 }
727
728 /** Build an old version of the row if required.
729 @param[in,out] rec Current row read from the index. This can
730 be modified by this method if an older version
731 needs to be built.
732 @param[in,out] offsets Same as above but pertains to the rec offsets
733 @param[in,out] heap Heap to use if a previous version needs to be
734 built from the undo log.
735 @param[in,out] mtr Mini-transaction covering the read.
736 @return true if row is visible to the transaction. */
737 bool is_rec_visible(const rec_t *&rec, ulint *&offsets, mem_heap_t *&heap,
738 mtr_t *mtr) {
739 return m_scan_ctx->check_visibility(rec, offsets, heap, mtr);
740 }
741
742 private:
743 /** Traverse the pages by key order.
744 @return DB_SUCCESS or error code. */
745 [[nodiscard]] dberr_t traverse();
746
747 /** Traverse the records in a node.
748 @param[in] pcursor persistent b-tree cursor
749 @param[in] mtr mtr
750 @return error */
751 dberr_t traverse_recs(PCursor *pcursor, mtr_t *mtr);
752
753 /** Move to the next node in the specified level.
754 @param[in] pcursor persistent b-tree cursor
755 @return success */
756 bool move_to_next_node(PCursor *pcursor);
757
758 /** Split the context into sub-ranges and add them to the execution queue.
759 @return DB_SUCCESS or error code. */
760 [[nodiscard]] dberr_t split();
761
762 /** @return true if in error state. */
763 [[nodiscard]] bool is_error_set() const {
765 }
766
767 private:
768 /** Context ID. */
770
771 /** If true then split the context at the block level. */
772 bool m_split{};
773
774 /** Range to read in this context. */
776
777 /** Scanner context. */
779
780 public:
781 /** Context information related to executing thread ID. */
783
784 /** Current block. */
786
787 /** Current row. */
788 const rec_t *m_rec{};
789
790 /** Number of pages traversed by the context. */
791 size_t m_n_pages{};
792
793 /** True if m_rec is the first record in the page. */
794 bool m_first_rec{true};
795
797
798 /** Start of a new range to scan. */
799 bool m_start{};
800
801 friend class Parallel_reader;
802};
803
804#endif /* !row0par_read_h */
uint32_t page_no_t
Page number.
Definition: api0api.h:47
The index tree cursor.
Persistent cursor wrapper around btr_pcur_t.
Definition: row0pread.cc:210
Parallel reader execution context.
Definition: row0pread.h:688
bool is_rec_visible(const rec_t *&rec, ulint *&offsets, mem_heap_t *&heap, mtr_t *mtr)
Build an old version of the row if required.
Definition: row0pread.h:737
Ctx(size_t id, Scan_ctx *scan_ctx, const Scan_ctx::Range &range)
Constructor.
Definition: row0pread.h:694
size_t id() const
Definition: row0pread.h:702
size_t m_n_pages
Number of pages traversed by the context.
Definition: row0pread.h:791
~Ctx()=default
Destructor.
bool is_error_set() const
Definition: row0pread.h:763
dberr_t split()
Split the context into sub-ranges and add them to the execution queue.
Definition: row0pread.cc:150
Scan_ctx::Range m_range
Range to read in this context.
Definition: row0pread.h:775
Scan_ctx * m_scan_ctx
Scanner context.
Definition: row0pread.h:778
bool m_start
Start of a new range to scan.
Definition: row0pread.h:799
const trx_t * trx() const
Definition: row0pread.h:708
bool m_split
If true then split the context at the block level.
Definition: row0pread.h:772
dberr_t traverse_recs(PCursor *pcursor, mtr_t *mtr)
Traverse the records in a node.
Definition: row0pread.cc:815
size_t thread_id() const
Definition: row0pread.h:716
bool m_first_rec
True if m_rec is the first record in the page.
Definition: row0pread.h:794
Thread_ctx * thread_ctx() const
Definition: row0pread.h:719
size_t scan_id() const
The scan ID of the scan context this belongs to.
Definition: row0pread.h:705
const buf_block_t * m_block
Current block.
Definition: row0pread.h:785
ulint * m_offsets
Definition: row0pread.h:796
bool move_to_next_node(PCursor *pcursor)
Move to the next node in the specified level.
Definition: row0pread.cc:761
size_t m_id
Context ID.
Definition: row0pread.h:769
const dict_index_t * index() const
Definition: row0pread.h:711
size_t partition_id() const
Definition: row0pread.h:724
Thread_ctx * m_thread_ctx
Context information related to executing thread ID.
Definition: row0pread.h:782
const rec_t * m_rec
Current row.
Definition: row0pread.h:788
dberr_t traverse()
Traverse the pages by key order.
Definition: row0pread.cc:777
Parallel reader context.
Definition: row0pread.h:479
std::atomic_size_t m_s_locks
Number of threads that have S locked the index.
Definition: row0pread.h:677
dberr_t partition(const Scan_range &scan_range, Ranges &ranges, size_t split_level)
Partition the B+Tree for parallel read.
Definition: row0pread.cc:1350
page_cur_t start_range(page_no_t page_no, mtr_t *mtr, const dtuple_t *key, Savepoints &savepoints) const
Traverse from given sub-tree page number to start of the scan range from the given page number.
Definition: row0pread.cc:1138
std::pair< ulint, buf_block_t * > Savepoint
mtr_t savepoint.
Definition: row0pread.h:517
size_t id() const
Definition: row0pread.h:528
Scan_ctx & operator=(Scan_ctx &&)=delete
void index_s_lock()
S lock the index.
Definition: row0pread.cc:134
std::shared_ptr< Iter > create_persistent_cursor(const page_cur_t &page_cursor, mtr_t *mtr) const
Create the persistent cursor that will be used to traverse the partition and position on the start ro...
Definition: row0pread.cc:714
size_t m_id
Context ID.
Definition: row0pread.h:656
F m_f
Callback function.
Definition: row0pread.h:665
bool index_s_own() const
Definition: row0pread.h:648
dberr_t create_context(const Range &range, bool split)
Create an execution context for a range and add it to the Parallel_reader's run queue.
Definition: row0pread.cc:1385
void index_s_unlock()
S unlock the index.
Definition: row0pread.cc:142
dberr_t create_contexts(const Ranges &ranges)
Create the execution contexts based on the ranges.
Definition: row0pread.cc:1410
void release_threads(size_t unused_threads)
Release unused threads back to the pool.
Definition: row0pread.h:637
page_no_t search(const buf_block_t *block, const dtuple_t *key) const
Find the page number of the node that contains the search key.
Definition: row0pread.cc:1100
size_t max_threads() const
Definition: row0pread.h:633
Config m_config
Parallel scan configuration.
Definition: row0pread.h:659
void set_error_state(dberr_t err)
Set the error state.
Definition: row0pread.h:532
void copy_row(const rec_t *rec, Iter *iter) const
Build a dtuple_t from rec_t.
Definition: row0pread.cc:679
~Scan_ctx()=default
Destructor.
std::vector< Savepoint, ut::allocator< Savepoint > > Savepoints
For releasing the S latches after processing the blocks.
Definition: row0pread.h:520
size_t m_depth
Depth of the Btree.
Definition: row0pread.h:668
std::pair< std::shared_ptr< Iter >, std::shared_ptr< Iter > > Range
The first cursor should read up to the second cursor [f, s).
Definition: row0pread.h:523
void create_range(Ranges &ranges, page_cur_t &leaf_page_cursor, mtr_t *mtr) const
Create and add the range to the scan ranges.
Definition: row0pread.cc:1178
std::atomic< dberr_t > m_err
Error during parallel read.
Definition: row0pread.h:674
Scan_ctx & operator=(const Scan_ctx &)=delete
std::vector< Range, ut::allocator< Range > > Ranges
Definition: row0pread.h:525
bool is_error_set() const
Definition: row0pread.h:537
const trx_t * m_trx
Covering transaction.
Definition: row0pread.h:662
buf_block_t * block_get_s_latched(const page_id_t &page_id, mtr_t *mtr, size_t line) const
Fetch a block from the buffer pool and acquire an S latch on it.
Definition: row0pread.cc:341
Scan_ctx(Scan_ctx &&)=delete
Scan_ctx(const Scan_ctx &)=delete
Scan_ctx(Parallel_reader *reader, size_t id, trx_t *trx, const Parallel_reader::Config &config, F &&f)
Constructor.
Definition: row0pread.cc:203
Parallel_reader * m_reader
The parallel reader.
Definition: row0pread.h:671
dberr_t create_ranges(const Scan_range &scan_range, page_no_t page_no, size_t depth, const size_t split_level, Ranges &ranges, mtr_t *mtr)
Find the subtrees to scan in a block.
Definition: row0pread.cc:1194
bool check_visibility(const rec_t *&rec, ulint *&offsets, mem_heap_t *&heap, mtr_t *mtr)
Build an old version of the row if required.
Definition: row0pread.cc:624
The core idea is to find the left and right paths down the B+Tree.These paths correspond to the scan ...
Definition: row0pread.h:101
size_t max_threads() const
Definition: row0pread.h:353
std::function< dberr_t(Thread_ctx *thread_ctx)> Finish
Callback to finalise callers state.
Definition: row0pread.h:140
void parallel_read()
Create the threads and do a parallel read across the partitions.
Definition: row0pread.cc:1442
std::atomic_size_t m_n_completed
Total tasks executed so far.
Definition: row0pread.h:454
std::vector< IB_thread, ut::allocator< IB_thread > > m_parallel_read_threads
List of threads used for paralle_read purpose.
Definition: row0pread.h:466
constexpr static size_t MAX_THREADS
Maximum value for innodb-parallel-read-threads.
Definition: row0pread.h:104
Parallel_reader & operator=(Parallel_reader &&)=delete
bool m_sync
If the caller wants to wait for the parallel_read to finish it's run.
Definition: row0pread.h:472
bool is_queue_empty() const
Definition: row0pread.cc:974
dberr_t run(size_t n_threads)
Start the threads to do the parallel read for the specified range.
Definition: row0pread.cc:1519
std::vector< Thread_ctx *, ut::allocator< Thread_ctx * > > m_thread_ctxs
Context information related to each parallel reader thread.
Definition: row0pread.h:475
std::vector< page_no_t, ut::allocator< page_no_t > > Links
Definition: row0pread.h:114
std::atomic< dberr_t > m_err
Error during parallel read.
Definition: row0pread.h:463
bool is_active() const
Definition: row0pread.h:409
size_t m_n_threads
Number of worker threads that will be spawned.
Definition: row0pread.h:430
uint64_t m_sig_count
Value returned by previous call of os_event_reset() on m_event.
Definition: row0pread.h:445
dberr_t get_error_state() const
Get the error stored in the global error state.
Definition: row0pread.h:326
Parallel_reader(const Parallel_reader &)=delete
size_t m_max_threads
Maximum number of worker threads to use.
Definition: row0pread.h:427
std::shared_ptr< Ctx > dequeue()
Fetch the next job execute.
Definition: row0pread.cc:958
void release_unused_threads(size_t unused_threads)
Release unused threads back to the pool.
Definition: row0pread.h:385
Start m_start_callback
Callback at start (before processing any rows).
Definition: row0pread.h:457
os_event_t m_event
For signalling worker threads about events.
Definition: row0pread.h:442
Parallel_reader & operator=(const Parallel_reader &)=delete
void set_start_callback(Start &&f)
Set the callback that must be called before any processing.
Definition: row0pread.h:335
bool is_error_set() const
Definition: row0pread.h:359
bool is_sync() const noexcept
Definition: row0pread.h:356
Scan_ctxs m_scan_ctxs
Scan contexts.
Definition: row0pread.h:439
Parallel_reader(size_t max_threads)
Constructor.
Definition: row0pread.cc:190
Parallel_reader(Parallel_reader &&)=delete
constexpr static size_t MAX_RESERVED_THREADS
Maximum value for reserved parallel read threads for data load so that at least this many threads are...
Definition: row0pread.h:108
dberr_t spawn(size_t n_threads) noexcept
Spawn the threads to do the parallel read for the specified range.
Definition: row0pread.cc:1504
ib_mutex_t m_mutex
Mutex protecting m_ctxs.
Definition: row0pread.h:433
void set_finish_callback(Finish &&f)
Set the callback that must be called after all processing.
Definition: row0pread.h:339
void worker(Thread_ctx *thread_ctx)
Poll for requests and execute.
Definition: row0pread.cc:981
void join()
Wait for the join of threads spawned by the parallel reader.
Definition: row0pread.h:318
~Parallel_reader()
Destructor.
Definition: row0pread.cc:92
std::list< std::shared_ptr< Scan_ctx >, ut::allocator< std::shared_ptr< Scan_ctx > > > Scan_ctxs
Definition: row0pread.h:422
Finish m_finish_callback
Callback at end (adter processing all rows).
Definition: row0pread.h:460
size_t m_scan_ctx_id
Counter for allocating scan context IDs.
Definition: row0pread.h:448
static std::atomic_size_t s_active_threads
Number of threads currently doing parallel reads.
Definition: row0pread.h:469
static void release_threads(size_t n_threads)
Release the parallel read threads.
Definition: row0pread.h:303
constexpr static size_t MAX_TOTAL_THREADS
Maximum value for at most number of parallel read threads that can be spawned.
Definition: row0pread.h:112
void enqueue(std::shared_ptr< Ctx > ctx)
Add an execution context to the run queue.
Definition: row0pread.cc:952
void set_n_threads(size_t n_threads)
Set the number of threads to be spawned.
Definition: row0pread.h:371
static size_t available_threads(size_t n_required, bool use_reserved)
Check how many threads are available for parallel reads.
Definition: row0pread.cc:105
void set_error_state(dberr_t err)
Set the error state.
Definition: row0pread.h:365
std::list< std::shared_ptr< Ctx >, ut::allocator< std::shared_ptr< Ctx > > > Ctxs
Definition: row0pread.h:418
State
Scan state.
Definition: row0pread.h:122
@ PAGE
Start/Finish page read.
@ CTX
Start/Finish Ctx state.
@ THREAD
Start/Finish thread state.
@ UNKNOWN
Unknown state.
dberr_t add_scan(trx_t *trx, const Config &config, F &&f)
Add scan context.
Definition: row0pread.cc:1559
bool is_tree_empty() const
Definition: row0pread.h:329
std::atomic_size_t m_ctx_id
Context ID.
Definition: row0pread.h:451
std::function< dberr_t(Thread_ctx *thread_ctx)> Start
Callback to initialise callers state.
Definition: row0pread.h:137
std::function< dberr_t(const Ctx *)> F
Callback to process the rows.
Definition: row0pread.h:143
Ctxs m_ctxs
Contexts that must be executed.
Definition: row0pread.h:436
Page identifier.
Definition: buf0types.h:191
Page size descriptor.
Definition: page0size.h:50
Allocator that allows std containers to manage their memory through ut::malloc* and ut::free library ...
Definition: ut0new.h:2023
Global error codes for the database.
dberr_t
Definition: db0err.h:39
@ DB_SUCCESS
Definition: db0err.h:43
uint32_t dict_tf_to_fsp_flags(uint32_t table_flags)
Convert a 32 bit integer table flags to the 32 bit FSP Flags.
Definition: dict0dict.cc:4955
static bool dict_table_is_comp(const dict_table_t *table)
Check whether the table uses the compact page format.
The low-level file system.
static int flags[50]
Definition: hp_test1.cc:40
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:180
#define T
Definition: jit_executor_value.cc:373
static void mem_heap_free(mem_heap_t *heap)
Frees the space occupied by a memory heap.
static mem_heap_t * mem_heap_create(ulint size, ut::Location loc, ulint type=MEM_HEAP_DYNAMIC)
Creates a memory heap.
static PFS_engine_table_share_proxy table
Definition: pfs.cc:61
bool index(const std::string &value, const String &search_for, uint32_t *idx)
Definition: contains.h:76
static Value err()
Create a Value object that represents an error condition.
Definition: json_binary.cc:943
ValueType max(X &&first)
Definition: gtid.h:103
noexcept
The return type for any call_and_catch(f, args...) call where f(args...) returns Type.
Definition: call_and_catch.h:76
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:192
The interface to the operating system condition variables.
The interface to the threading wrapper.
A class describing a page size.
Record manager global types.
byte rec_t
Definition: rem0types.h:41
required string key
Definition: replication_asynchronous_connection_failover.proto:60
Select.
Scan (Scan_ctx) configuration.
Definition: row0pread.h:171
size_t m_partition_id
Partition id if the index to be scanned belongs to a partitioned table, else std::numeric_limits<size...
Definition: row0pread.h:211
Config(const Scan_range &scan_range, dict_index_t *index, size_t read_level=0, size_t partition_id=std::numeric_limits< size_t >::max())
Constructor.
Definition: row0pread.h:178
const bool m_is_compact
Row format of table.
Definition: row0pread.h:201
size_t m_read_level
Btree level from which records need to be read.
Definition: row0pread.h:207
Config(const Config &config)=default
Copy constructor.
dict_index_t * m_index
(Cluster) Index in table to scan.
Definition: row0pread.h:198
const Scan_range m_scan_range
Range to scan.
Definition: row0pread.h:195
const page_size_t m_page_size
Tablespace page size.
Definition: row0pread.h:204
Boundary of the range to scan.
Definition: row0pread.h:495
const dtuple_t * m_tuple
Tuple representation inside m_rec, for two Iter instances in a range m_tuple will be [first->m_tuple,...
Definition: row0pread.h:510
btr_pcur_t * m_pcur
Persistent cursor.
Definition: row0pread.h:513
const rec_t * m_rec
Start scanning from this key.
Definition: row0pread.h:506
mem_heap_t * m_heap
Heap used to allocate m_rec, m_tuple and m_pcur.
Definition: row0pread.h:500
~Iter()
Destructor.
Definition: row0pread.cc:77
const ulint * m_offsets
m_rec column offsets.
Definition: row0pread.h:503
Specifies the range from where to start the scan and where to end it.
Definition: row0pread.h:146
Scan_range()
Default constructor.
Definition: row0pread.h:148
Scan_range(const Scan_range &scan_range)=default
Copy constructor.
const dtuple_t * m_end
End of the scan, can be null for +infinity.
Definition: row0pread.h:164
const dtuple_t * m_start
Start of the scan, can be nullptr for -infinity.
Definition: row0pread.h:161
std::string to_string() const
Convert the instance to a string representation.
Definition: row0pread.cc:59
Scan_range(const dtuple_t *start, const dtuple_t *end)
Constructor.
Definition: row0pread.h:157
Thread related context information.
Definition: row0pread.h:215
size_t m_thread_id
Thread ID.
Definition: row0pread.h:266
Thread_ctx & operator=(Thread_ctx &&)=delete
void create_blob_heap() noexcept
Create BLOB heap.
Definition: row0pread.h:245
Thread_ctx(const Thread_ctx &)=delete
mem_heap_t * m_blob_heap
BLOB heap per thread.
Definition: row0pread.h:273
void * m_callback_ctx
Callback information related to the thread.
Definition: row0pread.h:270
Thread_ctx(size_t id) noexcept
Constructor.
Definition: row0pread.h:218
void restore_to_first_unprocessed() noexcept
Definition: row0pread.cc:544
PCursor * m_pcursor
Current persistent cursor.
Definition: row0pread.h:279
void restore_to_last_processed_user_record() noexcept
Definition: row0pread.cc:535
Thread_ctx(Thread_ctx &&)=delete
State get_state() const noexcept
Definition: row0pread.h:251
Thread_ctx & operator=(const Thread_ctx &)=delete
State m_state
Worker thread state.
Definition: row0pread.h:276
void save_current_user_record_as_last_processed() noexcept
Definition: row0pread.cc:530
void set_callback_ctx(T *ctx) noexcept
Set thread related callback information.
Definition: row0pread.h:232
void save_previous_user_record_as_last_processed() noexcept
Definition: row0pread.cc:540
T * get_callback_ctx() noexcept
Get the thread related callback information/.
Definition: row0pread.h:240
~Thread_ctx() noexcept
Destructor.
Definition: row0pread.h:221
Definition: btr0pcur.h:99
The buffer control block structure.
Definition: buf0buf.h:1756
Data structure for an index.
Definition: dict0mem.h:1069
Data structure for a database table.
Definition: dict0mem.h:1927
Structure for an SQL data tuple of fields (logical record)
Definition: data0data.h:706
The info structure stored at the beginning of a heap block.
Definition: mem0mem.h:295
Mini-transaction handle and buffer.
Definition: mtr0mtr.h:174
InnoDB condition variable.
Definition: os0event.cc:63
Index page cursor.
Definition: page0cur.h:311
Definition: gen_lex_token.cc:149
Definition: trx0trx.h:670
#define UNIV_PAGE_SIZE
The universal page size of the database.
Definition: univ.i:291
unsigned long int ulint
Definition: univ.i:403
#define UT_LOCATION_HERE
Definition: ut0core.h:73
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:109
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:97