Commit 06ef5509 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-24167: Replace trx_purge_latch

parent 63dd2a97
...@@ -12,7 +12,6 @@ wait/synch/sxlock/innodb/fil_space_latch ...@@ -12,7 +12,6 @@ wait/synch/sxlock/innodb/fil_space_latch
wait/synch/sxlock/innodb/fts_cache_init_rw_lock wait/synch/sxlock/innodb/fts_cache_init_rw_lock
wait/synch/sxlock/innodb/fts_cache_rw_lock wait/synch/sxlock/innodb/fts_cache_rw_lock
wait/synch/sxlock/innodb/index_tree_rw_lock wait/synch/sxlock/innodb/index_tree_rw_lock
wait/synch/sxlock/innodb/trx_purge_latch
select name from performance_schema.rwlock_instances select name from performance_schema.rwlock_instances
where name in where name in
( (
...@@ -25,7 +24,6 @@ where name in ...@@ -25,7 +24,6 @@ where name in
order by name; order by name;
name name
wait/synch/sxlock/innodb/dict_operation_lock wait/synch/sxlock/innodb/dict_operation_lock
wait/synch/sxlock/innodb/trx_purge_latch
drop table if exists t1; drop table if exists t1;
create table t1(a int) engine=innodb; create table t1(a int) engine=innodb;
begin; begin;
......
...@@ -569,7 +569,7 @@ static PSI_rwlock_info all_innodb_rwlocks[] = { ...@@ -569,7 +569,7 @@ static PSI_rwlock_info all_innodb_rwlocks[] = {
PSI_RWLOCK_KEY(fts_cache_rw_lock), PSI_RWLOCK_KEY(fts_cache_rw_lock),
PSI_RWLOCK_KEY(fts_cache_init_rw_lock), PSI_RWLOCK_KEY(fts_cache_init_rw_lock),
{ &trx_i_s_cache_lock_key, "trx_i_s_cache_lock", 0 }, { &trx_i_s_cache_lock_key, "trx_i_s_cache_lock", 0 },
PSI_RWLOCK_KEY(trx_purge_latch), { &trx_purge_latch_key, "trx_purge_latch", 0 },
PSI_RWLOCK_KEY(index_tree_rw_lock), PSI_RWLOCK_KEY(index_tree_rw_lock),
}; };
# endif /* UNIV_PFS_RWLOCK */ # endif /* UNIV_PFS_RWLOCK */
......
...@@ -224,7 +224,6 @@ enum latch_level_t { ...@@ -224,7 +224,6 @@ enum latch_level_t {
SYNC_RSEG_HEADER_NEW, SYNC_RSEG_HEADER_NEW,
SYNC_NOREDO_RSEG, SYNC_NOREDO_RSEG,
SYNC_REDO_RSEG, SYNC_REDO_RSEG,
SYNC_PURGE_LATCH,
SYNC_TREE_NODE, SYNC_TREE_NODE,
SYNC_TREE_NODE_FROM_HASH, SYNC_TREE_NODE_FROM_HASH,
SYNC_TREE_NODE_NEW, SYNC_TREE_NODE_NEW,
...@@ -296,7 +295,6 @@ enum latch_id_t { ...@@ -296,7 +295,6 @@ enum latch_id_t {
LATCH_ID_FIL_SPACE, LATCH_ID_FIL_SPACE,
LATCH_ID_FTS_CACHE, LATCH_ID_FTS_CACHE,
LATCH_ID_FTS_CACHE_INIT, LATCH_ID_FTS_CACHE_INIT,
LATCH_ID_TRX_PURGE,
LATCH_ID_IBUF_INDEX_TREE, LATCH_ID_IBUF_INDEX_TREE,
LATCH_ID_INDEX_TREE, LATCH_ID_INDEX_TREE,
LATCH_ID_DICT_TABLE_STATS, LATCH_ID_DICT_TABLE_STATS,
......
...@@ -29,6 +29,7 @@ Created 3/26/1996 Heikki Tuuri ...@@ -29,6 +29,7 @@ Created 3/26/1996 Heikki Tuuri
#include "trx0rseg.h" #include "trx0rseg.h"
#include "que0types.h" #include "que0types.h"
#include "srw_lock.h"
#include <queue> #include <queue>
...@@ -127,11 +128,9 @@ class purge_sys_t ...@@ -127,11 +128,9 @@ class purge_sys_t
{ {
public: public:
/** latch protecting view, m_enabled */ /** latch protecting view, m_enabled */
MY_ALIGNED(CACHE_LINE_SIZE) MY_ALIGNED(CACHE_LINE_SIZE) mutable srw_lock latch;
mutable rw_lock_t latch;
private: private:
/** The purge will not remove undo logs which are >= this view */ /** The purge will not remove undo logs which are >= this view */
MY_ALIGNED(CACHE_LINE_SIZE)
ReadViewBase view; ReadViewBase view;
/** whether purge is enabled; protected by latch and std::atomic */ /** whether purge is enabled; protected by latch and std::atomic */
std::atomic<bool> m_enabled; std::atomic<bool> m_enabled;
...@@ -249,23 +248,20 @@ class purge_sys_t ...@@ -249,23 +248,20 @@ class purge_sys_t
/** A wrapper around ReadView::changes_visible(). */ /** A wrapper around ReadView::changes_visible(). */
bool changes_visible(trx_id_t id, const table_name_t &name) const bool changes_visible(trx_id_t id, const table_name_t &name) const
{ {
ut_ad(rw_lock_own(&latch, RW_LOCK_S));
return view.changes_visible(id, name); return view.changes_visible(id, name);
} }
/** A wrapper around ReadView::low_limit_no(). */ /** A wrapper around ReadView::low_limit_no(). */
trx_id_t low_limit_no() const trx_id_t low_limit_no() const
{ {
#if 0 /* Unfortunately we don't hold this assertion, see MDEV-22718. */ /* MDEV-22718 FIXME: We are not holding latch here! */
ut_ad(rw_lock_own(&latch, RW_LOCK_S));
#endif
return view.low_limit_no(); return view.low_limit_no();
} }
/** A wrapper around trx_sys_t::clone_oldest_view(). */ /** A wrapper around trx_sys_t::clone_oldest_view(). */
void clone_oldest_view() void clone_oldest_view()
{ {
rw_lock_x_lock(&latch); latch.wr_lock();
trx_sys.clone_oldest_view(&view); trx_sys.clone_oldest_view(&view);
rw_lock_x_unlock(&latch); latch.wr_unlock();
} }
}; };
......
...@@ -214,8 +214,6 @@ static bool row_undo_mod_must_purge(undo_node_t* node, mtr_t* mtr) ...@@ -214,8 +214,6 @@ static bool row_undo_mod_must_purge(undo_node_t* node, mtr_t* mtr)
ut_ad(btr_cur->index->is_primary()); ut_ad(btr_cur->index->is_primary());
DEBUG_SYNC_C("rollback_purge_clust"); DEBUG_SYNC_C("rollback_purge_clust");
mtr->s_lock(&purge_sys.latch, __FILE__, __LINE__);
if (!purge_sys.changes_visible(node->new_trx_id, node->table->name)) { if (!purge_sys.changes_visible(node->new_trx_id, node->table->name)) {
return false; return false;
} }
...@@ -239,6 +237,7 @@ row_undo_mod_clust( ...@@ -239,6 +237,7 @@ row_undo_mod_clust(
{ {
btr_pcur_t* pcur; btr_pcur_t* pcur;
mtr_t mtr; mtr_t mtr;
bool have_latch = false;
dberr_t err; dberr_t err;
dict_index_t* index; dict_index_t* index;
bool online; bool online;
...@@ -365,23 +364,32 @@ row_undo_mod_clust( ...@@ -365,23 +364,32 @@ row_undo_mod_clust(
goto mtr_commit_exit; goto mtr_commit_exit;
} }
ut_ad(rec_get_deleted_flag(btr_pcur_get_rec(pcur),
dict_table_is_comp(node->table)));
if (index->table->is_temporary()) { if (index->table->is_temporary()) {
mtr.set_log_mode(MTR_LOG_NO_REDO); mtr.set_log_mode(MTR_LOG_NO_REDO);
if (btr_cur_optimistic_delete(&pcur->btr_cur, 0,
&mtr)) {
goto mtr_commit_exit;
}
btr_pcur_commit_specify_mtr(pcur, &mtr);
} else { } else {
index->set_modified(mtr);
have_latch = true;
purge_sys.latch.rd_lock();
if (!row_undo_mod_must_purge(node, &mtr)) { if (!row_undo_mod_must_purge(node, &mtr)) {
goto mtr_commit_exit; goto mtr_commit_exit;
} }
index->set_modified(mtr); if (btr_cur_optimistic_delete(&pcur->btr_cur, 0,
} &mtr)) {
goto mtr_commit_exit;
ut_ad(rec_get_deleted_flag(btr_pcur_get_rec(pcur), }
dict_table_is_comp(node->table))); purge_sys.latch.rd_unlock();
if (btr_cur_optimistic_delete(&pcur->btr_cur, 0, &mtr)) { btr_pcur_commit_specify_mtr(pcur, &mtr);
goto mtr_commit_exit; have_latch = false;
} }
btr_pcur_commit_specify_mtr(pcur, &mtr);
mtr.start(); mtr.start();
if (!btr_pcur_restore_position( if (!btr_pcur_restore_position(
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
...@@ -389,18 +397,20 @@ row_undo_mod_clust( ...@@ -389,18 +397,20 @@ row_undo_mod_clust(
goto mtr_commit_exit; goto mtr_commit_exit;
} }
ut_ad(rec_get_deleted_flag(btr_pcur_get_rec(pcur),
dict_table_is_comp(node->table)));
if (index->table->is_temporary()) { if (index->table->is_temporary()) {
mtr.set_log_mode(MTR_LOG_NO_REDO); mtr.set_log_mode(MTR_LOG_NO_REDO);
} else { } else {
have_latch = true;
purge_sys.latch.rd_lock();
if (!row_undo_mod_must_purge(node, &mtr)) { if (!row_undo_mod_must_purge(node, &mtr)) {
goto mtr_commit_exit; goto mtr_commit_exit;
} }
index->set_modified(mtr); index->set_modified(mtr);
} }
ut_ad(rec_get_deleted_flag(btr_pcur_get_rec(pcur),
dict_table_is_comp(node->table)));
/* This operation is analogous to purge, we can free /* This operation is analogous to purge, we can free
also inherited externally stored fields. We can also also inherited externally stored fields. We can also
assume that the record was complete (including BLOBs), assume that the record was complete (including BLOBs),
...@@ -409,8 +419,7 @@ row_undo_mod_clust( ...@@ -409,8 +419,7 @@ row_undo_mod_clust(
rollback=false, just like purge does. */ rollback=false, just like purge does. */
btr_cur_pessimistic_delete(&err, FALSE, &pcur->btr_cur, 0, btr_cur_pessimistic_delete(&err, FALSE, &pcur->btr_cur, 0,
false, &mtr); false, &mtr);
ut_ad(err == DB_SUCCESS ut_ad(err == DB_SUCCESS || err == DB_OUT_OF_FILE_SPACE);
|| err == DB_OUT_OF_FILE_SPACE);
} else if (!index->table->is_temporary() && node->new_trx_id) { } else if (!index->table->is_temporary() && node->new_trx_id) {
/* We rolled back a record so that it still exists. /* We rolled back a record so that it still exists.
We must reset the DB_TRX_ID if the history is no We must reset the DB_TRX_ID if the history is no
...@@ -421,7 +430,8 @@ row_undo_mod_clust( ...@@ -421,7 +430,8 @@ row_undo_mod_clust(
goto mtr_commit_exit; goto mtr_commit_exit;
} }
rec_t* rec = btr_pcur_get_rec(pcur); rec_t* rec = btr_pcur_get_rec(pcur);
mtr.s_lock(&purge_sys.latch, __FILE__, __LINE__); have_latch = true;
purge_sys.latch.rd_lock();
if (!purge_sys.changes_visible(node->new_trx_id, if (!purge_sys.changes_visible(node->new_trx_id,
node->table->name)) { node->table->name)) {
goto mtr_commit_exit; goto mtr_commit_exit;
...@@ -493,6 +503,10 @@ row_undo_mod_clust( ...@@ -493,6 +503,10 @@ row_undo_mod_clust(
} }
mtr_commit_exit: mtr_commit_exit:
if (have_latch) {
purge_sys.latch.rd_unlock();
}
btr_pcur_commit_specify_mtr(pcur, &mtr); btr_pcur_commit_specify_mtr(pcur, &mtr);
func_exit: func_exit:
......
...@@ -1124,7 +1124,6 @@ row_vers_build_for_consistent_read( ...@@ -1124,7 +1124,6 @@ row_vers_build_for_consistent_read(
ut_ad(index->is_primary()); ut_ad(index->is_primary());
ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_S_FIX)); | MTR_MEMO_PAGE_S_FIX));
ut_ad(!rw_lock_own(&(purge_sys.latch), RW_LOCK_S));
ut_ad(rec_offs_validate(rec, index, *offsets)); ut_ad(rec_offs_validate(rec, index, *offsets));
...@@ -1237,7 +1236,6 @@ row_vers_build_for_semi_consistent_read( ...@@ -1237,7 +1236,6 @@ row_vers_build_for_semi_consistent_read(
ut_ad(index->is_primary()); ut_ad(index->is_primary());
ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX ut_ad(mtr->memo_contains_page_flagged(rec, MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_S_FIX)); | MTR_MEMO_PAGE_S_FIX));
ut_ad(!rw_lock_own(&(purge_sys.latch), RW_LOCK_S));
ut_ad(rec_offs_validate(rec, index, *offsets)); ut_ad(rec_offs_validate(rec, index, *offsets));
......
...@@ -1492,13 +1492,13 @@ bool purge_sys_t::running() const ...@@ -1492,13 +1492,13 @@ bool purge_sys_t::running() const
/** Stop purge during FLUSH TABLES FOR EXPORT */ /** Stop purge during FLUSH TABLES FOR EXPORT */
void purge_sys_t::stop() void purge_sys_t::stop()
{ {
rw_lock_x_lock(&latch); latch.wr_lock();
if (!enabled()) if (!enabled())
{ {
/* Shutdown must have been initiated during FLUSH TABLES FOR EXPORT. */ /* Shutdown must have been initiated during FLUSH TABLES FOR EXPORT. */
ut_ad(!srv_undo_sources); ut_ad(!srv_undo_sources);
rw_lock_x_unlock(&latch); latch.wr_unlock();
return; return;
} }
...@@ -1506,7 +1506,7 @@ void purge_sys_t::stop() ...@@ -1506,7 +1506,7 @@ void purge_sys_t::stop()
const auto paused= m_paused++; const auto paused= m_paused++;
rw_lock_x_unlock(&latch); latch.wr_unlock();
if (!paused) if (!paused)
{ {
...@@ -1529,7 +1529,7 @@ void purge_sys_t::resume() ...@@ -1529,7 +1529,7 @@ void purge_sys_t::resume()
ut_ad(srv_force_recovery < SRV_FORCE_NO_BACKGROUND); ut_ad(srv_force_recovery < SRV_FORCE_NO_BACKGROUND);
ut_ad(!sync_check_iterate(sync_check())); ut_ad(!sync_check_iterate(sync_check()));
purge_coordinator_task.enable(); purge_coordinator_task.enable();
rw_lock_x_lock(&latch); latch.wr_lock();
int32_t paused= m_paused--; int32_t paused= m_paused--;
ut_a(paused); ut_a(paused);
...@@ -1540,7 +1540,7 @@ void purge_sys_t::resume() ...@@ -1540,7 +1540,7 @@ void purge_sys_t::resume()
srv_wake_purge_thread_if_not_active(); srv_wake_purge_thread_if_not_active();
MONITOR_ATOMIC_INC(MONITOR_PURGE_RESUME_COUNT); MONITOR_ATOMIC_INC(MONITOR_PURGE_RESUME_COUNT);
} }
rw_lock_x_unlock(&latch); latch.wr_unlock();
} }
/*******************************************************************//** /*******************************************************************//**
......
...@@ -483,7 +483,6 @@ LatchDebug::LatchDebug() ...@@ -483,7 +483,6 @@ LatchDebug::LatchDebug()
LEVEL_MAP_INSERT(SYNC_RSEG_HEADER_NEW); LEVEL_MAP_INSERT(SYNC_RSEG_HEADER_NEW);
LEVEL_MAP_INSERT(SYNC_NOREDO_RSEG); LEVEL_MAP_INSERT(SYNC_NOREDO_RSEG);
LEVEL_MAP_INSERT(SYNC_REDO_RSEG); LEVEL_MAP_INSERT(SYNC_REDO_RSEG);
LEVEL_MAP_INSERT(SYNC_PURGE_LATCH);
LEVEL_MAP_INSERT(SYNC_TREE_NODE); LEVEL_MAP_INSERT(SYNC_TREE_NODE);
LEVEL_MAP_INSERT(SYNC_TREE_NODE_FROM_HASH); LEVEL_MAP_INSERT(SYNC_TREE_NODE_FROM_HASH);
LEVEL_MAP_INSERT(SYNC_TREE_NODE_NEW); LEVEL_MAP_INSERT(SYNC_TREE_NODE_NEW);
...@@ -738,7 +737,6 @@ LatchDebug::check_order( ...@@ -738,7 +737,6 @@ LatchDebug::check_order(
case SYNC_IBUF_BITMAP_MUTEX: case SYNC_IBUF_BITMAP_MUTEX:
case SYNC_REDO_RSEG: case SYNC_REDO_RSEG:
case SYNC_NOREDO_RSEG: case SYNC_NOREDO_RSEG:
case SYNC_PURGE_LATCH:
case SYNC_PURGE_QUEUE: case SYNC_PURGE_QUEUE:
case SYNC_DICT_OPERATION: case SYNC_DICT_OPERATION:
case SYNC_DICT_HEADER: case SYNC_DICT_HEADER:
...@@ -1318,8 +1316,6 @@ sync_latch_meta_init() ...@@ -1318,8 +1316,6 @@ sync_latch_meta_init()
LATCH_ADD_RWLOCK(FTS_CACHE_INIT, SYNC_FTS_CACHE_INIT, LATCH_ADD_RWLOCK(FTS_CACHE_INIT, SYNC_FTS_CACHE_INIT,
fts_cache_init_rw_lock_key); fts_cache_init_rw_lock_key);
LATCH_ADD_RWLOCK(TRX_PURGE, SYNC_PURGE_LATCH, trx_purge_latch_key);
LATCH_ADD_RWLOCK(IBUF_INDEX_TREE, SYNC_IBUF_INDEX_TREE, LATCH_ADD_RWLOCK(IBUF_INDEX_TREE, SYNC_IBUF_INDEX_TREE,
index_tree_rw_lock_key); index_tree_rw_lock_key);
......
...@@ -36,7 +36,6 @@ Created 3/26/1996 Heikki Tuuri ...@@ -36,7 +36,6 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0mon.h" #include "srv0mon.h"
#include "srv0srv.h" #include "srv0srv.h"
#include "srv0start.h" #include "srv0start.h"
#include "sync0sync.h"
#include "trx0rec.h" #include "trx0rec.h"
#include "trx0roll.h" #include "trx0roll.h"
#include "trx0rseg.h" #include "trx0rseg.h"
...@@ -45,6 +44,10 @@ Created 3/26/1996 Heikki Tuuri ...@@ -45,6 +44,10 @@ Created 3/26/1996 Heikki Tuuri
#include <unordered_map> #include <unordered_map>
#ifdef UNIV_PFS_RWLOCK
extern mysql_pfs_key_t trx_purge_latch_key;
#endif /* UNIV_PFS_RWLOCK */
/** Maximum allowable purge history length. <=0 means 'infinite'. */ /** Maximum allowable purge history length. <=0 means 'infinite'. */
ulong srv_max_purge_lag = 0; ulong srv_max_purge_lag = 0;
...@@ -172,7 +175,7 @@ void purge_sys_t::create() ...@@ -172,7 +175,7 @@ void purge_sys_t::create()
offset= 0; offset= 0;
hdr_page_no= 0; hdr_page_no= 0;
hdr_offset= 0; hdr_offset= 0;
rw_lock_create(trx_purge_latch_key, &latch, SYNC_PURGE_LATCH); latch.init(trx_purge_latch_key);
mutex_create(LATCH_ID_PURGE_SYS_PQ, &pq_mutex); mutex_create(LATCH_ID_PURGE_SYS_PQ, &pq_mutex);
truncate.current= NULL; truncate.current= NULL;
truncate.last= NULL; truncate.last= NULL;
...@@ -193,7 +196,7 @@ void purge_sys_t::close() ...@@ -193,7 +196,7 @@ void purge_sys_t::close()
ut_ad(trx->state == TRX_STATE_ACTIVE); ut_ad(trx->state == TRX_STATE_ACTIVE);
trx->state= TRX_STATE_NOT_STARTED; trx->state= TRX_STATE_NOT_STARTED;
trx->free(); trx->free();
rw_lock_free(&latch); latch.destroy();
mutex_free(&pq_mutex); mutex_free(&pq_mutex);
mem_heap_free(heap); mem_heap_free(heap);
heap= nullptr; heap= nullptr;
......
...@@ -2201,14 +2201,14 @@ trx_undo_get_undo_rec( ...@@ -2201,14 +2201,14 @@ trx_undo_get_undo_rec(
const table_name_t& name, const table_name_t& name,
trx_undo_rec_t** undo_rec) trx_undo_rec_t** undo_rec)
{ {
rw_lock_s_lock(&purge_sys.latch); purge_sys.latch.rd_lock();
bool missing_history = purge_sys.changes_visible(trx_id, name); bool missing_history = purge_sys.changes_visible(trx_id, name);
if (!missing_history) { if (!missing_history) {
*undo_rec = trx_undo_get_undo_rec_low(roll_ptr, heap); *undo_rec = trx_undo_get_undo_rec_low(roll_ptr, heap);
} }
rw_lock_s_unlock(&purge_sys.latch); purge_sys.latch.rd_unlock();
return(missing_history); return(missing_history);
} }
...@@ -2271,7 +2271,6 @@ trx_undo_prev_version_build( ...@@ -2271,7 +2271,6 @@ trx_undo_prev_version_build(
byte* buf; byte* buf;
ut_ad(!index->table->is_temporary()); ut_ad(!index->table->is_temporary());
ut_ad(!rw_lock_own(&purge_sys.latch, RW_LOCK_S));
ut_ad(index_mtr->memo_contains_page_flagged(index_rec, ut_ad(index_mtr->memo_contains_page_flagged(index_rec,
MTR_MEMO_PAGE_S_FIX MTR_MEMO_PAGE_S_FIX
| MTR_MEMO_PAGE_X_FIX)); | MTR_MEMO_PAGE_X_FIX));
...@@ -2365,14 +2364,12 @@ trx_undo_prev_version_build( ...@@ -2365,14 +2364,12 @@ trx_undo_prev_version_build(
if ((update->info_bits & REC_INFO_DELETED_FLAG) if ((update->info_bits & REC_INFO_DELETED_FLAG)
&& row_upd_changes_disowned_external(update)) { && row_upd_changes_disowned_external(update)) {
bool missing_extern; purge_sys.latch.rd_lock();
rw_lock_s_lock(&purge_sys.latch); bool missing_extern = purge_sys.changes_visible(
missing_extern = purge_sys.changes_visible(
trx_id, index->table->name); trx_id, index->table->name);
rw_lock_s_unlock(&purge_sys.latch); purge_sys.latch.rd_unlock();
if (missing_extern) { if (missing_extern) {
/* treat as a fresh insert, not to /* treat as a fresh insert, not to
......
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