1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Merge 10.5 into 10.6

This commit is contained in:
Marko Mäkelä
2023-06-08 10:42:56 +03:00
21 changed files with 170 additions and 66 deletions

View File

@ -4204,6 +4204,30 @@ a b s1
2 2 t2:t2a-null;min_t3_b:t3b-null 2 2 t2:t2a-null;min_t3_b:t3b-null
3 3 t2:1;min_t3_b:3 3 3 t2:1;min_t3_b:3
drop table t1,t2,t3; drop table t1,t2,t3;
#
# MDEV-31380: Assertion `s->table->opt_range_condition_rows <= s->found_records' failed
# (assertion in 10.6+, DBL_MAX costs in 10.5)
#
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY(a), KEY(b)) ENGINE=InnoDB;
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100;
SET
@tmp=@@optimizer_use_condition_selectivity,
optimizer_use_condition_selectivity = 1,
@tmp2=@@optimizer_trace,
optimizer_trace=1;
SELECT DISTINCT * FROM t1 WHERE a IN (1, 2);
a b
1 1
2 2
select
CAST(json_value(json_extract(trace, '$**.chosen_access_method.cost'), '$[0]')
as DOUBLE) < 1.0e100
from information_schema.optimizer_trace;
CAST(json_value(json_extract(trace, '$**.chosen_access_method.cost'), '$[0]')
as DOUBLE) < 1.0e100
1
set optimizer_use_condition_selectivity = @tmp, optimizer_trace=@tmp2;
drop table t1;
# #
# End of 10.5 tests # End of 10.5 tests
# #

View File

@ -7,6 +7,7 @@
--source include/default_optimizer_switch.inc --source include/default_optimizer_switch.inc
--source include/have_sequence.inc --source include/have_sequence.inc
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/have_sequence.inc
# #
# TODO: # TODO:
# Add queries with: # Add queries with:
@ -1859,6 +1860,30 @@ from t1;
drop table t1,t2,t3; drop table t1,t2,t3;
--echo #
--echo # MDEV-31380: Assertion `s->table->opt_range_condition_rows <= s->found_records' failed
--echo # (assertion in 10.6+, DBL_MAX costs in 10.5)
--echo #
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY(a), KEY(b)) ENGINE=InnoDB;
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_100;
SET
@tmp=@@optimizer_use_condition_selectivity,
optimizer_use_condition_selectivity = 1,
@tmp2=@@optimizer_trace,
optimizer_trace=1;
SELECT DISTINCT * FROM t1 WHERE a IN (1, 2);
select
CAST(json_value(json_extract(trace, '$**.chosen_access_method.cost'), '$[0]')
as DOUBLE) < 1.0e100
from information_schema.optimizer_trace;
set optimizer_use_condition_selectivity = @tmp, optimizer_trace=@tmp2;
drop table t1;
--echo # --echo #
--echo # End of 10.5 tests --echo # End of 10.5 tests
--echo # --echo #

View File

@ -16,7 +16,7 @@ INSERT INTO t1 (f1, f2) VALUES(1,2);
set global debug_dbug="+d,ib_purge_virtual_index_callback"; set global debug_dbug="+d,ib_purge_virtual_index_callback";
connection con1; connection con1;
COMMIT; COMMIT;
InnoDB 0 transactions not purged SET GLOBAL innodb_max_purge_lag_wait=1;
connection con2; connection con2;
commit; commit;
disconnect con1; disconnect con1;

View File

@ -78,7 +78,7 @@ SET DEBUG_SYNC= 'now WAIT_FOR uncommitted';
# enable purge # enable purge
COMMIT; COMMIT;
# wait for purge to process the deleted records. # wait for purge to process the deleted records.
InnoDB 0 transactions not purged InnoDB 1 transactions not purged
SET DEBUG_SYNC= 'now SIGNAL purged'; SET DEBUG_SYNC= 'now SIGNAL purged';
connection default; connection default;
/* connection default */ ALTER TABLE t1 ADD COLUMN c INT GENERATED ALWAYS AS(a+b), ADD INDEX idx (c), ALGORITHM=INPLACE, LOCK=SHARED; /* connection default */ ALTER TABLE t1 ADD COLUMN c INT GENERATED ALWAYS AS(a+b), ADD INDEX idx (c), ALGORITHM=INPLACE, LOCK=SHARED;

