mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge 10.5 into 10.6
This commit is contained in:
@ -4205,6 +4205,30 @@ a b s1
|
||||
3 3 t2:1;min_t3_b:3
|
||||
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
|
||||
#
|
||||
#
|
||||
|
@ -7,6 +7,7 @@
|
||||
--source include/default_optimizer_switch.inc
|
||||
--source include/have_sequence.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_sequence.inc
|
||||
#
|
||||
# TODO:
|
||||
# Add queries with:
|
||||
@ -1859,6 +1860,30 @@ from t1;
|
||||
|
||||
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 # End of 10.5 tests
|
||||
--echo #
|
||||
|
@ -16,7 +16,7 @@ INSERT INTO t1 (f1, f2) VALUES(1,2);
|
||||
set global debug_dbug="+d,ib_purge_virtual_index_callback";
|
||||
connection con1;
|
||||
COMMIT;
|
||||
InnoDB 0 transactions not purged
|
||||
SET GLOBAL innodb_max_purge_lag_wait=1;
|
||||
connection con2;
|
||||
commit;
|
||||
disconnect con1;
|
||||
|
@ -78,7 +78,7 @@ SET DEBUG_SYNC= 'now WAIT_FOR uncommitted';
|
||||
# enable purge
|
||||
COMMIT;
|
||||
# wait for purge to process the deleted records.
|
||||
InnoDB 0 transactions not purged
|
||||
InnoDB 1 transactions not purged
|
||||
SET DEBUG_SYNC= 'now SIGNAL purged';
|
||||
connection default;
|
||||
/* connection default */ ALTER TABLE t1 ADD COLUMN c INT GENERATED ALWAYS AS(a+b), ADD INDEX idx (c), ALGORITHM=INPLACE, LOCK=SHARED;
|
||||
|
@ -23,7 +23,7 @@ set global debug_dbug="+d,ib_purge_virtual_index_callback";
|
||||
connection con1;
|
||||
COMMIT;
|
||||
|
||||
--source ../innodb/include/wait_all_purged.inc
|
||||
SET GLOBAL innodb_max_purge_lag_wait=1;
|
||||
|
||||
connection con2;
|
||||
commit;
|
||||
|
@ -113,7 +113,9 @@ SET DEBUG_SYNC= 'now WAIT_FOR uncommitted';
|
||||
COMMIT;
|
||||
|
||||
--echo # wait for purge to process the deleted records.
|
||||
let $wait_all_purged = 1;
|
||||
--source ../../innodb/include/wait_all_purged.inc
|
||||
let $wait_all_purged = 0;
|
||||
|
||||
SET DEBUG_SYNC= 'now SIGNAL purged';
|
||||
|
||||
|
@ -1,31 +1,34 @@
|
||||
SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
|
||||
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
|
||||
connect prevent_purge,localhost,root,,;
|
||||
start transaction with consistent snapshot;
|
||||
connect con_del_1,localhost,root,,;
|
||||
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';
|
||||
DELETE FROM t WHERE b = 20;
|
||||
DELETE FROM t WHERE b = 20 # trx_1;
|
||||
connect con_ins_1,localhost,root,,;
|
||||
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 = '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,,;
|
||||
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_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;
|
||||
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 WAIT_FOR first_ins_row_inserted';
|
||||
connection con_del_1;
|
||||
connection default;
|
||||
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';
|
||||
connection con_del_2;
|
||||
connection con_ins_1;
|
||||
|
@ -19,7 +19,7 @@ BEGIN;
|
||||
UPDATE t1 SET b=4 WHERE a=3;
|
||||
disconnect prevent_purge;
|
||||
connection default;
|
||||
InnoDB 0 transactions not purged
|
||||
SET GLOBAL innodb_max_purge_lag_wait=1;
|
||||
connection con1;
|
||||
ROLLBACK;
|
||||
disconnect con1;
|
||||
|
@ -390,11 +390,12 @@ connection stop_purge;
|
||||
COMMIT;
|
||||
disconnect stop_purge;
|
||||
connection default;
|
||||
InnoDB 0 transactions not purged
|
||||
InnoDB 1 transactions not purged
|
||||
SET DEBUG_SYNC='now SIGNAL s2';
|
||||
connection dml;
|
||||
disconnect dml;
|
||||
connection default;
|
||||
InnoDB 0 transactions not purged
|
||||
SET DEBUG_SYNC=RESET;
|
||||
DROP TABLE t1;
|
||||
# End of 10.3 tests
|
||||
|
@ -1,5 +1,6 @@
|
||||
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
|
||||
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
|
||||
#
|
||||
@ -16,7 +17,7 @@ COMMIT;
|
||||
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||
connection default;
|
||||
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;
|
||||
disconnect prevent_purge;
|
||||
InnoDB 0 transactions not purged
|
||||
|
@ -5,7 +5,7 @@ source include/have_debug_sync.inc;
|
||||
|
||||
SET @save_freq=@@GLOBAL.innodb_purge_rseg_truncate_frequency;
|
||||
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
|
||||
--connect(prevent_purge,localhost,root,,)
|
||||
@ -14,20 +14,20 @@ start transaction with consistent snapshot;
|
||||
--connect(con_del_1,localhost,root,,)
|
||||
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';
|
||||
--send DELETE FROM t WHERE b = 20
|
||||
--send DELETE FROM t WHERE b = 20 # trx_1
|
||||
|
||||
--connect(con_ins_1,localhost,root,,)
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished';
|
||||
# It's supposed the following INSERT will be suspended just after
|
||||
# lock_wait_start syncpoint, and will be awaken
|
||||
# after the previous DELETE commits. ib_after_row_insert will be executed
|
||||
# after the INSERT is woken up. The previous DELETE will wait for
|
||||
# after trx_1 DELETE commits. ib_after_row_insert will be executed
|
||||
# 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.
|
||||
# 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.
|
||||
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';
|
||||
--send INSERT INTO t VALUES(10, 20)
|
||||
--send INSERT INTO t VALUES(10, 20) # trx_2
|
||||
|
||||
--connect(con_del_2,localhost,root,,)
|
||||
# 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 DEBUG_SYNC = 'now WAIT_FOR first_ins_locked';
|
||||
SET DEBUG_SYNC = 'lock_wait_start SIGNAL second_del_locked';
|
||||
###############################################################################
|
||||
# This DELETE is locked by the previous DELETE, after that DELETE is
|
||||
# committed, it will still be locked by the next INSERT on delete-marked
|
||||
# heap_no 2 record. After that INSERT inserted the record with heap_no 3,
|
||||
# and after heap_no 2 record is purged, this DELETE will be unlocked and
|
||||
##############################################################################
|
||||
# trx_3 DELETE is locked by trx_1 DELETE, after trx_1 DELETE is
|
||||
# committed, it will still be locked by trx_2 INSERT on delete-marked
|
||||
# heap_no 2 record. After trx_2 INSERT inserted the record with heap_no 3,
|
||||
# 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
|
||||
# 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
|
||||
# delete the record, inserted by the previous INSERT, and the last INSERT(see
|
||||
# by trx_2 INSERT, and after trx_2 INSERT is committed, it must
|
||||
# delete the record, inserted by trx_2 INSERT, and trx_4 INSERT(see
|
||||
# below) must be finished without error. But instead this DELETE restores
|
||||
# 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.
|
||||
###############################################################################
|
||||
--send DELETE FROM t WHERE b = 20
|
||||
--send DELETE FROM t WHERE b = 20 # trx_3
|
||||
|
||||
--connection default
|
||||
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 WAIT_FOR first_ins_row_inserted';
|
||||
--connection con_del_1
|
||||
@ -61,7 +63,8 @@ SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted';
|
||||
|
||||
--connection default
|
||||
--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';
|
||||
|
||||
--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.
|
||||
###############################################################################
|
||||
INSERT INTO t VALUES(30, 20);
|
||||
INSERT INTO t VALUES(30, 20); # trx_4
|
||||
|
||||
--disconnect con_ins_1
|
||||
--disconnect con_del_1
|
||||
|
@ -32,7 +32,7 @@ UPDATE t1 SET b=4 WHERE a=3;
|
||||
|
||||
--connection default
|
||||
# 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.
|
||||
--connection con1
|
||||
ROLLBACK;
|
||||
|
@ -450,7 +450,9 @@ COMMIT;
|
||||
disconnect stop_purge;
|
||||
|
||||
connection default;
|
||||
let $wait_all_purged = 1;
|
||||
--source include/wait_all_purged.inc
|
||||
let $wait_all_purged = 0;
|
||||
SET DEBUG_SYNC='now SIGNAL s2';
|
||||
|
||||
connection dml;
|
||||
@ -458,6 +460,7 @@ reap;
|
||||
disconnect dml;
|
||||
|
||||
connection default;
|
||||
--source include/wait_all_purged.inc
|
||||
SET DEBUG_SYNC=RESET;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
@ -6,6 +6,7 @@ if ($have_debug) {
|
||||
|
||||
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
|
||||
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
|
||||
--source include/wait_all_purged.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-17793 Crash in purge after instant DROP and emptying the table
|
||||
@ -27,8 +28,7 @@ START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||
connection default;
|
||||
|
||||
ALTER TABLE t1 ADD COLUMN extra TINYINT UNSIGNED NOT NULL DEFAULT 42;
|
||||
let $wait_all_purged= 1;
|
||||
--source include/wait_all_purged.inc
|
||||
SET GLOBAL innodb_max_purge_lag_wait=1;
|
||||
ALTER TABLE t1 DROP extra;
|
||||
disconnect prevent_purge;
|
||||
let $wait_all_purged= 0;
|
||||
|
@ -1,6 +1,10 @@
|
||||
--source include/have_innodb.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.
|
||||
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
|
||||
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
|
||||
|
@ -3030,8 +3030,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||
restore_nonrange_trees(¶m, tree, backup_keys);
|
||||
if ((group_trp= get_best_group_min_max(¶m, tree, read_time)))
|
||||
{
|
||||
param.table->opt_range_condition_rows= MY_MIN(group_trp->records,
|
||||
head->stat_records());
|
||||
set_if_smaller(param.table->opt_range_condition_rows,
|
||||
group_trp->records);
|
||||
Json_writer_object grp_summary(thd, "best_group_range_summary");
|
||||
|
||||
if (unlikely(thd->trace_started()))
|
||||
|
@ -19422,10 +19422,17 @@ static MYSQL_SYSVAR_ULONG(purge_rseg_truncate_frequency,
|
||||
" purge rollback segment(s) on every Nth iteration of purge invocation",
|
||||
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,
|
||||
PLUGIN_VAR_OPCMDARG,
|
||||
"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,
|
||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||
|
@ -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 */
|
||||
void
|
||||
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.
|
||||
@param n_tasks number of purge tasks to submit to the queue
|
||||
@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 */
|
||||
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
|
||||
scheduled for purge. */
|
||||
@ -285,6 +292,18 @@ public:
|
||||
typically via purge_sys_t::view_guard. */
|
||||
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(). */
|
||||
template<bool also_end_view= false>
|
||||
void clone_oldest_view()
|
||||
|
@ -47,6 +47,7 @@ Created 3/14/1997 Heikki Tuuri
|
||||
#include "handler.h"
|
||||
#include "ha_innodb.h"
|
||||
#include "fil0fil.h"
|
||||
#include "debug_sync.h"
|
||||
#include <mysql/service_thd_mdl.h>
|
||||
|
||||
/*************************************************************************
|
||||
@ -631,7 +632,17 @@ row_purge_del_mark(
|
||||
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()
|
||||
@ -850,6 +861,9 @@ skip_secondaries:
|
||||
buf_page_get(page_id_t(rseg.space->id,
|
||||
page_no),
|
||||
0, RW_X_LATCH, &mtr)) {
|
||||
block->page.set_accessed();
|
||||
buf_page_make_young_if_needed(&block->page);
|
||||
|
||||
byte* data_field = block->page.frame
|
||||
+ offset + internal_offset;
|
||||
|
||||
|
@ -1296,17 +1296,14 @@ static tpool::waitable_task purge_coordinator_task
|
||||
static tpool::timer *purge_coordinator_timer;
|
||||
|
||||
/** Wake up the purge threads if there is work to do. */
|
||||
void
|
||||
srv_wake_purge_thread_if_not_active()
|
||||
void 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()
|
||||
&& trx_sys.history_exists()) {
|
||||
if(++purge_state.m_running == 1) {
|
||||
srv_thread_pool->submit_task(&purge_coordinator_task);
|
||||
}
|
||||
}
|
||||
if (purge_sys.enabled() && !purge_sys.paused() &&
|
||||
(srv_undo_log_truncate || trx_sys.history_exists()) &&
|
||||
++purge_state.m_running == 1)
|
||||
srv_thread_pool->submit_task(&purge_coordinator_task);
|
||||
}
|
||||
|
||||
/** @return whether the purge tasks are active */
|
||||
@ -1697,13 +1694,20 @@ fewer_threads:
|
||||
m_history_length= history_size;
|
||||
|
||||
if (!history_size)
|
||||
{
|
||||
srv_dml_needed_delay= 0;
|
||||
else if (trx_purge(n_use_threads, history_size,
|
||||
!(++count % srv_purge_rseg_truncate_frequency) ||
|
||||
purge_sys.truncate.current ||
|
||||
(srv_shutdown_state != SRV_SHUTDOWN_NONE &&
|
||||
srv_fast_shutdown == 0)))
|
||||
continue;
|
||||
trx_purge_truncate_history();
|
||||
}
|
||||
else
|
||||
{
|
||||
ulint n_pages_handled= trx_purge(n_use_threads, history_size);
|
||||
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);
|
||||
else if (m_running == sigcount)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
/** Free an undo log segment.
|
||||
@param block rollback segment header page
|
||||
@param mtr mini-transaction */
|
||||
@ -561,10 +560,11 @@ __attribute__((optimize(0)))
|
||||
# endif
|
||||
#endif
|
||||
/**
|
||||
Removes unnecessary history data from rollback segments. NOTE that when this
|
||||
function is called, the caller must not have any latches on undo log pages!
|
||||
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!
|
||||
*/
|
||||
TRANSACTIONAL_TARGET static void trx_purge_truncate_history()
|
||||
TRANSACTIONAL_TARGET void trx_purge_truncate_history()
|
||||
{
|
||||
ut_ad(purge_sys.head <= purge_sys.tail);
|
||||
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=
|
||||
trx_purge_truncate_rseg_history(rseg, head,
|
||||
!rseg.is_referenced() &&
|
||||
rseg.needs_purge <= head.trx_no))
|
||||
purge_sys.sees(rseg.needs_purge)))
|
||||
err= e;
|
||||
rseg.latch.wr_unlock();
|
||||
}
|
||||
@ -644,7 +644,7 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history()
|
||||
|
||||
rseg.latch.rd_lock(SRW_LOCK_CALL);
|
||||
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:
|
||||
rseg.latch.rd_unlock();
|
||||
@ -658,7 +658,7 @@ not_free:
|
||||
for (const trx_undo_t *undo= UT_LIST_GET_FIRST(rseg.undo_cached); 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;
|
||||
else
|
||||
cached+= undo->size;
|
||||
@ -791,7 +791,7 @@ not_free:
|
||||
continue;
|
||||
|
||||
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,
|
||||
&rseg - trx_sys.rseg_array,
|
||||
@ -1264,10 +1264,8 @@ TRANSACTIONAL_INLINE void purge_sys_t::clone_end_view()
|
||||
Run a purge batch.
|
||||
@param n_tasks number of purge tasks to submit to the queue
|
||||
@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 */
|
||||
TRANSACTIONAL_TARGET
|
||||
ulint trx_purge(ulint n_tasks, ulint history_size, bool truncate)
|
||||
TRANSACTIONAL_TARGET ulint trx_purge(ulint n_tasks, ulint history_size)
|
||||
{
|
||||
que_thr_t* thr = NULL;
|
||||
ulint n_pages_handled;
|
||||
@ -1319,10 +1317,6 @@ ulint trx_purge(ulint n_tasks, ulint history_size, bool truncate)
|
||||
|
||||
purge_sys.clone_end_view();
|
||||
|
||||
if (truncate) {
|
||||
trx_purge_truncate_history();
|
||||
}
|
||||
|
||||
MONITOR_INC_VALUE(MONITOR_PURGE_INVOKED, 1);
|
||||
MONITOR_INC_VALUE(MONITOR_PURGE_N_PAGE_HANDLED, n_pages_handled);
|
||||
|
||||
|
Reference in New Issue
Block a user