Skip to content

Optimize undo spaces lock #620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions mysql-test/r/all_persisted_variables.result
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,17 @@ include/assert.inc [Expect 500+ variables in the table. Due to open Bugs, we are

# Test SET PERSIST

include/assert.inc [Expect 445 persisted variables in the table.]
include/assert.inc [Expect 446 persisted variables in the table.]

************************************************************
* 3. Restart server, it must preserve the persisted variable
* settings. Verify persisted configuration.
************************************************************
# restart

include/assert.inc [Expect 445 persisted variables in persisted_variables table.]
include/assert.inc [Expect 445 persisted variables shown as PERSISTED in variables_info table.]
include/assert.inc [Expect 445 persisted variables with matching peristed and global values.]
include/assert.inc [Expect 446 persisted variables in persisted_variables table.]
include/assert.inc [Expect 446 persisted variables shown as PERSISTED in variables_info table.]
include/assert.inc [Expect 446 persisted variables with matching peristed and global values.]

************************************************************
* 4. Test RESET PERSIST IF EXISTS. Verify persisted variable
Expand Down
3 changes: 3 additions & 0 deletions mysql-test/suite/innodb/r/monitor.result
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ undo_truncate_count disabled
undo_truncate_start_logging_count disabled
undo_truncate_done_logging_count disabled
undo_truncate_usec disabled
undo_truncate_snapshot_ticket_grant_count disabled
undo_truncate_snapshot_ticket_try_count disabled
undo_truncate_snapshot_ticket_wait_count disabled
log_lsn_last_flush disabled
log_lsn_last_checkpoint disabled
log_lsn_current disabled
Expand Down
47 changes: 47 additions & 0 deletions mysql-test/suite/innodb_undo/r/undo_tablespace_snapshot.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#
# undo tablespace counter
#
SHOW VARIABLES LIKE 'innodb_rollback_segments';
Variable_name Value
innodb_rollback_segments 1
SELECT NAME, SPACE_TYPE, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES
WHERE SPACE_TYPE = 'Undo' ORDER BY NAME;
NAME SPACE_TYPE STATE
innodb_undo_001 Undo active
innodb_undo_002 Undo active
SET GLOBAL innodb_purge_stop_now=ON;
create table t1(
keyc int,
c1 char(255),
c2 char(255),
c3 char(255),
c4 char(255),
c5 char(255),
c6 char(255),
primary key(keyc)) engine = innodb;
CREATE PROCEDURE populate_t1()
BEGIN
DECLARE i INT DEFAULT 1;
while (i <= 20000) DO
insert into t1 values (i, 'a', 'b', 'c', 'd', 'e', 'f' );
SET i = i + 1;
END WHILE;
END |
call populate_t1();
delete from t1 where keyc < 10000;
update t1 set c1 = 'mysql' where keyc > 10000;
update t1 set c2 = 'mysql' where keyc > 10000;
update t1 set c3= 'mysql' where keyc > 10000;
update t1 set c4= 'mysql' where keyc > 10000;
update t1 set c5= 'mysql' where keyc > 10000;
update t1 set c6= 'mysql' where keyc > 10000;
SELECT @@innodb_undo_spaces_snapshot_tickets;
@@innodb_undo_spaces_snapshot_tickets
100
SET GLOBAL debug="+d,until_undo_spaces_snapshot_change,abort_if_use_undospace_latch";
SET GLOBAL innodb_purge_run_now=ON;
SET GLOBAL debug="-d,until_undo_spaces_snapshot_change";
update t1 set c6= 'modified' where keyc = 10000;
SET GLOBAL debug="-d,abort_if_use_undospace_latch";
drop PROCEDURE populate_t1;
drop table t1;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
--innodb_rollback_segments=1
--innodb_undo_log_truncate=1
--innodb_max_undo_log_size=11M
--innodb_purge_rseg_truncate_frequency=1
--log-error-verbosity=3
--innodb_undo_spaces_snapshot_tickets=100
71 changes: 71 additions & 0 deletions mysql-test/suite/innodb_undo/t/undo_tablespace_snapshot.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
--echo #
--echo # undo tablespace counter
--echo #

# This test uses debug settings like innodb_purge_stop_now.
--source include/have_debug.inc

# Valgrind would complain about memory leaks when we crash on purpose.
--source include/not_valgrind.inc

--source include/big_test.inc
--source include/have_innodb_default_undo_tablespaces.inc

SHOW VARIABLES LIKE 'innodb_rollback_segments';
SELECT NAME, SPACE_TYPE, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES
WHERE SPACE_TYPE = 'Undo' ORDER BY NAME;

SET GLOBAL innodb_purge_stop_now=ON;

--connect(conn1,localhost,root,,test)
--connection conn1

create table t1(
keyc int,
c1 char(255),
c2 char(255),
c3 char(255),
c4 char(255),
c5 char(255),
c6 char(255),
primary key(keyc)) engine = innodb;

delimiter |;
CREATE PROCEDURE populate_t1()
BEGIN
DECLARE i INT DEFAULT 1;
while (i <= 20000) DO
insert into t1 values (i, 'a', 'b', 'c', 'd', 'e', 'f' );
SET i = i + 1;
END WHILE;
END |
delimiter ;|

call populate_t1();
delete from t1 where keyc < 10000;
update t1 set c1 = 'mysql' where keyc > 10000;
update t1 set c2 = 'mysql' where keyc > 10000;
update t1 set c3= 'mysql' where keyc > 10000;
update t1 set c4= 'mysql' where keyc > 10000;
update t1 set c5= 'mysql' where keyc > 10000;
update t1 set c6= 'mysql' where keyc > 10000;

SELECT @@innodb_undo_spaces_snapshot_tickets;
SET GLOBAL debug="+d,until_undo_spaces_snapshot_change,abort_if_use_undospace_latch";
SET GLOBAL innodb_purge_run_now=ON;

# Wait until until_undo_spaces_snapshot_change to be reached.
--sleep 10

connection default;
SET GLOBAL debug="-d,until_undo_spaces_snapshot_change";
# The command can succeed iff until_undo_spaces_snapshot_change loop has ended. Otherwise abort_if_use_undospace_latch will be triggered.
update t1 set c6= 'modified' where keyc = 10000;

# Cleanup
SET GLOBAL debug="-d,abort_if_use_undospace_latch";
drop PROCEDURE populate_t1;
drop table t1;
--disconnect conn1

--sleep 5
2 changes: 2 additions & 0 deletions mysql-test/suite/sys_vars/r/all_vars.result
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ innodb_log_spin_cpu_pct_hwm
innodb_log_spin_cpu_pct_hwm
innodb_log_wait_for_flush_spin_hwm
innodb_log_wait_for_flush_spin_hwm
innodb_undo_spaces_snapshot_tickets
innodb_undo_spaces_snapshot_tickets
keyring_operations
keyring_operations
log_replica_updates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ undo_truncate_count disabled
undo_truncate_start_logging_count disabled
undo_truncate_done_logging_count disabled
undo_truncate_usec disabled
undo_truncate_snapshot_ticket_grant_count disabled
undo_truncate_snapshot_ticket_try_count disabled
undo_truncate_snapshot_ticket_wait_count disabled
log_lsn_last_flush disabled
log_lsn_last_checkpoint disabled
log_lsn_current disabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ undo_truncate_count disabled
undo_truncate_start_logging_count disabled
undo_truncate_done_logging_count disabled
undo_truncate_usec disabled
undo_truncate_snapshot_ticket_grant_count disabled
undo_truncate_snapshot_ticket_try_count disabled
undo_truncate_snapshot_ticket_wait_count disabled
log_lsn_last_flush disabled
log_lsn_last_checkpoint disabled
log_lsn_current disabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ undo_truncate_count disabled
undo_truncate_start_logging_count disabled
undo_truncate_done_logging_count disabled
undo_truncate_usec disabled
undo_truncate_snapshot_ticket_grant_count disabled
undo_truncate_snapshot_ticket_try_count disabled
undo_truncate_snapshot_ticket_wait_count disabled
log_lsn_last_flush disabled
log_lsn_last_checkpoint disabled
log_lsn_current disabled
Expand Down
3 changes: 3 additions & 0 deletions mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ undo_truncate_count disabled
undo_truncate_start_logging_count disabled
undo_truncate_done_logging_count disabled
undo_truncate_usec disabled
undo_truncate_snapshot_ticket_grant_count disabled
undo_truncate_snapshot_ticket_try_count disabled
undo_truncate_snapshot_ticket_wait_count disabled
log_lsn_last_flush disabled
log_lsn_last_checkpoint disabled
log_lsn_current disabled
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/t/all_persisted_variables.test
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ let $total_global_vars=`SELECT COUNT(*)
AND variable_name NOT LIKE 'debug_%'
AND variable_name NOT LIKE '%telemetry%'`;

let $total_persistent_vars=445;
let $total_persistent_vars=446;

--echo ***************************************************************
--echo * 0. Verify that variables present in performance_schema.global
Expand Down
1 change: 1 addition & 0 deletions storage/innobase/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ SET(INNOBASE_SOURCES
trx/trx0sys.cc
trx/trx0trx.cc
trx/trx0undo.cc
trx/undo_spaces_snapshot.cc
usr/usr0sess.cc
ut/ut0dbg.cc
ut/ut0list.cc
Expand Down
10 changes: 10 additions & 0 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,8 @@ static ulonglong innobase_fts_flags() {
return (FTS_ORDERED_RESULT | FTS_DOCID_IN_RESULT);
}

static constexpr uint innodb_undo_spaces_snapshot_tickets_max = 1048576;

/** Find and Retrieve the FTS doc_id for the current result row
@param[in,out] fts_hdl FTS handler
@return the document ID */
Expand Down Expand Up @@ -22315,6 +22317,13 @@ static MYSQL_SYSVAR_ULONG(sync_array_size, srv_sync_array_size,
1, /* Minimum value */
1024, 0); /* Maximum value */

static MYSQL_SYSVAR_UINT(undo_spaces_snapshot_tickets, innodb_undo_spaces_snapshot_tickets,
PLUGIN_VAR_OPCMDARG,
"Ticket number of undo spaces snapshot.", nullptr,
nullptr, 0, /* Default setting */
0, /* Minimum value */
innodb_undo_spaces_snapshot_tickets_max, 0); /* Maximum value */

static MYSQL_SYSVAR_ULONG(
fast_shutdown, srv_fast_shutdown, PLUGIN_VAR_OPCMDARG,
"Speeds up the shutdown process of the InnoDB storage engine. Possible"
Expand Down Expand Up @@ -23605,6 +23614,7 @@ static SYS_VAR *innobase_system_variables[] = {
MYSQL_SYSVAR(undo_directory),
MYSQL_SYSVAR(temp_tablespaces_dir),
MYSQL_SYSVAR(sync_array_size),
MYSQL_SYSVAR(undo_spaces_snapshot_tickets),
MYSQL_SYSVAR(compression_failure_threshold_pct),
MYSQL_SYSVAR(compression_pad_pct_max),
MYSQL_SYSVAR(default_row_format),
Expand Down
3 changes: 3 additions & 0 deletions storage/innobase/include/srv0mon.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@ enum monitor_id_t {
MONITOR_UNDO_TRUNCATE_START_LOGGING_COUNT,
MONITOR_UNDO_TRUNCATE_DONE_LOGGING_COUNT,
MONITOR_UNDO_TRUNCATE_MICROSECOND,
MONITOR_UNDO_TRUNCATE_SNAPSHOT_TICKET_GRANT_COUNT,
MONITOR_UNDO_TRUNCATE_SNAPSHOT_TICKET_TRY_COUNT,
MONITOR_UNDO_TRUNCATE_SNAPSHOT_TICKET_WAIT_COUNT,

/* Recovery related counters */
MONITOR_MODULE_REDO_LOG,
Expand Down
8 changes: 8 additions & 0 deletions storage/innobase/include/trx0purge.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
#ifndef trx0purge_h
#define trx0purge_h

#include <atomic>
#include "fil0fil.h"
#include "mtr0mtr.h"
#include "page0page.h"
Expand All @@ -50,6 +51,8 @@ this program; if not, write to the Free Software Foundation, Inc.,
/** The global data structure coordinating a purge */
extern trx_purge_t *purge_sys;

extern unsigned int innodb_undo_spaces_snapshot_tickets;

/** Calculates the file address of an undo log header when we have the file
address of its history list node.
@return file address of the log */
Expand Down Expand Up @@ -140,6 +143,9 @@ struct purge_iter_t {
to truncate an undo tablespace. */
namespace undo {

// Forward declaration
class Undo_spaces_snapshot;

/** Magic Number to indicate truncate action is complete. */
const uint32_t s_magic = 76845412;

Expand Down Expand Up @@ -814,6 +820,8 @@ class Inject_failure_once {

#endif /* UNIV_DEBUG */

extern Undo_spaces_snapshot *undo_spaces_snapshot;

/** Create the truncate log file. Needed to track the state of truncate during
a crash. An auxiliary redo log file undo_<space_id>_trunc.log will be created
while the truncate of the UNDO is in progress. This file is required during
Expand Down
67 changes: 67 additions & 0 deletions storage/innobase/include/undo_spaces_snapshot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#ifndef UNDO_SPACES_SNAPSHOT_H
#define UNDO_SPACES_SNAPSHOT_H

#include <atomic>
#include <vector>
#include "trx0purge.h"

#ifdef GMOCK_FOUND
#include "gtest/gtest_prod.h"
#endif

namespace undo {

class Undo_spaces_snapshot {
public:
Undo_spaces_snapshot();
Undo_spaces_snapshot(const Undo_spaces_snapshot &) = delete;
Undo_spaces_snapshot &operator=(const Undo_spaces_snapshot &) = delete;
Undo_spaces_snapshot(Undo_spaces_snapshot &&) = delete;
Undo_spaces_snapshot &operator=(Undo_spaces_snapshot &&) = delete;
~Undo_spaces_snapshot();
/* Reset the snapshot and tickets. The method should never be called when
* block_until_tickets_returned is being executed. */
void reset(const unsigned int max_tickets,
const std::vector<Tablespace *> &tablespaces);
/* Return the undo tablespaces size in the snapshot. */
std::size_t get_target_undo_tablespaces_size() const;
/* Return the unused tickets number. */
unsigned int get_unused_tickets_number() const;
/* Request a ticket. It will repeatedly call try_request_ticket until either
it succeeds or unused_tickets_number equals 0.
Return true if it succeeds.
Return false if there is no unused ticket. */
bool request_ticket();
/* Return a ticket requested earlier. */
void return_ticket();
/* Block the caller until all used tickets have been returned. */
void block_until_tickets_returned();
/* Return the max tickets number. */
unsigned int get_max_tickets_number() const;
/* Wrapper */
bool is_active_no_latch_for_undo_space(size_t pos) const;
/* Wrapper */
ulint get_rsegs_size_for_undo_space(size_t pos) const;
/* Wrapper */
trx_rseg_t *get_active_for_undo_space(size_t pos, ulint rseg_slot) const;

private:
/* Return the tablespace pointer at pos, or nullptr if pos is out of bound. */
Tablespace *at(size_t pos) const;

private:
unsigned int m_max_tickets;
std::atomic<unsigned int> m_unused_tickets;
std::atomic<unsigned int> m_used_tickets;
std::vector<Tablespace *> m_tablespaces;
std::atomic<bool> m_is_depriving;

#ifdef FRIEND_TEST
FRIEND_TEST(UndoSpacesSnapshotTest, DefaultConstructor);
FRIEND_TEST(UndoSpacesSnapshotTest, UseAllTickets);
FRIEND_TEST(UndoSpacesSnapshotTest, UseSomeTickets);
#endif
}; /* class Undo_spaces_snapshot */
} /* namespace undo */

#endif // UNDO_SPACES_SNAPSHOT_H
15 changes: 15 additions & 0 deletions storage/innobase/srv/srv0mon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,21 @@ static monitor_info_t innodb_counter_info[] = {
"Time (in microseconds) spent to process undo truncation", MONITOR_NONE,
MONITOR_DEFAULT_START, MONITOR_UNDO_TRUNCATE_MICROSECOND},

{"undo_truncate_snapshot_ticket_grant_count", "undo",
"Number of times during undo truncation a snapshot ticket was granted",
MONITOR_NONE, MONITOR_DEFAULT_START,
MONITOR_UNDO_TRUNCATE_SNAPSHOT_TICKET_GRANT_COUNT},

{"undo_truncate_snapshot_ticket_try_count", "undo",
"Number of times during undo truncation a snapshot ticket was tried",
MONITOR_NONE, MONITOR_DEFAULT_START,
MONITOR_UNDO_TRUNCATE_SNAPSHOT_TICKET_TRY_COUNT},

{"undo_truncate_snapshot_ticket_wait_count", "undo",
"Number of times during undo truncation the purge coordinator has waited until all tickets were returned",
MONITOR_NONE, MONITOR_DEFAULT_START,
MONITOR_UNDO_TRUNCATE_SNAPSHOT_TICKET_WAIT_COUNT},

/* ========== Counters for Redo log Module ========== */
{"module_log", "log", "Redo log Module", MONITOR_MODULE,
MONITOR_DEFAULT_START, MONITOR_MODULE_REDO_LOG},
Expand Down
Loading