View File

@ -23,7 +23,7 @@ set global debug_dbug="+d,ib_purge_virtual_index_callback";
connection con1; connection con1;
COMMIT; COMMIT;
--source ../innodb/include/wait_all_purged.inc SET GLOBAL innodb_max_purge_lag_wait=1;
connection con2; connection con2;
commit; commit;

View File

@ -113,7 +113,9 @@ SET DEBUG_SYNC= 'now WAIT_FOR uncommitted';
COMMIT; COMMIT;
--echo # wait for purge to process the deleted records. --echo # wait for purge to process the deleted records.
let $wait_all_purged = 1;
--source ../../innodb/include/wait_all_purged.inc --source ../../innodb/include/wait_all_purged.inc
let $wait_all_purged = 0;
SET DEBUG_SYNC= 'now SIGNAL purged'; SET DEBUG_SYNC= 'now SIGNAL purged';

View File

@ -1,31 +1,34 @@
SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB; CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB, STATS_PERSISTENT=0;
InnoDB 0 transactions not purged InnoDB 0 transactions not purged
connect prevent_purge,localhost,root,,; connect prevent_purge,localhost,root,,;
start transaction with consistent snapshot; start transaction with consistent snapshot;
connect con_del_1,localhost,root,,; connect con_del_1,localhost,root,,;
INSERT INTO t VALUES (20,20); INSERT INTO t VALUES (20,20);
SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont'; SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont';
DELETE FROM t WHERE b = 20; DELETE FROM t WHERE b = 20 # trx_1;
connect con_ins_1,localhost,root,,; connect con_ins_1,localhost,root,,;
SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished'; SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished';
SET DEBUG_SYNC = 'lock_wait_start SIGNAL first_ins_locked'; SET DEBUG_SYNC = 'lock_wait_start SIGNAL first_ins_locked';
SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont'; SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont';
INSERT INTO t VALUES(10, 20); INSERT INTO t VALUES(10, 20) # trx_2;
connect con_del_2,localhost,root,,; connect con_del_2,localhost,root,,;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked'; SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked';
SET DEBUG_SYNC = 'lock_wait_start SIGNAL second_del_locked'; SET DEBUG_SYNC = 'lock_wait_start SIGNAL second_del_locked';
DELETE FROM t WHERE b = 20; DELETE FROM t WHERE b = 20 # trx_3;
connection default; connection default;
SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked'; SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked';
SET @saved_dbug = @@GLOBAL.debug_dbug;
SET @@GLOBAL.debug_dbug="d,enable_row_purge_del_mark_exit_sync_point";
SET DEBUG_SYNC = 'now SIGNAL first_del_cont'; SET DEBUG_SYNC = 'now SIGNAL first_del_cont';
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted'; SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted';
connection con_del_1; connection con_del_1;
connection default; connection default;
disconnect prevent_purge; disconnect prevent_purge;
InnoDB 0 transactions not purged SET DEBUG_SYNC = 'now WAIT_FOR row_purge_del_mark_finished';
SET @@GLOBAL.debug_dbug = @saved_dbug;
SET DEBUG_SYNC = 'now SIGNAL first_ins_cont'; SET DEBUG_SYNC = 'now SIGNAL first_ins_cont';
connection con_del_2; connection con_del_2;
connection con_ins_1; connection con_ins_1;

View File

@ -19,7 +19,7 @@ BEGIN;
UPDATE t1 SET b=4 WHERE a=3; UPDATE t1 SET b=4 WHERE a=3;
disconnect prevent_purge; disconnect prevent_purge;
connection default; connection default;
InnoDB 0 transactions not purged SET GLOBAL innodb_max_purge_lag_wait=1;
connection con1; connection con1;
ROLLBACK; ROLLBACK;
disconnect con1; disconnect con1;

View File

@ -390,11 +390,12 @@ connection stop_purge;
COMMIT; COMMIT;
disconnect stop_purge; disconnect stop_purge;
connection default; connection default;
InnoDB 0 transactions not purged InnoDB 1 transactions not purged
SET DEBUG_SYNC='now SIGNAL s2'; SET DEBUG_SYNC='now SIGNAL s2';
connection dml; connection dml;
disconnect dml; disconnect dml;
connection default; connection default;
InnoDB 0 transactions not purged
SET DEBUG_SYNC=RESET; SET DEBUG_SYNC=RESET;
DROP TABLE t1; DROP TABLE t1;
# End of 10.3 tests # End of 10.3 tests

