1 /***************************************************************************** 2 3 Copyright (c) 1996, 2020, 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/trx0types.h 28 Transaction system global type definitions 29 30 Created 3/26/1996 Heikki Tuuri 31 *******************************************************/ 32 33 #ifndef trx0types_h 34 #define trx0types_h 35 36 #include "page0size.h" 37 #include "sync0rw.h" 38 #include "ut0byte.h" 39 #include "ut0mutex.h" 40 #include "ut0new.h" 41 42 #include <atomic> 43 #include <queue> 44 #include <set> 45 #include <vector> 46 47 //#include <unordered_set> 48 49 /** printf(3) format used for printing DB_TRX_ID and other system fields */ 50 #define TRX_ID_FMT IB_ID_FMT 51 52 /** Space id of the transaction system page (the system tablespace) */ 53 static const space_id_t TRX_SYS_SPACE = 0; 54 55 /** Page number of the transaction system page */ 56 #define TRX_SYS_PAGE_NO FSP_TRX_SYS_PAGE_NO 57 58 /** Random value to check for corruption of trx_t */ 59 static const ulint TRX_MAGIC_N = 91118598; 60 61 /** If this flag is set then the transaction cannot be rolled back 62 asynchronously. */ 63 static const ib_uint32_t TRX_FORCE_ROLLBACK_DISABLE = 1 << 29; 64 65 /** Was the transaction rolled back asynchronously or by the 66 owning thread. This flag is relevant only if TRX_FORCE_ROLLBACK 67 is set. */ 68 static const ib_uint32_t TRX_FORCE_ROLLBACK_ASYNC = 1 << 30; 69 70 /** Mark the transaction for forced rollback */ 71 static const ib_uint32_t TRX_FORCE_ROLLBACK = 1 << 31; 72 73 /** For masking out the above four flags */ 74 static const ib_uint32_t TRX_FORCE_ROLLBACK_MASK = 0x1FFFFFFF; 75 76 /** Transaction execution states when trx->state == TRX_STATE_ACTIVE */ 77 enum trx_que_t { 78 TRX_QUE_RUNNING, /*!< transaction is running */ 79 TRX_QUE_LOCK_WAIT, /*!< transaction is waiting for 80 a lock */ 81 TRX_QUE_ROLLING_BACK, /*!< transaction is rolling back */ 82 TRX_QUE_COMMITTING /*!< transaction is committing */ 83 }; 84 85 /** Transaction states (trx_t::state) */ 86 enum trx_state_t { 87 88 TRX_STATE_NOT_STARTED, 89 90 /** Same as not started but with additional semantics that it 91 was rolled back asynchronously the last time it was active. */ 92 TRX_STATE_FORCED_ROLLBACK, 93 94 TRX_STATE_ACTIVE, 95 96 /** Support for 2PC/XA */ 97 TRX_STATE_PREPARED, 98 99 TRX_STATE_COMMITTED_IN_MEMORY 100 }; 101 102 /** Type of data dictionary operation */ 103 enum trx_dict_op_t { 104 /** The transaction is not modifying the data dictionary. */ 105 TRX_DICT_OP_NONE = 0, 106 /** The transaction is creating a table or an index, or 107 dropping a table. The table must be dropped in crash 108 recovery. This and TRX_DICT_OP_NONE are the only possible 109 operation modes in crash recovery. */ 110 TRX_DICT_OP_TABLE = 1, 111 /** The transaction is creating or dropping an index in an 112 existing table. In crash recovery, the data dictionary 113 must be locked, but the table must not be dropped. */ 114 TRX_DICT_OP_INDEX = 2 115 }; 116 117 /** Memory objects */ 118 /* @{ */ 119 /** Transaction */ 120 struct trx_t; 121 /** The locks and state of an active transaction */ 122 struct trx_lock_t; 123 /** Transaction system */ 124 struct trx_sys_t; 125 /** Signal */ 126 struct trx_sig_t; 127 /** Rollback segment */ 128 struct trx_rseg_t; 129 /** Transaction undo log */ 130 struct trx_undo_t; 131 /** The control structure used in the purge operation */ 132 struct trx_purge_t; 133 /** Rollback command node in a query graph */ 134 struct roll_node_t; 135 /** Commit command node in a query graph */ 136 struct commit_node_t; 137 /** SAVEPOINT command node in a query graph */ 138 struct trx_named_savept_t; 139 /* @} */ 140 141 /** Row identifier (DB_ROW_ID, DATA_ROW_ID) */ 142 typedef ib_id_t row_id_t; 143 /** Transaction identifier (DB_TRX_ID, DATA_TRX_ID) */ 144 typedef ib_id_t trx_id_t; 145 /** Rollback pointer (DB_ROLL_PTR, DATA_ROLL_PTR) */ 146 typedef ib_id_t roll_ptr_t; 147 /** Undo number */ 148 typedef ib_id_t undo_no_t; 149 150 /** Maximum transaction identifier */ 151 #define TRX_ID_MAX IB_ID_MAX 152 153 /** Transaction savepoint */ 154 struct trx_savept_t { 155 undo_no_t least_undo_no; /*!< least undo number to undo */ 156 }; 157 158 /** File objects */ 159 /* @{ */ 160 /** Transaction system header */ 161 typedef byte trx_sysf_t; 162 /** Rollback segment array header */ 163 typedef byte trx_rsegsf_t; 164 /** Rollback segment header */ 165 typedef byte trx_rsegf_t; 166 /** Undo segment header */ 167 typedef byte trx_usegf_t; 168 /** Undo log header */ 169 typedef byte trx_ulogf_t; 170 /** Undo log page header */ 171 typedef byte trx_upagef_t; 172 /** Undo log record */ 173 typedef byte trx_undo_rec_t; 174 /* @} */ 175 176 typedef ib_mutex_t RsegMutex; 177 typedef ib_mutex_t TrxMutex; 178 typedef ib_mutex_t UndoMutex; 179 typedef ib_mutex_t PQMutex; 180 typedef ib_mutex_t TrxSysMutex; 181 182 /** The rollback segment memory object */ 183 struct trx_rseg_t { 184 #ifdef UNIV_DEBUG 185 /** Validate the curr_size member by re-calculating it. 186 @param[in] take_mutex take the rseg->mutex. default is true. 187 @return true if valid, false otherwise. */ 188 bool validate_curr_size(bool take_mutex = true); 189 #endif /* UNIV_DEBUG */ 190 191 /** Enter the rseg->mutex. */ latchtrx_rseg_t192 void latch() { 193 mutex_enter(&mutex); 194 ut_ad(validate_curr_size(false)); 195 } 196 197 /** Exit the rseg->mutex. */ unlatchtrx_rseg_t198 void unlatch() { 199 ut_ad(validate_curr_size(false)); 200 mutex_exit(&mutex); 201 } 202 203 /** Decrement the current size of the rollback segment by the given number 204 of pages. 205 @param[in] npages number of pages to reduce in size. */ 206 void decr_curr_size(page_no_t npages = 1) { 207 ut_ad(curr_size >= npages); 208 curr_size -= npages; 209 } 210 211 /** Increment the current size of the rollback segment by the given number 212 of pages. */ incr_curr_sizetrx_rseg_t213 void incr_curr_size() { ++curr_size; } 214 215 /* Get the current size of the rollback segment in pages. 216 @return current size of the rollback segment in pages. */ get_curr_sizetrx_rseg_t217 page_no_t get_curr_size() const { return (curr_size); } 218 219 /* Set the current size of the rollback segment in pages. 220 @param[in] npages new value for the current size. */ set_curr_sizetrx_rseg_t221 void set_curr_size(page_no_t npages) { curr_size = npages; } 222 223 /*--------------------------------------------------------*/ 224 /** rollback segment id == the index of its slot in the trx 225 system file copy */ 226 size_t id{}; 227 228 /** mutex protecting the fields in this struct except id,space,page_no 229 which are constant */ 230 RsegMutex mutex; 231 232 /** space ID where the rollback segment header is placed */ 233 space_id_t space_id{}; 234 235 /** page number of the rollback segment header */ 236 page_no_t page_no{}; 237 238 /** page size of the relevant tablespace */ 239 page_size_t page_size; 240 241 /** maximum allowed size in pages */ 242 page_no_t max_size{}; 243 244 private: 245 /** current size in pages */ 246 page_no_t curr_size{}; 247 248 public: 249 /*--------------------------------------------------------*/ 250 /* Fields for update undo logs */ 251 /** List of update undo logs */ 252 UT_LIST_BASE_NODE_T(trx_undo_t) update_undo_list; 253 254 /** List of update undo log segments cached for fast reuse */ 255 UT_LIST_BASE_NODE_T(trx_undo_t) update_undo_cached; 256 257 /*--------------------------------------------------------*/ 258 /* Fields for insert undo logs */ 259 /** List of insert undo logs */ 260 UT_LIST_BASE_NODE_T(trx_undo_t) insert_undo_list; 261 262 /** List of insert undo log segments cached for fast reuse */ 263 UT_LIST_BASE_NODE_T(trx_undo_t) insert_undo_cached; 264 265 /*--------------------------------------------------------*/ 266 267 /** Page number of the last not yet purged log header in the history 268 list; FIL_NULL if all list purged */ 269 page_no_t last_page_no{}; 270 271 /** Byte offset of the last not yet purged log header */ 272 size_t last_offset{}; 273 274 /** Transaction number of the last not yet purged log */ 275 trx_id_t last_trx_no; 276 277 /** true if the last not yet purged log needs purging */ 278 bool last_del_marks{}; 279 280 /** Reference counter to track rseg allocated transactions. */ 281 std::atomic<size_t> trx_ref_count{}; 282 printtrx_rseg_t283 std::ostream &print(std::ostream &out) const { 284 out << "[trx_rseg_t: this=" << (void *)this << ", id=" << id 285 << ", space_id=" << space_id << ", page_no=" << page_no 286 << ", curr_size=" << curr_size << "]"; 287 return (out); 288 } 289 }; 290 291 inline std::ostream &operator<<(std::ostream &out, const trx_rseg_t &rseg) { 292 return (rseg.print(out)); 293 } 294 295 using Rsegs_Vector = std::vector<trx_rseg_t *, ut_allocator<trx_rseg_t *>>; 296 using Rseg_Iterator = Rsegs_Vector::iterator; 297 298 /** This is a wrapper for a std::vector of trx_rseg_t object pointers. */ 299 class Rsegs { 300 public: 301 /** Default constructor */ Rsegs()302 Rsegs() : m_rsegs(), m_latch(), m_state(INIT) { 303 #ifndef UNIV_HOTBACKUP 304 init(); 305 #endif /* !UNIV_HOTBACKUP */ 306 } 307 ~Rsegs()308 ~Rsegs() { 309 #ifndef UNIV_HOTBACKUP 310 deinit(); 311 #endif /* !UNIV_HOTBACKUP */ 312 } 313 314 /** Initialize */ 315 void init(); 316 317 /** De-initialize */ 318 void deinit(); 319 320 /** Clear the vector of cached rollback segments leaving the 321 reserved space allocated. */ 322 void clear(); 323 324 /** Add rollback segment. 325 @param[in] rseg rollback segment to add. */ push_back(trx_rseg_t * rseg)326 void push_back(trx_rseg_t *rseg) { m_rsegs.push_back(rseg); } 327 328 /** Number of registered rsegs. 329 @return size of rseg list. */ size()330 ulint size() { return (m_rsegs.size()); } 331 332 /** beginning iterator 333 @return an iterator to the first element */ begin()334 Rseg_Iterator begin() { return (m_rsegs.begin()); } 335 336 /** ending iterator 337 @return an iterator to the end */ end()338 Rseg_Iterator end() { return (m_rsegs.end()); } 339 340 /** Find the rseg at the given slot in this vector. 341 @param[in] slot a slot within the vector. 342 @return an iterator to the end */ at(ulint slot)343 trx_rseg_t *at(ulint slot) { return (m_rsegs.at(slot)); } 344 345 /** Find an rseg in the std::vector that uses the rseg_id given. 346 @param[in] rseg_id A slot in a durable array such as 347 the TRX_SYS page or RSEG_ARRAY page. 348 @return a pointer to an trx_rseg_t that uses the rseg_id. */ 349 trx_rseg_t *find(ulint rseg_id); 350 351 /** Sort the vector on trx_rseg_t::id */ sort()352 void sort() { 353 if (m_rsegs.empty()) { 354 return; 355 } 356 357 std::sort( 358 m_rsegs.begin(), m_rsegs.end(), 359 [](trx_rseg_t *lhs, trx_rseg_t *rhs) { return (rhs->id > lhs->id); }); 360 } 361 362 /** Get a shared lock on m_rsegs. */ s_lock()363 void s_lock() { rw_lock_s_lock(m_latch); } 364 365 /** Get a shared lock on m_rsegs. */ s_unlock()366 void s_unlock() { rw_lock_s_unlock(m_latch); } 367 368 /** Get a shared lock on m_rsegs. */ x_lock()369 void x_lock() { rw_lock_x_lock(m_latch); } 370 371 /** Get a shared lock on m_rsegs. */ x_unlock()372 void x_unlock() { rw_lock_x_unlock(m_latch); } 373 374 /** Return whether the undo tablespace is active. 375 @return true if active */ is_active()376 bool is_active() { return (m_state == ACTIVE); } 377 378 /** Return whether the undo tablespace is inactive due to 379 implicit selection by the purge thread. 380 @return true if marked for truncation by the purge thread */ is_inactive_implicit()381 bool is_inactive_implicit() { return (m_state == INACTIVE_IMPLICIT); } 382 383 /** Return whether the undo tablespace was made inactive by 384 ALTER TABLESPACE. 385 @return true if altered */ is_inactive_explicit()386 bool is_inactive_explicit() { return (m_state == INACTIVE_EXPLICIT); } 387 388 /** Return whether the undo tablespace is empty and ready 389 to be dropped. 390 @return true if empty */ is_empty()391 bool is_empty() { return (m_state == EMPTY); } 392 393 /** Return whether the undo tablespace is being initialized. 394 @return true if empty */ is_init()395 bool is_init() { return (m_state == INIT); } 396 397 /** Set the state of the rollback segments in this undo tablespace 398 to ACTIVE for use by new transactions. */ set_active()399 void set_active() { m_state = ACTIVE; } 400 401 /** Set the state of the rollback segments in this undo 402 tablespace to inactive_implicit. This means that it will be 403 truncated and then made active again by the purge thread. 404 It will not be used for new transactions until it becomes 405 active again. */ set_inactive_implicit()406 void set_inactive_implicit() { 407 ut_ad(m_state == ACTIVE || m_state == INACTIVE_EXPLICIT); 408 m_state = INACTIVE_IMPLICIT; 409 } 410 411 /** Make the undo tablespace inactive so that it will not be 412 used for new transactions. The purge thread will clear out 413 all the undo logs, truncate it, and then mark it empty. */ set_inactive_explicit()414 void set_inactive_explicit() { m_state = INACTIVE_EXPLICIT; } 415 416 /** Set the state of the undo tablespace to empty so that it 417 can be dropped. */ set_empty()418 void set_empty() { 419 ut_ad(m_state == INACTIVE_EXPLICIT || m_state == ACTIVE || 420 m_state == INIT || m_state == EMPTY); 421 m_state = EMPTY; 422 } 423 424 /** std::vector of rollback segments */ 425 Rsegs_Vector m_rsegs; 426 427 private: 428 /** RW lock to protect m_rsegs vector, m_active, and each 429 trx_rseg_t::trx_ref_count within it. 430 m_rsegs: x for adding elements, s for scanning, size etc. 431 m_active: x for modification, s for read 432 each trx_rseg_t::trx_ref_count within m_rsegs 433 s and atomic increment for modification, x for read */ 434 rw_lock_t *m_latch; 435 436 /* The four states of an undo tablespace. 437 INIT: The initial state of an undo space that is being created or opened. 438 ACTIVE: The rollback segments in this tablespace can be allocated to new 439 transactions. The undo tablespace is ready for undo logs. 440 INACTIVE_IMPLICIT: These rollback segments are no longer being used by new 441 transactions. They arre 'inactive'. The truncate process 442 is happening. This undo tablespace was selected by the 443 purge thread implicitly. When the truncation process 444 is complete, the next state is ACTIVE. 445 INACTIVE_EXPLICIT: These rollback segments are no longer being used by new 446 transactions. They arre 'inactive'. The truncate process 447 is happening. This undo tablespace was selected by the 448 an ALTER UNDO TABLESPACE SET INACTIVE command. When the 449 truncation process is complete, the next state is EMPTY. 450 EMPTY: The undo tablespace has been truncated but is no longer 451 active. It is ready to be either dropped or set active 452 explicitly. This state is also used when the undo tablespace and 453 its rollback segments are being inititalized. 454 455 These states are changed under an exclusive lock on m_latch and are read 456 under a shared lock. 457 458 The following actions can cause changes in these states: 459 Init: Implicit undo spaces are created at startup. 460 Create: Explicit undo tablespace creation at runtime. 461 Mark: Purge thread implicitly selects an undo space to truncate. 462 SetInactive: This ALTER UNDO TABLESPACE causes an explicit truncation. 463 SetActive: This ALTER UNDO TABLESPACE changes the target state from 464 EMPTY to ACTIVE. 465 Trucate: The truncate process is completed by the purge thread. 466 Drop: Delete an EMPTY undo tablespace 467 Crash: A crash occurs 468 Fixup: At startup, if an undo space was being truncated with a crash. 469 SaveDDState: At startup, once the DD is available the state saved there 470 will be applied. INACTIVE_IMPLICIT is never saved to the DD. 471 So the DD state INACTIVE means INACTIVE_EXPLICIT. 472 See apply_dd_undo_state() 473 474 State changes allowed: (Actions on states not mentioned are not allowed.) 475 Init from null -> INIT -> ACTIVE see srv_start() 476 from null -> INIT -> EMPTY see trx_rsegs_init() 477 Create from null -> EMPTY -> ACTIVE 478 Mark from INACTIVE_EXPLICIT -> INACTIVE_EXPLICIT -> Truncate 479 from ACTIVE -> INACTIVE_IMPLICIT -> Truncate 480 SetInactive from ACTIVE -> INACTIVE_EXPLICIT -> Mark 481 from INACTIVE_IMPLICIT -> INACTIVE_EXPLICIT 482 from INACTIVE_EXPLICIT -> INACTIVE_EXPLICIT 483 from EMPTY -> EMPTY 484 SetActive from ACTIVE -> ACTIVE 485 from INACTIVE_IMPLICIT -> INACTIVE_IMPLICIT 486 from INACTIVE_EXPLICIT -> INACTIVE_IMPLICIT 487 from EMPTY -> ACTIVE 488 Truncate from INACTIVE_IMPLICIT -> ACTIVE 489 from INACTIVE_EXPLICIT -> EMPTY 490 Drop if ACTIVE -> error returned 491 if INACTIVE_IMPLICIT -> error returned 492 if INACTIVE_EXPLICIT -> error returned 493 from EMPTY -> null 494 Crash if ACTIVE, at startup: ACTIVE 495 if INACTIVE_IMPLICIT, at startup: Fixup 496 if INACTIVE_EXPLICIT, at startup: Fixup 497 if EMPTY, at startup: EMPTY 498 Fixup from INACTIVE_IMPLICIT before crash -> INACTIVE_IMPLICIT -> Mark 499 from INACTIVE_EXPLICIT before crash -> INACTIVE_IMPLICIT -> Mark 500 SaveDDState from ACTIVE before crash -> ACTIVE 501 from INACTIVE_IMPLICIT before crash -> ACTIVE 502 from INACTIVE_EXPLICIT before crash -> INACTIVE_EXPLICIT -> Mark 503 from EMPTY -> EMPTY 504 */ 505 enum undo_space_states { 506 INIT, 507 ACTIVE, 508 INACTIVE_IMPLICIT, 509 INACTIVE_EXPLICIT, 510 EMPTY 511 }; 512 513 /** The current state of this undo tablespace. */ 514 undo_space_states m_state; 515 }; 516 517 /** Rollback segements from a given transaction with trx-no 518 scheduled for purge. */ 519 class TrxUndoRsegs { 520 public: 521 /** Default constructor */ TrxUndoRsegs()522 TrxUndoRsegs() : m_trx_no() {} 523 TrxUndoRsegs(trx_id_t trx_no)524 explicit TrxUndoRsegs(trx_id_t trx_no) : m_trx_no(trx_no) { 525 // Do nothing 526 } 527 528 /** Get transaction number 529 @return trx_id_t - get transaction number. */ get_trx_no()530 trx_id_t get_trx_no() const { return (m_trx_no); } 531 532 /** Add rollback segment. 533 @param rseg rollback segment to add. */ push_back(trx_rseg_t * rseg)534 void push_back(trx_rseg_t *rseg) { m_rsegs.push_back(rseg); } 535 536 /** Erase the element pointed by given iterator. 537 @param[in] it iterator */ erase(Rseg_Iterator & it)538 void erase(Rseg_Iterator &it) { m_rsegs.erase(it); } 539 540 /** Number of registered rsegs. 541 @return size of rseg list. */ size()542 ulint size() const { return (m_rsegs.size()); } 543 544 /** 545 @return an iterator to the first element */ begin()546 Rseg_Iterator begin() { return (m_rsegs.begin()); } 547 548 /** 549 @return an iterator to the end */ end()550 Rseg_Iterator end() { return (m_rsegs.end()); } 551 552 /** Append rollback segments from referred instance to current 553 instance. */ append(const TrxUndoRsegs & append_from)554 void append(const TrxUndoRsegs &append_from) { 555 ut_ad(get_trx_no() == append_from.get_trx_no()); 556 557 m_rsegs.insert(m_rsegs.end(), append_from.m_rsegs.begin(), 558 append_from.m_rsegs.end()); 559 } 560 561 /** Compare two TrxUndoRsegs based on trx_no. 562 @param lhs first element to compare 563 @param rhs second element to compare 564 @return true if elem1 > elem2 else false.*/ operator()565 bool operator()(const TrxUndoRsegs &lhs, const TrxUndoRsegs &rhs) { 566 return (lhs.m_trx_no > rhs.m_trx_no); 567 } 568 569 /** Compiler defined copy-constructor/assignment operator 570 should be fine given that there is no reference to a memory 571 object outside scope of class object.*/ 572 573 private: 574 /** The rollback segments transaction number. */ 575 trx_id_t m_trx_no; 576 577 /** Rollback segments of a transaction, scheduled for purge. */ 578 Rsegs_Vector m_rsegs; 579 }; 580 581 typedef std::priority_queue< 582 TrxUndoRsegs, std::vector<TrxUndoRsegs, ut_allocator<TrxUndoRsegs>>, 583 TrxUndoRsegs> 584 purge_pq_t; 585 586 typedef std::vector<trx_id_t, ut_allocator<trx_id_t>> trx_ids_t; 587 588 /** Mapping read-write transactions from id to transaction instance, for 589 creating read views and during trx id lookup for MVCC and locking. */ 590 struct TrxTrack { m_idTrxTrack591 explicit TrxTrack(trx_id_t id, trx_t *trx = nullptr) : m_id(id), m_trx(trx) { 592 // Do nothing 593 } 594 595 trx_id_t m_id; 596 trx_t *m_trx; 597 }; 598 599 struct TrxTrackHash { operatorTrxTrackHash600 size_t operator()(const TrxTrack &key) const { return (size_t(key.m_id)); } 601 }; 602 603 /** 604 Comparator for TrxMap */ 605 struct TrxTrackHashCmp { operatorTrxTrackHashCmp606 bool operator()(const TrxTrack &lhs, const TrxTrack &rhs) const { 607 return (lhs.m_id == rhs.m_id); 608 } 609 }; 610 611 /** 612 Comparator for TrxMap */ 613 struct TrxTrackCmp { operatorTrxTrackCmp614 bool operator()(const TrxTrack &lhs, const TrxTrack &rhs) const { 615 return (lhs.m_id < rhs.m_id); 616 } 617 }; 618 619 // typedef std::unordered_set<TrxTrack, TrxTrackHash, TrxTrackHashCmp> TrxIdSet; 620 typedef std::set<TrxTrack, TrxTrackCmp, ut_allocator<TrxTrack>> TrxIdSet; 621 622 struct TrxVersion { 623 TrxVersion(trx_t *trx); 624 625 trx_t *m_trx; 626 ulint m_version; 627 }; 628 629 typedef std::vector<TrxVersion, ut_allocator<TrxVersion>> hit_list_t; 630 #endif /* trx0types_h */ 631