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