View File

@ -1,5 +1,6 @@
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
InnoDB 0 transactions not purged
# #
# MDEV-17793 Crash in purge after instant DROP and emptying the table # MDEV-17793 Crash in purge after instant DROP and emptying the table
# #
@ -16,7 +17,7 @@ COMMIT;
START TRANSACTION WITH CONSISTENT SNAPSHOT; START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default; connection default;
ALTER TABLE t1 ADD COLUMN extra TINYINT UNSIGNED NOT NULL DEFAULT 42; ALTER TABLE t1 ADD COLUMN extra TINYINT UNSIGNED NOT NULL DEFAULT 42;
InnoDB 1 transactions not purged SET GLOBAL innodb_max_purge_lag_wait=1;
ALTER TABLE t1 DROP extra; ALTER TABLE t1 DROP extra;
disconnect prevent_purge; disconnect prevent_purge;
InnoDB 0 transactions not purged InnoDB 0 transactions not purged

View File

@ -5,7 +5,7 @@ source include/have_debug_sync.inc;
SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB; CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB, STATS_PERSISTENT=0;
--source include/wait_all_purged.inc --source include/wait_all_purged.inc
--connect(prevent_purge,localhost,root,,) --connect(prevent_purge,localhost,root,,)
@ -14,20 +14,20 @@ start transaction with consistent snapshot;
--connect(con_del_1,localhost,root,,) --connect(con_del_1,localhost,root,,)
INSERT INTO t VALUES (20,20); INSERT INTO t VALUES (20,20);
SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont'; SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont';
--send DELETE FROM t WHERE b = 20 --send DELETE FROM t WHERE b = 20 # trx_1
--connect(con_ins_1,localhost,root,,) --connect(con_ins_1,localhost,root,,)
SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished'; SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished';
# It's supposed the following INSERT will be suspended just after # It's supposed the following INSERT will be suspended just after
# lock_wait_start syncpoint, and will be awaken # lock_wait_start syncpoint, and will be awaken
# after the previous DELETE commits. ib_after_row_insert will be executed # after trx_1 DELETE commits. ib_after_row_insert will be executed
# after the INSERT is woken up. The previous DELETE will wait for # after the trx_2 INSERT is woken up. The trx_1 DELETE will wait for
# first_del_cont signal before commit, and this signal will be sent later. # first_del_cont signal before commit, and this signal will be sent later.
# So it's safe to use two signals in a row here, it's guaranted the first # So it's safe to use two signals in a row here, it's guaranted the first
# signal will be received before the second signal is sent. # signal will be received before the second signal is sent.
SET DEBUG_SYNC = 'lock_wait_start SIGNAL first_ins_locked'; SET DEBUG_SYNC = 'lock_wait_start SIGNAL first_ins_locked';
SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont'; SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont';
--send INSERT INTO t VALUES(10, 20) --send INSERT INTO t VALUES(10, 20) # trx_2
--connect(con_del_2,localhost,root,,) --connect(con_del_2,localhost,root,,)
# After MDEV-30225 is fixed, the following DELETE creates next-key lock for # After MDEV-30225 is fixed, the following DELETE creates next-key lock for
@ -36,24 +36,26 @@ SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR fir
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked'; SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked';
SET DEBUG_SYNC = 'lock_wait_start SIGNAL second_del_locked'; SET DEBUG_SYNC = 'lock_wait_start SIGNAL second_del_locked';
############################################################################### ##############################################################################
# This DELETE is locked by the previous DELETE, after that DELETE is # trx_3 DELETE is locked by trx_1 DELETE, after trx_1 DELETE is
# committed, it will still be locked by the next INSERT on delete-marked # committed, it will still be locked by trx_2 INSERT on delete-marked
# heap_no 2 record. After that INSERT inserted the record with heap_no 3, # heap_no 2 record. After trx_2 INSERT inserted the record with heap_no 3,
# and after heap_no 2 record is purged, this DELETE will be unlocked and # and after heap_no 2 record is purged, trx_3 DELETE will be unlocked and
# must restore persistent cursor position at heap_no 3 record, as it has the # must restore persistent cursor position at heap_no 3 record, as it has the
# same secondary key value as former heap_no 2 record. Then it must be blocked # same secondary key value as former heap_no 2 record. Then it must be blocked
# by the previous INSERT, and after the INSERT is committed, it must # by trx_2 INSERT, and after trx_2 INSERT is committed, it must
# delete the record, inserted by the previous INSERT, and the last INSERT(see # delete the record, inserted by trx_2 INSERT, and trx_4 INSERT(see
# below) must be finished without error. But instead this DELETE restores # below) must be finished without error. But instead this DELETE restores
# persistent cursor position to supremum, as a result, it does not delete the # persistent cursor position to supremum, as a result, it does not delete the
# record, inserted by the previous INSERT, and the last INSERT is finished with # record, inserted by trx_2 INSERT, and trx_4 INSERT is finished with
# duplicate key check error. # duplicate key check error.
############################################################################### ###############################################################################
--send DELETE FROM t WHERE b = 20 --send DELETE FROM t WHERE b = 20 # trx_3
--connection default --connection default
SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked'; SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked';
SET @saved_dbug = @@GLOBAL.debug_dbug;
SET @@GLOBAL.debug_dbug="d,enable_row_purge_del_mark_exit_sync_point";
SET DEBUG_SYNC = 'now SIGNAL first_del_cont'; SET DEBUG_SYNC = 'now SIGNAL first_del_cont';
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted'; SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted';
--connection con_del_1 --connection con_del_1
@ -61,7 +63,8 @@ SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted';
--connection default --connection default
--disconnect prevent_purge --disconnect prevent_purge
--source include/wait_all_purged.inc SET DEBUG_SYNC = 'now WAIT_FOR row_purge_del_mark_finished';
SET @@GLOBAL.debug_dbug = @saved_dbug;
SET DEBUG_SYNC = 'now SIGNAL first_ins_cont'; SET DEBUG_SYNC = 'now SIGNAL first_ins_cont';
--connection con_del_2 --connection con_del_2
@ -74,7 +77,7 @@ SET DEBUG_SYNC = 'now SIGNAL first_ins_cont';
############################################################################### ###############################################################################
# Duplicate key error is expected if the bug is not fixed. # Duplicate key error is expected if the bug is not fixed.
############################################################################### ###############################################################################
INSERT INTO t VALUES(30, 20); INSERT INTO t VALUES(30, 20); # trx_4
--disconnect con_ins_1 --disconnect con_ins_1
--disconnect con_del_1 --disconnect con_del_1

