@@ -969,93 +969,50 @@ trx_start_low(
969
969
ut_a (trx->error_state == DB_SUCCESS);
970
970
}
971
971
972
- /* * Set the serialisation number for a persistent committed transaction.
973
- @param[in,out] trx committed transaction with persistent changes */
974
- static
975
- void
976
- trx_serialise (trx_t * trx)
977
- {
978
- trx_rseg_t *rseg = trx->rsegs .m_redo .rseg ;
979
- ut_ad (rseg);
980
-
981
- if (rseg->last_page_no == FIL_NULL) {
982
- mysql_mutex_lock (&purge_sys.pq_mutex );
983
- }
984
-
985
- trx_sys.assign_new_trx_no (trx);
986
-
987
- /* If the rollback segment is not empty then the
988
- new trx_t::no can't be less than any trx_t::no
989
- already in the rollback segment. User threads only
990
- produce events when a rollback segment is empty. */
991
- if (rseg->last_page_no == FIL_NULL) {
992
- purge_sys.purge_queue .push (TrxUndoRsegs (trx->rw_trx_hash_element ->no ,
993
- *rseg));
994
- mysql_mutex_unlock (&purge_sys.pq_mutex );
995
- }
996
- }
997
-
998
- /* ***************************************************************/ /* *
999
- Assign the transaction its history serialisation number and write the
1000
- update UNDO log record to the assigned rollback segment. */
1001
- static
1002
- void
1003
- trx_write_serialisation_history (
1004
- /* ============================*/
1005
- trx_t * trx, /* !< in/out: transaction */
1006
- mtr_t * mtr) /* !< in/out: mini-transaction */
972
+ /* * Assign the transaction its history serialisation number and write the
973
+ UNDO log to the assigned rollback segment.
974
+ @param trx persistent transaction
975
+ @param mtr mini-transaction */
976
+ static void trx_write_serialisation_history (trx_t *trx, mtr_t *mtr)
1007
977
{
1008
- /* Change the undo log segment states from TRX_UNDO_ACTIVE to some
1009
- other state: these modifications to the file data structure define
1010
- the transaction as committed in the file based domain, at the
1011
- serialization point of the log sequence number lsn obtained below. */
1012
-
1013
- /* We have to hold the rseg mutex because update log headers have
1014
- to be put to the history list in the (serialisation) order of the
1015
- UNDO trx number. This is required for the purge in-memory data
1016
- structures too. */
1017
-
1018
- if (trx_undo_t * undo = trx->rsegs .m_noredo .undo ) {
1019
- /* Undo log for temporary tables is discarded at transaction
1020
- commit. There is no purge for temporary tables, and also no
1021
- MVCC, because they are private to a session. */
1022
-
1023
- mtr_t temp_mtr;
1024
- temp_mtr.start ();
1025
- temp_mtr.set_log_mode (MTR_LOG_NO_REDO);
1026
- buf_block_t * block= buf_page_get (page_id_t (SRV_TMP_SPACE_ID,
1027
- undo->hdr_page_no ),
1028
- 0 , RW_X_LATCH, mtr);
1029
- ut_a (block);
1030
- temp_mtr.write <2 >(*block, TRX_UNDO_SEG_HDR + TRX_UNDO_STATE
1031
- + block->page .frame , TRX_UNDO_TO_PURGE);
1032
- undo->state = TRX_UNDO_TO_PURGE;
1033
- temp_mtr.commit ();
1034
- }
1035
-
1036
- trx_rseg_t * rseg = trx->rsegs .m_redo .rseg ;
1037
- if (!rseg) {
1038
- ut_ad (!trx->rsegs .m_redo .undo );
1039
- return ;
1040
- }
1041
-
1042
- trx_undo_t *& undo = trx->rsegs .m_redo .undo ;
1043
-
1044
- ut_ad (!trx->read_only );
1045
-
1046
- /* Assign the transaction serialisation number and add any
1047
- undo log to the purge queue. */
1048
- if (undo) {
1049
- rseg->latch .wr_lock (SRW_LOCK_CALL);
1050
- ut_ad (undo->rseg == rseg);
1051
- trx_serialise (trx);
1052
- UT_LIST_REMOVE (rseg->undo_list , undo);
1053
- trx_purge_add_undo_to_history (trx, undo, mtr);
1054
- MONITOR_INC (MONITOR_TRX_COMMIT_UNDO);
1055
- rseg->latch .wr_unlock ();
1056
- }
1057
-
1058
- rseg->release ();
978
+ ut_ad (!trx->read_only );
979
+ trx_rseg_t *rseg= trx->rsegs .m_redo .rseg ;
980
+ trx_undo_t *&undo= trx->rsegs .m_redo .undo ;
981
+ if (UNIV_LIKELY (undo != nullptr ))
982
+ {
983
+ MONITOR_INC (MONITOR_TRX_COMMIT_UNDO);
984
+
985
+ /* We have to hold exclusive rseg->latch because undo log headers have
986
+ to be put to the history list in the (serialisation) order of the
987
+ UNDO trx number. This is required for purge_sys too. */
988
+ rseg->latch .wr_lock (SRW_LOCK_CALL);
989
+ ut_ad (undo->rseg == rseg);
990
+ /* Assign the transaction serialisation number and add any
991
+ undo log to the purge queue. */
992
+ if (rseg->last_page_no == FIL_NULL)
993
+ {
994
+ mysql_mutex_lock (&purge_sys.pq_mutex );
995
+ trx_sys.assign_new_trx_no (trx);
996
+ /* If the rollback segment is not empty, trx->no cannot be less
997
+ than any trx_t::no already in rseg. User threads only produce
998
+ events when a rollback segment is empty. */
999
+ purge_sys.purge_queue .push (TrxUndoRsegs (trx->rw_trx_hash_element ->no ,
1000
+ *rseg));
1001
+ mysql_mutex_unlock (&purge_sys.pq_mutex );
1002
+ }
1003
+ else
1004
+ trx_sys.assign_new_trx_no (trx);
1005
+ UT_LIST_REMOVE (rseg->undo_list , undo);
1006
+ /* Change the undo log segment state from TRX_UNDO_ACTIVE, to
1007
+ define the transaction as committed in the file based domain,
1008
+ at mtr->commit_lsn() obtained in mtr->commit() below. */
1009
+ trx_purge_add_undo_to_history (trx, undo, mtr);
1010
+ rseg->release ();
1011
+ rseg->latch .wr_unlock ();
1012
+ }
1013
+ else
1014
+ rseg->release ();
1015
+ mtr->commit ();
1059
1016
}
1060
1017
1061
1018
/* *******************************************************************
@@ -1229,6 +1186,55 @@ void trx_t::evict_table(table_id_t table_id, bool reset_only)
1229
1186
}
1230
1187
}
1231
1188
1189
+ /* * Free temporary undo log after commit or rollback.
1190
+ @param undo temporary undo log */
1191
+ ATTRIBUTE_NOINLINE static void trx_commit_cleanup (trx_undo_t *&undo)
1192
+ {
1193
+ trx_rseg_t *const rseg= undo->rseg ;
1194
+ ut_ad (rseg->space == fil_system.temp_space );
1195
+ rseg->latch .wr_lock (SRW_LOCK_CALL);
1196
+ UT_LIST_REMOVE (rseg->undo_list , undo);
1197
+ ut_ad (undo->state == TRX_UNDO_ACTIVE || undo->state == TRX_UNDO_PREPARED);
1198
+ ut_ad (undo->id < TRX_RSEG_N_SLOTS);
1199
+ /* Delete first the undo log segment in the file */
1200
+ bool finished;
1201
+ mtr_t mtr;
1202
+ do
1203
+ {
1204
+ mtr.start ();
1205
+ mtr.set_log_mode (MTR_LOG_NO_REDO);
1206
+
1207
+ finished= true ;
1208
+
1209
+ if (buf_block_t *block=
1210
+ buf_page_get (page_id_t (SRV_TMP_SPACE_ID, undo->hdr_page_no ), 0 ,
1211
+ RW_X_LATCH, &mtr))
1212
+ {
1213
+ fseg_header_t *file_seg= TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER +
1214
+ block->page .frame ;
1215
+
1216
+ finished= fseg_free_step (file_seg, &mtr);
1217
+
1218
+ if (!finished);
1219
+ else if (buf_block_t *rseg_header= rseg->get (&mtr, nullptr ))
1220
+ {
1221
+ static_assert (FIL_NULL == 0xffffffff , " compatibility" );
1222
+ memset (rseg_header->page .frame + TRX_RSEG + TRX_RSEG_UNDO_SLOTS +
1223
+ undo->id * TRX_RSEG_SLOT_SIZE, 0xff , 4 );
1224
+ }
1225
+ }
1226
+
1227
+ mtr.commit ();
1228
+ }
1229
+ while (!finished);
1230
+
1231
+ ut_ad (rseg->curr_size > undo->size );
1232
+ rseg->curr_size -= undo->size ;
1233
+ rseg->latch .wr_unlock ();
1234
+ ut_free (undo);
1235
+ undo= nullptr ;
1236
+ }
1237
+
1232
1238
TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory (const mtr_t *mtr)
1233
1239
{
1234
1240
/* We already detached from rseg in trx_write_serialisation_history() */
@@ -1300,15 +1306,14 @@ TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory(const mtr_t *mtr)
1300
1306
release_locks ();
1301
1307
}
1302
1308
1303
- if (mtr )
1309
+ if (trx_undo_t *&undo= rsegs. m_noredo . undo )
1304
1310
{
1305
- if (trx_undo_t *&undo= rsegs.m_noredo .undo )
1306
- {
1307
- ut_ad (undo->rseg == rsegs.m_noredo .rseg );
1308
- trx_undo_commit_cleanup (undo);
1309
- undo= nullptr ;
1310
- }
1311
+ ut_ad (undo->rseg == rsegs.m_noredo .rseg );
1312
+ trx_commit_cleanup (undo);
1313
+ }
1311
1314
1315
+ if (mtr)
1316
+ {
1312
1317
/* NOTE that we could possibly make a group commit more efficient
1313
1318
here: call std::this_thread::yield() here to allow also other trxs to come
1314
1319
to commit! */
@@ -1346,8 +1351,6 @@ TRANSACTIONAL_INLINE inline void trx_t::commit_in_memory(const mtr_t *mtr)
1346
1351
trx_flush_log_if_needed (commit_lsn, this );
1347
1352
}
1348
1353
1349
- ut_ad (!rsegs.m_noredo .undo );
1350
-
1351
1354
savepoints_discard ();
1352
1355
1353
1356
if (fts_trx)
@@ -1390,7 +1393,7 @@ TRANSACTIONAL_TARGET void trx_t::commit_low(mtr_t *mtr)
1390
1393
{
1391
1394
ut_ad (!mtr || mtr->is_active ());
1392
1395
ut_d (bool aborted= in_rollback && error_state == DB_DEADLOCK);
1393
- ut_ad (!mtr == (aborted || !has_logged ()));
1396
+ ut_ad (!mtr == (aborted || !has_logged_persistent ()));
1394
1397
ut_ad (!mtr || !aborted);
1395
1398
1396
1399
if (fts_trx && undo_no)
@@ -1416,24 +1419,19 @@ TRANSACTIONAL_TARGET void trx_t::commit_low(mtr_t *mtr)
1416
1419
{
1417
1420
if (UNIV_UNLIKELY (apply_online_log))
1418
1421
apply_log ();
1419
- trx_write_serialisation_history (this , mtr);
1420
1422
1421
1423
/* The following call commits the mini-transaction, making the
1422
1424
whole transaction committed in the file-based world, at this log
1423
1425
sequence number. The transaction becomes 'durable' when we write
1424
1426
the log to disk, but in the logical sense the commit in the
1425
1427
file-based data structures (undo logs etc.) happens here.
1426
1428
1427
- NOTE that transaction numbers, which are assigned only to
1428
- transactions with an update undo log, do not necessarily come in
1429
+ NOTE that transaction numbers do not necessarily come in
1429
1430
exactly the same order as commit lsn's, if the transactions have
1430
- different rollback segments. To get exactly the same order we
1431
- should hold the kernel mutex up to this point, adding to the
1432
- contention of the kernel mutex. However, if a transaction T2 is
1431
+ different rollback segments. However, if a transaction T2 is
1433
1432
able to see modifications made by a transaction T1, T2 will always
1434
1433
get a bigger transaction number and a bigger commit lsn than T1. */
1435
-
1436
- mtr->commit ();
1434
+ trx_write_serialisation_history (this , mtr);
1437
1435
}
1438
1436
else if (trx_rseg_t *rseg= rsegs.m_redo .rseg )
1439
1437
{
@@ -1456,7 +1454,7 @@ void trx_t::commit_persist()
1456
1454
mtr_t *mtr= nullptr ;
1457
1455
mtr_t local_mtr;
1458
1456
1459
- if (has_logged ())
1457
+ if (has_logged_persistent ())
1460
1458
{
1461
1459
mtr= &local_mtr;
1462
1460
local_mtr.start ();
0 commit comments