@@ -340,14 +340,6 @@ struct rw_trx_hash_element_t
340340
341341
342342 trx_id_t id; /* lf_hash_init() relies on this to be first in the struct */
343-
344- /* *
345- Transaction serialization number.
346-
347- Assigned shortly before the transaction is moved to COMMITTED_IN_MEMORY
348- state. Initially set to TRX_ID_MAX.
349- */
350- Atomic_counter<trx_id_t > no;
351343 trx_t *trx;
352344 srw_mutex mutex;
353345};
@@ -443,7 +435,6 @@ class rw_trx_hash_t
443435 ut_ad (element->trx == 0 );
444436 element->trx = trx;
445437 element->id = trx->id ;
446- element->no = TRX_ID_MAX;
447438 trx->rw_trx_hash_element = element;
448439 }
449440
@@ -512,7 +503,6 @@ class rw_trx_hash_t
512503 if (element->trx )
513504 validate_element (element->trx );
514505 element->mutex .wr_unlock ();
515- ut_ad (element->id < element->no );
516506 return arg->action (element, arg->argument );
517507 }
518508#endif
@@ -849,6 +839,108 @@ class thread_safe_trx_ilist_t
849839 alignas (CPU_LEVEL1_DCACHE_LINESIZE) ilist<trx_t > trx_list;
850840};
851841
842+ class rw_trx_vector
843+ {
844+ struct rw_trx_id
845+ {
846+ Atomic_relaxed<trx_id_t > id{TRX_ID_MAX};
847+ Atomic_relaxed<trx_id_t > no{TRX_ID_MAX};
848+ trx_t *trx;
849+ rw_trx_id (trx_t *t): trx(t) {}
850+ };
851+ std::vector<rw_trx_id, ut_allocator<rw_trx_id>>
852+ ids{ut_allocator<rw_trx_id>(mem_key_trx_sys_t_rw_trx_ids)};
853+ mutable srw_spin_lock latch;
854+
855+ public:
856+ void assign_new_trx_no (const trx_t *trx) noexcept
857+ {
858+ ut_ad (trx->rw_trx_ids_slot != std::numeric_limits<uint32_t >::max ());
859+ ut_ad (trx->id < trx->no );
860+ latch.rd_lock (SRW_LOCK_CALL);
861+ ut_ad (ids[trx->rw_trx_ids_slot ].id == trx->id );
862+ ut_ad (ids[trx->rw_trx_ids_slot ].no == TRX_ID_MAX);
863+ ids[trx->rw_trx_ids_slot ].no = trx->no ;
864+ latch.rd_unlock ();
865+ }
866+ trx_id_t snapshot_ids (trx_ids_t &view_ids,
867+ const trx_id_t max_trx_id) const noexcept
868+ {
869+ trx_id_t min_trx_no{max_trx_id};
870+ view_ids.clear ();
871+ latch.rd_lock (SRW_LOCK_CALL);
872+ view_ids.reserve (ids.size ());
873+ for (const auto &it : ids)
874+ {
875+ trx_id_t id{it.id };
876+ if (id < max_trx_id)
877+ {
878+ view_ids.push_back (id);
879+ const trx_id_t no{it.no };
880+ if (no < min_trx_no)
881+ min_trx_no= no;
882+ }
883+ }
884+ latch.rd_unlock ();
885+ return min_trx_no;
886+ }
887+ void register_rw (const trx_t *trx) noexcept
888+ {
889+ ut_ad (trx->rw_trx_ids_slot != std::numeric_limits<uint32_t >::max ());
890+ ut_ad (trx->no == TRX_ID_MAX);
891+ latch.rd_lock (SRW_LOCK_CALL);
892+ ut_ad (ids[trx->rw_trx_ids_slot ].id == TRX_ID_MAX);
893+ ut_ad (ids[trx->rw_trx_ids_slot ].no == TRX_ID_MAX);
894+ ids[trx->rw_trx_ids_slot ].id = trx->id ;
895+ latch.rd_unlock ();
896+ }
897+ void deregister_rw (const trx_t *trx) noexcept
898+ {
899+ ut_ad (trx->rw_trx_ids_slot != std::numeric_limits<uint32_t >::max ());
900+ latch.rd_lock (SRW_LOCK_CALL);
901+ ut_ad (ids[trx->rw_trx_ids_slot ].id != TRX_ID_MAX);
902+ ut_ad (ids[trx->rw_trx_ids_slot ].id == trx->id );
903+ ut_ad (ids[trx->rw_trx_ids_slot ].no == trx->no );
904+ ids[trx->rw_trx_ids_slot ].id = TRX_ID_MAX;
905+ ids[trx->rw_trx_ids_slot ].no = TRX_ID_MAX;
906+ latch.rd_unlock ();
907+ }
908+ void register_trx (trx_t *trx) noexcept
909+ {
910+ ut_ad (trx->rw_trx_ids_slot == std::numeric_limits<uint32_t >::max ());
911+ ut_ad (trx->no == TRX_ID_MAX);
912+ latch.wr_lock (SRW_LOCK_CALL);
913+ trx->rw_trx_ids_slot = static_cast <uint32_t >(ids.size ());
914+ ids.emplace_back (trx);
915+ latch.wr_unlock ();
916+ }
917+ void deregister_trx (trx_t *trx) noexcept
918+ {
919+ ut_ad (trx->rw_trx_ids_slot != std::numeric_limits<uint32_t >::max ());
920+ ut_ad (trx->no == TRX_ID_MAX);
921+ latch.wr_lock (SRW_LOCK_CALL);
922+ if (trx->rw_trx_ids_slot + 1 < ids.size ())
923+ {
924+ trx_t *move_trx= ids.back ().trx ;
925+ ids[trx->rw_trx_ids_slot ]= std::move (ids.back ());
926+ move_trx->rw_trx_ids_slot = trx->rw_trx_ids_slot ;
927+ }
928+ ids.pop_back ();
929+ latch.wr_unlock ();
930+ trx->rw_trx_ids_slot = std::numeric_limits<uint32_t >::max ();
931+ }
932+ void create () noexcept
933+ {
934+ ut_ad (ids.size () == 0 );
935+ latch.SRW_LOCK_INIT (rw_trx_ids_latch_key);
936+ }
937+ void destroy () noexcept
938+ {
939+ ut_ad (ids.size () == 0 );
940+ latch.destroy ();
941+ }
942+ };
943+
852944/* * The transaction system central memory data structure. */
853945class trx_sys_t
854946{
@@ -876,6 +968,8 @@ class trx_sys_t
876968 /* * False if there is no undo log to purge or rollback */
877969 bool undo_log_nonempty;
878970public:
971+ rw_trx_vector rw_trx_ids;
972+
879973 /* * List of all transactions. */
880974 thread_safe_trx_ilist_t trx_list;
881975
@@ -1014,7 +1108,7 @@ class trx_sys_t
10141108 next call to trx_sys.get_new_trx_id()
10151109 */
10161110
1017- trx_id_t get_max_trx_id ()
1111+ trx_id_t get_max_trx_id () const noexcept
10181112 {
10191113 return m_max_trx_id;
10201114 }
@@ -1057,17 +1151,15 @@ class trx_sys_t
10571151 */
10581152 void assign_new_trx_no (trx_t *trx)
10591153 {
1060- trx->rw_trx_hash_element ->no = get_new_trx_id_no_refresh ();
1154+ trx->no = get_new_trx_id_no_refresh ();
1155+ rw_trx_ids.assign_new_trx_no (trx);
10611156 refresh_rw_trx_hash_version ();
10621157 }
10631158
10641159
10651160 /* *
10661161 Takes MVCC snapshot.
10671162
1068- To reduce malloc probability we reserve rw_trx_hash.size() + 32 elements
1069- in ids.
1070-
10711163 For details about get_rw_trx_hash_version() != get_max_trx_id() spin
10721164 @sa register_rw() and @sa assign_new_trx_no().
10731165
@@ -1078,27 +1170,18 @@ class trx_sys_t
10781170 of rw_trx_hash.iterate_no_dups(). It means that some transaction
10791171 identifiers may appear multiple times in ids.
10801172
1081- @param[in,out] caller_trx used to get access to rw_trx_hash_pins
10821173 @param[out] ids array to store registered transaction identifiers
10831174 @param[out] max_trx_id variable to store m_max_trx_id value
1084- @param[out] mix_trx_no variable to store min(no) value
1175+
1176+ @return min(no)
10851177 */
10861178
1087- void snapshot_ids (trx_t *caller_trx, trx_ids_t *ids, trx_id_t *max_trx_id,
1088- trx_id_t *min_trx_no)
1179+ trx_id_t snapshot_ids (trx_ids_t &ids, trx_id_t &max_trx_id) const noexcept
10891180 {
1090- snapshot_ids_arg arg (ids);
1091-
1092- while ((arg.m_id = get_rw_trx_hash_version ()) != get_max_trx_id ())
1181+ while ((max_trx_id= get_rw_trx_hash_version ()) != get_max_trx_id ())
10931182 ut_delay (1 );
1094- arg.m_no = arg.m_id ;
1095-
1096- ids->clear ();
1097- ids->reserve (rw_trx_hash.size () + 32 );
1098- rw_trx_hash.iterate(caller_trx, copy_one_id, &arg);
10991183
1100- *max_trx_id= arg.m_id ;
1101- *min_trx_no= arg.m_no ;
1184+ return rw_trx_ids.snapshot_ids (ids, max_trx_id);
11021185 }
11031186
11041187
@@ -1166,8 +1249,9 @@ class trx_sys_t
11661249 void register_rw (trx_t *trx)
11671250 {
11681251 trx->id = get_new_trx_id_no_refresh ();
1169- rw_trx_hash. insert (trx);
1252+ rw_trx_ids. register_rw (trx);
11701253 refresh_rw_trx_hash_version ();
1254+ rw_trx_hash.insert (trx);
11711255 }
11721256
11731257
@@ -1178,9 +1262,11 @@ class trx_sys_t
11781262 MVCC snapshot won't see this transaction anymore.
11791263 */
11801264
1181- void deregister_rw (trx_t *trx)
1265+ void deregister_rw (trx_t *trx) noexcept
11821266 {
1267+ rw_trx_ids.deregister_rw (trx);
11831268 rw_trx_hash.erase (trx);
1269+ trx->no = TRX_ID_MAX;
11841270 }
11851271
11861272
@@ -1204,6 +1290,7 @@ class trx_sys_t
12041290 void register_trx (trx_t *trx)
12051291 {
12061292 trx_list.push_front (*trx);
1293+ rw_trx_ids.register_trx (trx);
12071294 }
12081295
12091296
@@ -1214,6 +1301,7 @@ class trx_sys_t
12141301 */
12151302 void deregister_trx (trx_t *trx)
12161303 {
1304+ rw_trx_ids.deregister_trx (trx);
12171305 trx_list.remove (*trx);
12181306 }
12191307
@@ -1266,33 +1354,8 @@ class trx_sys_t
12661354private:
12671355 static my_bool find_same_or_older_callback (void *el, void *i) noexcept ;
12681356
1269-
1270- struct snapshot_ids_arg
1271- {
1272- snapshot_ids_arg (trx_ids_t *ids): m_ids(ids) {}
1273- trx_ids_t *m_ids;
1274- trx_id_t m_id;
1275- trx_id_t m_no;
1276- };
1277-
1278-
1279- static my_bool copy_one_id (void * el, void *a)
1280- {
1281- auto element= static_cast <const rw_trx_hash_element_t *>(el);
1282- auto arg= static_cast <snapshot_ids_arg*>(a);
1283- if (element->id < arg->m_id )
1284- {
1285- trx_id_t no= element->no ;
1286- arg->m_ids ->push_back (element->id );
1287- if (no < arg->m_no )
1288- arg->m_no = no;
1289- }
1290- return 0 ;
1291- }
1292-
1293-
12941357 /* * Getter for m_rw_trx_hash_version, must issue ACQUIRE memory barrier. */
1295- trx_id_t get_rw_trx_hash_version ()
1358+ trx_id_t get_rw_trx_hash_version () const noexcept
12961359 {
12971360 return m_rw_trx_hash_version.load (std::memory_order_acquire);
12981361 }
0 commit comments