View File

@ -32,7 +32,7 @@ UPDATE t1 SET b=4 WHERE a=3;
--connection default --connection default
# Initiate a full purge, which should reset the DB_TRX_ID except for a=3. # Initiate a full purge, which should reset the DB_TRX_ID except for a=3.
--source include/wait_all_purged.inc SET GLOBAL innodb_max_purge_lag_wait=1;
# Initiate a ROLLBACK of the update, which should reset the DB_TRX_ID for a=3. # Initiate a ROLLBACK of the update, which should reset the DB_TRX_ID for a=3.
--connection con1 --connection con1
ROLLBACK; ROLLBACK;

View File

@ -450,7 +450,9 @@ COMMIT;
disconnect stop_purge; disconnect stop_purge;
connection default; connection default;
let $wait_all_purged = 1;
--source include/wait_all_purged.inc --source include/wait_all_purged.inc
let $wait_all_purged = 0;
SET DEBUG_SYNC='now SIGNAL s2'; SET DEBUG_SYNC='now SIGNAL s2';
connection dml; connection dml;
@ -458,6 +460,7 @@ reap;
disconnect dml; disconnect dml;
connection default; connection default;
--source include/wait_all_purged.inc
SET DEBUG_SYNC=RESET; SET DEBUG_SYNC=RESET;
DROP TABLE t1; DROP TABLE t1;

View File

