Commit c484a358 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-26864 Race condition between transaction commit and undo log truncation

trx_commit_in_memory(): Do not release the rseg reference before
trx_undo_commit_cleanup() has been invoked and the current transaction
is truly done with the rollback segment. The purpose of the reference
count is to prevent data races with trx_purge_truncate_history().

This is based on
mysql/mysql-server@ac79aa1522f33e6eb912133a81fa2614db764c9c.
parent 8ce8c269
...@@ -1775,12 +1775,7 @@ trx_commit_in_memory( ...@@ -1775,12 +1775,7 @@ trx_commit_in_memory(
ut_ad(!trx->rsegs.m_redo.update_undo); ut_ad(!trx->rsegs.m_redo.update_undo);
if (trx_rseg_t* rseg = trx->rsegs.m_redo.rseg) { if (ut_d(trx_rseg_t* rseg =) trx->rsegs.m_redo.rseg) {
mutex_enter(&rseg->mutex);
ut_ad(rseg->trx_ref_count > 0);
--rseg->trx_ref_count;
mutex_exit(&rseg->mutex);
if (trx_undo_t*& insert = trx->rsegs.m_redo.insert_undo) { if (trx_undo_t*& insert = trx->rsegs.m_redo.insert_undo) {
ut_ad(insert->rseg == rseg); ut_ad(insert->rseg == rseg);
trx_undo_commit_cleanup(insert, false); trx_undo_commit_cleanup(insert, false);
...@@ -1849,6 +1844,15 @@ trx_commit_in_memory( ...@@ -1849,6 +1844,15 @@ trx_commit_in_memory(
ut_ad(!trx->rsegs.m_noredo.undo); ut_ad(!trx->rsegs.m_noredo.undo);
/* Only after trx_undo_commit_cleanup() it is safe to release
our rseg reference. */
if (trx_rseg_t* rseg = trx->rsegs.m_redo.rseg) {
mutex_enter(&rseg->mutex);
ut_ad(rseg->trx_ref_count > 0);
--rseg->trx_ref_count;
mutex_exit(&rseg->mutex);
}
/* Free all savepoints, starting from the first. */ /* Free all savepoints, starting from the first. */
trx_named_savept_t* savep = UT_LIST_GET_FIRST(trx->trx_savepoints); trx_named_savept_t* savep = UT_LIST_GET_FIRST(trx->trx_savepoints);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment