mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 22:12:30 +01:00
MDEV-14756 - Remove trx_sys_t::rw_trx_list
Determine minimum transaction id by iterating rw_trx_hash, not rw_trx_list. It is more expensive than previous implementation since it does linear search, especially if there're many concurrent transactions running. But in such case mutex is much bigger evil. And since it doesn't require trx_sys->mutex protection it scales better. For low concurrency performance difference is neglible.
This commit is contained in:
parent
868c77df3e
commit
a0b385ea2b
3 changed files with 69 additions and 59 deletions
|
@ -188,16 +188,6 @@ inline bool trx_id_check(const void* db_trx_id, trx_id_t trx_id)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************************************************//**
|
|
||||||
Returns the minimum trx id in rw trx list. This is the smallest id for which
|
|
||||||
the trx can possibly be active. (But, you must look at the trx->state to
|
|
||||||
find out if the minimum trx id transaction itself is active, or already
|
|
||||||
committed.)
|
|
||||||
@return the minimum trx id, or trx_sys->max_trx_id if the trx list is empty */
|
|
||||||
UNIV_INLINE
|
|
||||||
trx_id_t
|
|
||||||
trx_rw_min_trx_id(void);
|
|
||||||
/*===================*/
|
|
||||||
/*****************************************************************//**
|
/*****************************************************************//**
|
||||||
Updates the offset information about the end of the MySQL binlog entry
|
Updates the offset information about the end of the MySQL binlog entry
|
||||||
which corresponds to the transaction just being committed. In a MySQL
|
which corresponds to the transaction just being committed. In a MySQL
|
||||||
|
@ -743,6 +733,38 @@ public:
|
||||||
{
|
{
|
||||||
return my_atomic_load32_explicit(&hash.count, MY_MEMORY_ORDER_RELAXED);
|
return my_atomic_load32_explicit(&hash.count, MY_MEMORY_ORDER_RELAXED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterates the hash.
|
||||||
|
|
||||||
|
@param caller_trx used to get/set pins
|
||||||
|
@param action called for every element in hash
|
||||||
|
@param argument opque argument passed to action
|
||||||
|
|
||||||
|
May return the same element multiple times if hash is under contention.
|
||||||
|
Elements can be added or removed while this method is being executed.
|
||||||
|
|
||||||
|
@return
|
||||||
|
@retval 0 iteration completed successfully
|
||||||
|
@retval 1 iteration was interrupted (action returned 1)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int iterate(trx_t *caller_trx, my_hash_walk_action action, void *argument)
|
||||||
|
{
|
||||||
|
LF_PINS *pins= caller_trx ? get_pins(caller_trx) : lf_hash_get_pins(&hash);
|
||||||
|
ut_a(pins);
|
||||||
|
int res= lf_hash_iterate(&hash, pins, action, argument);
|
||||||
|
if (!caller_trx)
|
||||||
|
lf_hash_put_pins(pins);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int iterate(my_hash_walk_action action, void *argument)
|
||||||
|
{
|
||||||
|
return iterate(current_trx(), action, argument);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -840,6 +862,40 @@ struct trx_sys_t {
|
||||||
while there were XA PREPARED
|
while there were XA PREPARED
|
||||||
transactions. We disable query cache
|
transactions. We disable query cache
|
||||||
if such transactions exist. */
|
if such transactions exist. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the minimum trx id in rw trx list.
|
||||||
|
|
||||||
|
This is the smallest id for which the trx can possibly be active. (But, you
|
||||||
|
must look at the trx->state to find out if the minimum trx id transaction
|
||||||
|
itself is active, or already committed.)
|
||||||
|
|
||||||
|
@return the minimum trx id, or trx_sys->max_trx_id if the trx list is empty
|
||||||
|
*/
|
||||||
|
|
||||||
|
trx_id_t get_min_trx_id()
|
||||||
|
{
|
||||||
|
trx_id_t id= trx_sys_get_max_trx_id();
|
||||||
|
rw_trx_hash.iterate(reinterpret_cast<my_hash_walk_action>
|
||||||
|
(get_min_trx_id_callback), &id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
static my_bool get_min_trx_id_callback(rw_trx_hash_element_t *element,
|
||||||
|
trx_id_t *id)
|
||||||
|
{
|
||||||
|
if (element->id < *id)
|
||||||
|
{
|
||||||
|
mutex_enter(&element->mutex);
|
||||||
|
/* We don't care about read-only transactions here. */
|
||||||
|
if (element->trx && element->trx->rsegs.m_redo.rseg)
|
||||||
|
*id= element->id;
|
||||||
|
mutex_exit(&element->mutex);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** When a trx id which is zero modulo this number (which must be a power of
|
/** When a trx id which is zero modulo this number (which must be a power of
|
||||||
|
|
|
@ -192,53 +192,6 @@ trx_write_trx_id(
|
||||||
mach_write_to_6(ptr, id);
|
mach_write_to_6(ptr, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************//**
|
|
||||||
Returns the minimum trx id in trx list. This is the smallest id for which
|
|
||||||
the trx can possibly be active. (But, you must look at the trx->state
|
|
||||||
to find out if the minimum trx id transaction itself is active, or already
|
|
||||||
committed.). The caller must be holding the trx_sys_t::mutex in shared mode.
|
|
||||||
@return the minimum trx id, or trx_sys->max_trx_id if the trx list is empty */
|
|
||||||
UNIV_INLINE
|
|
||||||
trx_id_t
|
|
||||||
trx_rw_min_trx_id_low(void)
|
|
||||||
/*=======================*/
|
|
||||||
{
|
|
||||||
trx_id_t id;
|
|
||||||
|
|
||||||
ut_ad(trx_sys_mutex_own());
|
|
||||||
|
|
||||||
const trx_t* trx = UT_LIST_GET_LAST(trx_sys->rw_trx_list);
|
|
||||||
|
|
||||||
if (trx == NULL) {
|
|
||||||
id = trx_sys->max_trx_id;
|
|
||||||
} else {
|
|
||||||
assert_trx_in_rw_list(trx);
|
|
||||||
id = trx->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************//**
|
|
||||||
Returns the minimum trx id in rw trx list. This is the smallest id for which
|
|
||||||
the rw trx can possibly be active. (But, you must look at the trx->state
|
|
||||||
to find out if the minimum trx id transaction itself is active, or already
|
|
||||||
committed.)
|
|
||||||
@return the minimum trx id, or trx_sys->max_trx_id if rw trx list is empty */
|
|
||||||
UNIV_INLINE
|
|
||||||
trx_id_t
|
|
||||||
trx_rw_min_trx_id(void)
|
|
||||||
/*===================*/
|
|
||||||
{
|
|
||||||
trx_sys_mutex_enter();
|
|
||||||
|
|
||||||
trx_id_t id = trx_rw_min_trx_id_low();
|
|
||||||
|
|
||||||
trx_sys_mutex_exit();
|
|
||||||
|
|
||||||
return(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************//**
|
/*****************************************************************//**
|
||||||
Allocates a new transaction id.
|
Allocates a new transaction id.
|
||||||
@return new, allocated trx id */
|
@return new, allocated trx id */
|
||||||
|
|
|
@ -1514,7 +1514,7 @@ lock_sec_rec_some_has_impl(
|
||||||
max trx id to the log, and therefore during recovery, this value
|
max trx id to the log, and therefore during recovery, this value
|
||||||
for a page may be incorrect. */
|
for a page may be incorrect. */
|
||||||
|
|
||||||
if (max_trx_id < trx_rw_min_trx_id()) {
|
if (max_trx_id < trx_sys->get_min_trx_id()) {
|
||||||
|
|
||||||
trx = 0;
|
trx = 0;
|
||||||
|
|
||||||
|
@ -7094,7 +7094,8 @@ lock_sec_rec_read_check_and_lock(
|
||||||
database recovery is running. */
|
database recovery is running. */
|
||||||
|
|
||||||
if (!page_rec_is_supremum(rec)
|
if (!page_rec_is_supremum(rec)
|
||||||
&& page_get_max_trx_id(block->frame) >= trx_rw_min_trx_id()) {
|
&& page_get_max_trx_id(block->frame) >=
|
||||||
|
trx_sys->get_min_trx_id()) {
|
||||||
|
|
||||||
lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec,
|
lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec,
|
||||||
index, offsets);
|
index, offsets);
|
||||||
|
|
Loading…
Reference in a new issue