@ -6,6 +6,7 @@ if ($have_debug) {
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1; SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
--source include/wait_all_purged.inc
--echo # --echo #
--echo # MDEV-17793 Crash in purge after instant DROP and emptying the table --echo # MDEV-17793 Crash in purge after instant DROP and emptying the table
@ -27,8 +28,7 @@ START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default; connection default;
ALTER TABLE t1 ADD COLUMN extra TINYINT UNSIGNED NOT NULL DEFAULT 42; ALTER TABLE t1 ADD COLUMN extra TINYINT UNSIGNED NOT NULL DEFAULT 42;
let $wait_all_purged= 1; SET GLOBAL innodb_max_purge_lag_wait=1;
--source include/wait_all_purged.inc
ALTER TABLE t1 DROP extra; ALTER TABLE t1 DROP extra;
disconnect prevent_purge; disconnect prevent_purge;
let $wait_all_purged= 0; let $wait_all_purged= 0;

View File

@ -1,6 +1,10 @@
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/have_sequence.inc --source include/have_sequence.inc
--disable_query_log
call mtr.add_suppression("InnoDB: Difficult to find free blocks in the buffer pool");
--enable_query_log
# Ensure that the history list length will actually be decremented by purge. # Ensure that the history list length will actually be decremented by purge.
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;

View File

@ -3030,8 +3030,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
restore_nonrange_trees(&param, tree, backup_keys); restore_nonrange_trees(&param, tree, backup_keys);
if ((group_trp= get_best_group_min_max(&param, tree, read_time))) if ((group_trp= get_best_group_min_max(&param, tree, read_time)))
{ {
param.table->opt_range_condition_rows= MY_MIN(group_trp->records, set_if_smaller(param.table->opt_range_condition_rows,
head->stat_records()); group_trp->records);
Json_writer_object grp_summary(thd, "best_group_range_summary"); Json_writer_object grp_summary(thd, "best_group_range_summary");
if (unlikely(thd->trace_started())) if (unlikely(thd->trace_started()))

View File

@ -19422,10 +19422,17 @@ static MYSQL_SYSVAR_ULONG(purge_rseg_truncate_frequency,
" purge rollback segment(s) on every Nth iteration of purge invocation", " purge rollback segment(s) on every Nth iteration of purge invocation",
NULL, NULL, 128, 1, 128, 0); NULL, NULL, 128, 1, 128, 0);
static void innodb_undo_log_truncate_update(THD *thd, struct st_mysql_sys_var*,
void*, const void *save)
{
if ((srv_undo_log_truncate= *static_cast<const my_bool*>(save)))
srv_wake_purge_thread_if_not_active();
}
static MYSQL_SYSVAR_BOOL(undo_log_truncate, srv_undo_log_truncate, static MYSQL_SYSVAR_BOOL(undo_log_truncate, srv_undo_log_truncate,
PLUGIN_VAR_OPCMDARG, PLUGIN_VAR_OPCMDARG,
"Enable or Disable Truncate of UNDO tablespace.", "Enable or Disable Truncate of UNDO tablespace.",
NULL, NULL, FALSE); NULL, innodb_undo_log_truncate_update, FALSE);
static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode, static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,

View File

@ -39,13 +39,20 @@ Remove the undo log segment from the rseg slot if it is too big for reuse.
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
void void
trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr); trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr);
/**
Remove unnecessary history data from rollback segments. NOTE that when this
function is called, the caller (purge_coordinator_callback)
must not have any latches on undo log pages!
*/
void trx_purge_truncate_history();
/** /**
Run a purge batch. Run a purge batch.
@param n_tasks number of purge tasks to submit to the queue @param n_tasks number of purge tasks to submit to the queue
@param history_size trx_sys.history_size() @param history_size trx_sys.history_size()
@param truncate whether to truncate the history at the end of the batch
@return number of undo log pages handled in the batch */ @return number of undo log pages handled in the batch */
ulint trx_purge(ulint n_tasks, ulint history_size, bool truncate); ulint trx_purge(ulint n_tasks, ulint history_size);
/** Rollback segements from a given transaction with trx-no /** Rollback segements from a given transaction with trx-no
scheduled for purge. */ scheduled for purge. */
@ -285,6 +292,18 @@ public:
typically via purge_sys_t::view_guard. */ typically via purge_sys_t::view_guard. */
return view.low_limit_no(); return view.low_limit_no();
} }
/** A wrapper around ReadView::sees(). */
trx_id_t sees(trx_id_t id) const
{
/* This function may only be called by purge_coordinator_callback().
The purge coordinator task may call this without holding any latch,
because it is the only thread that may modify purge_sys.view.
Any other threads that access purge_sys.view must hold purge_sys.latch,
typically via purge_sys_t::view_guard. */
return view.sees(id);
}
/** A wrapper around trx_sys_t::clone_oldest_view(). */ /** A wrapper around trx_sys_t::clone_oldest_view(). */
template<bool also_end_view= false> template<bool also_end_view= false>
void clone_oldest_view() void clone_oldest_view()

View File

@ -47,6 +47,7 @@ Created 3/14/1997 Heikki Tuuri
#include "handler.h" #include "handler.h"
#include "ha_innodb.h" #include "ha_innodb.h"
#include "fil0fil.h" #include "fil0fil.h"
#include "debug_sync.h"
#include <mysql/service_thd_mdl.h> #include <mysql/service_thd_mdl.h>
/************************************************************************* /*************************************************************************
@ -631,7 +632,17 @@ row_purge_del_mark(
mem_heap_free(heap); mem_heap_free(heap);
} }
return row_purge_remove_clust_if_poss(node); bool result= row_purge_remove_clust_if_poss(node);
#ifdef ENABLED_DEBUG_SYNC
DBUG_EXECUTE_IF("enable_row_purge_del_mark_exit_sync_point",
debug_sync_set_action
(current_thd,
STRING_WITH_LEN("now SIGNAL row_purge_del_mark_finished"));
);
#endif
return result;
} }
void purge_sys_t::wait_SYS() void purge_sys_t::wait_SYS()
@ -850,6 +861,9 @@ skip_secondaries:
buf_page_get(page_id_t(rseg.space->id, buf_page_get(page_id_t(rseg.space->id,
page_no), page_no),
0, RW_X_LATCH, &mtr)) { 0, RW_X_LATCH, &mtr)) {
block->page.set_accessed();
buf_page_make_young_if_needed(&block->page);
byte* data_field = block->page.frame byte* data_field = block->page.frame
+ offset + internal_offset; + offset + internal_offset;

View File

@ -1296,17 +1296,14 @@ static tpool::waitable_task purge_coordinator_task
static tpool::timer *purge_coordinator_timer; static tpool::timer *purge_coordinator_timer;
/** Wake up the purge threads if there is work to do. */ /** Wake up the purge threads if there is work to do. */
void void srv_wake_purge_thread_if_not_active()
srv_wake_purge_thread_if_not_active()
{ {
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
if (purge_sys.enabled() && !purge_sys.paused() if (purge_sys.enabled() && !purge_sys.paused() &&
&& trx_sys.history_exists()) { (srv_undo_log_truncate || trx_sys.history_exists()) &&
if(++purge_state.m_running == 1) { ++purge_state.m_running == 1)
srv_thread_pool->submit_task(&purge_coordinator_task); srv_thread_pool->submit_task(&purge_coordinator_task);
}
}
} }
/** @return whether the purge tasks are active */ /** @return whether the purge tasks are active */
@ -1697,13 +1694,20 @@ fewer_threads:
m_history_length= history_size; m_history_length= history_size;
if (!history_size) if (!history_size)
{
srv_dml_needed_delay= 0; srv_dml_needed_delay= 0;
else if (trx_purge(n_use_threads, history_size, trx_purge_truncate_history();
!(++count % srv_purge_rseg_truncate_frequency) || }
purge_sys.truncate.current || else
(srv_shutdown_state != SRV_SHUTDOWN_NONE && {
srv_fast_shutdown == 0))) ulint n_pages_handled= trx_purge(n_use_threads, history_size);
continue; if (!(++count % srv_purge_rseg_truncate_frequency) ||
purge_sys.truncate.current ||
(srv_shutdown_state != SRV_SHUTDOWN_NONE && srv_fast_shutdown == 0))
trx_purge_truncate_history();
if (n_pages_handled)
continue;
}
if (srv_dml_needed_delay); if (srv_dml_needed_delay);
else if (m_running == sigcount) else if (m_running == sigcount)

View File

@ -363,7 +363,6 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
TRX_UNDO_NEEDS_PURGE, 1U); TRX_UNDO_NEEDS_PURGE, 1U);
} }
/** Free an undo log segment. /** Free an undo log segment.
@param block rollback segment header page @param block rollback segment header page
@param mtr mini-transaction */ @param mtr mini-transaction */
@ -561,10 +560,11 @@ __attribute__((optimize(0)))
# endif # endif
#endif #endif
/** /**
Removes unnecessary history data from rollback segments. NOTE that when this Remove unnecessary history data from rollback segments. NOTE that when this
function is called, the caller must not have any latches on undo log pages! function is called, the caller (purge_coordinator_callback)
must not have any latches on undo log pages!
*/ */
TRANSACTIONAL_TARGET static void trx_purge_truncate_history() TRANSACTIONAL_TARGET void trx_purge_truncate_history()
{ {
ut_ad(purge_sys.head <= purge_sys.tail); ut_ad(purge_sys.head <= purge_sys.tail);
purge_sys_t::iterator &head= purge_sys.head.trx_no purge_sys_t::iterator &head= purge_sys.head.trx_no
@ -586,7 +586,7 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history()
if (dberr_t e= if (dberr_t e=
trx_purge_truncate_rseg_history(rseg, head, trx_purge_truncate_rseg_history(rseg, head,
!rseg.is_referenced() && !rseg.is_referenced() &&
rseg.needs_purge <= head.trx_no)) purge_sys.sees(rseg.needs_purge)))
err= e; err= e;
rseg.latch.wr_unlock(); rseg.latch.wr_unlock();
} }
@ -644,7 +644,7 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history()
rseg.latch.rd_lock(SRW_LOCK_CALL); rseg.latch.rd_lock(SRW_LOCK_CALL);
ut_ad(rseg.skip_allocation()); ut_ad(rseg.skip_allocation());
if (rseg.is_referenced() || rseg.needs_purge > head.trx_no) if (rseg.is_referenced() || !purge_sys.sees(rseg.needs_purge))
{ {
not_free: not_free:
rseg.latch.rd_unlock(); rseg.latch.rd_unlock();
@ -658,7 +658,7 @@ not_free:
for (const trx_undo_t *undo= UT_LIST_GET_FIRST(rseg.undo_cached); undo; for (const trx_undo_t *undo= UT_LIST_GET_FIRST(rseg.undo_cached); undo;
undo= UT_LIST_GET_NEXT(undo_list, undo)) undo= UT_LIST_GET_NEXT(undo_list, undo))
{ {
if (head.trx_no < undo->trx_id) if (head.trx_no && head.trx_no < undo->trx_id)
goto not_free; goto not_free;
else else
cached+= undo->size; cached+= undo->size;
@ -791,7 +791,7 @@ not_free:
continue; continue;
ut_ad(!rseg.is_referenced()); ut_ad(!rseg.is_referenced());
ut_ad(rseg.needs_purge <= head.trx_no); ut_ad(!head.trx_no || rseg.needs_purge <= head.trx_no);
buf_block_t *rblock= trx_rseg_header_create(&space, buf_block_t *rblock= trx_rseg_header_create(&space,
&rseg - trx_sys.rseg_array, &rseg - trx_sys.rseg_array,
@ -1264,10 +1264,8 @@ TRANSACTIONAL_INLINE void purge_sys_t::clone_end_view()
Run a purge batch. Run a purge batch.
@param n_tasks number of purge tasks to submit to the queue @param n_tasks number of purge tasks to submit to the queue
@param history_size trx_sys.history_size() @param history_size trx_sys.history_size()
@param truncate whether to truncate the history at the end of the batch
@return number of undo log pages handled in the batch */ @return number of undo log pages handled in the batch */
TRANSACTIONAL_TARGET TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size)
ulint trx_purge(ulint n_tasks, ulint history_size, bool truncate)
{ {
que_thr_t* thr = NULL; que_thr_t* thr = NULL;
ulint n_pages_handled; ulint n_pages_handled;
@ -1319,10 +1317,6 @@ ulint trx_purge(ulint n_tasks, ulint history_size, bool truncate)
purge_sys.clone_end_view(); purge_sys.clone_end_view();
if (truncate) {
trx_purge_truncate_history();
}
MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1); MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1);
MONITOR_INC_VALUE(MONITOR_PURGE_N_PAGE_HANDLED, n_pages_handled); MONITOR_INC_VALUE(MONITOR_PURGE_N_PAGE_HANDLED, n_pages_handled);