Merge 10.6 into 10.9

This commit is contained in:
Marko Mäkelä 2023-05-19 15:11:06 +03:00
commit 2ec42f793d
9 changed files with 90 additions and 82 deletions

2
.github/CODEOWNERS vendored
View File

@ -1,2 +0,0 @@
/debian @ottok

35
debian/additions/innotop/innotop vendored Normal file → Executable file
View File

@ -20,6 +20,9 @@
# Street, Fifth Floor, Boston, MA 02110-1335 USA # Street, Fifth Floor, Boston, MA 02110-1335 USA
use strict; use strict;
use warnings;
use utf8;
use feature ':5.16';
use warnings FATAL => 'all'; use warnings FATAL => 'all';
our $VERSION = '1.11.4'; our $VERSION = '1.11.4';
@ -265,7 +268,7 @@ sub get_dbh {
$dbh->do($sql); $dbh->do($sql);
MKDEBUG && _d('Enabling charset for STDOUT'); MKDEBUG && _d('Enabling charset for STDOUT');
if ( $charset eq 'utf8' ) { if ( $charset eq 'utf8' ) {
binmode(STDOUT, ':utf8') binmode(STDOUT, ':encoding(UTF-8)')
or die "Can't binmode(STDOUT, ':utf8'): $OS_ERROR"; or die "Can't binmode(STDOUT, ':utf8'): $OS_ERROR";
} }
else { else {
@ -612,6 +615,9 @@ sub ts_to_string {
sub parse_innodb_timestamp { sub parse_innodb_timestamp {
my $text = shift; my $text = shift;
if ( ! defined $text ) {
return (0, 0, 0, 0, 0, 0);
}
my ( $y, $m, $d, $h, $i, $s ) my ( $y, $m, $d, $h, $i, $s )
= $text =~ m/^(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)$/; = $text =~ m/^(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)$/;
die("Can't get timestamp from $text\n") unless $y; die("Can't get timestamp from $text\n") unless $y;
@ -803,7 +809,8 @@ sub parse_fk_transaction_error {
# TODO: write some tests for this # TODO: write some tests for this
sub parse_innodb_record_dump { sub parse_innodb_record_dump {
my ( $dump, $complete, $debug ) = @_; my ( $dump, $complete, $debug ) = @_;
return undef unless $dump; # Use bare return as recommend in page 199 of PBP
return unless $dump;
my $result = {}; my $result = {};
@ -6769,6 +6776,9 @@ sub set_precision {
my ( $num, $precision ) = @_; my ( $num, $precision ) = @_;
$num = 0 unless defined $num; $num = 0 unless defined $num;
$precision = $config{num_digits}->{val} if !defined $precision; $precision = $config{num_digits}->{val} if !defined $precision;
if ( $num eq "" ) {
$num = int(0);
}
sprintf("%.${precision}f", $num); sprintf("%.${precision}f", $num);
} }
@ -6777,6 +6787,9 @@ sub set_precision {
sub percent { sub percent {
my ( $num ) = @_; my ( $num ) = @_;
$num = 0 unless defined $num; $num = 0 unless defined $num;
if ( $num eq "" ) {
$num = int(0);
}
my $digits = $config{num_digits}->{val}; my $digits = $config{num_digits}->{val};
return sprintf("%.${digits}f", $num * 100) return sprintf("%.${digits}f", $num * 100)
. ($config{show_percent}->{val} ? '%' : ''); . ($config{show_percent}->{val} ? '%' : '');
@ -6841,7 +6854,7 @@ sub make_color_func {
push @criteria, push @criteria,
"( defined \$set->{$spec->{col}} && \$set->{$spec->{col}} $spec->{op} $val ) { return '$spec->{color}'; }"; "( defined \$set->{$spec->{col}} && \$set->{$spec->{col}} $spec->{op} $val ) { return '$spec->{color}'; }";
} }
return undef unless @criteria; return unless @criteria;
my $sub = eval 'sub { my ( $set ) = @_; if ' . join(" elsif ", @criteria) . '}'; my $sub = eval 'sub { my ( $set ) = @_; if ' . join(" elsif ", @criteria) . '}';
die if $EVAL_ERROR; die if $EVAL_ERROR;
return $sub; return $sub;
@ -7521,10 +7534,10 @@ sub choose_connections {
sub do_stmt { sub do_stmt {
my ( $cxn, $stmt_name, @args ) = @_; my ( $cxn, $stmt_name, @args ) = @_;
return undef if $file; return if $file;
# Test if the cxn should not even be tried # Test if the cxn should not even be tried
return undef if $dbhs{$cxn} return if $dbhs{$cxn}
&& $dbhs{$cxn}->{failed} && $dbhs{$cxn}->{failed}
&& ( !$dbhs{$cxn}->{dbh} || !$dbhs{$cxn}->{dbh}->{Active} || $dbhs{$cxn}->{mode} eq $config{mode}->{val} ); && ( !$dbhs{$cxn}->{dbh} || !$dbhs{$cxn}->{dbh}->{Active} || $dbhs{$cxn}->{mode} eq $config{mode}->{val} );
@ -7596,10 +7609,10 @@ sub handle_cxn_error {
sub do_query { sub do_query {
my ( $cxn, $query ) = @_; my ( $cxn, $query ) = @_;
return undef if $file; return if $file;
# Test if the cxn should not even be tried # Test if the cxn should not even be tried
return undef if $dbhs{$cxn} return if $dbhs{$cxn}
&& $dbhs{$cxn}->{failed} && $dbhs{$cxn}->{failed}
&& ( !$dbhs{$cxn}->{dbh} || !$dbhs{$cxn}->{dbh}->{Active} || $dbhs{$cxn}->{mode} eq $config{mode}->{val} ); && ( !$dbhs{$cxn}->{dbh} || !$dbhs{$cxn}->{dbh}->{Active} || $dbhs{$cxn}->{mode} eq $config{mode}->{val} );
@ -7781,7 +7794,7 @@ sub compile_select_stmt {
sub compile_filter { sub compile_filter {
my ( $text ) = @_; my ( $text ) = @_;
my ( $sub, $err ); my ( $sub, $err );
eval "\$sub = sub { my \$set = shift; $text }"; eval { $sub = sub { my $set = shift; $text } };
if ( $EVAL_ERROR ) { if ( $EVAL_ERROR ) {
$EVAL_ERROR =~ s/at \(eval.*$//; $EVAL_ERROR =~ s/at \(eval.*$//;
$sub = sub { return $EVAL_ERROR }; $sub = sub { return $EVAL_ERROR };
@ -8013,7 +8026,7 @@ sub load_config_plugins {
# First, find a list of all plugins that exist on disk, and get information about them. # First, find a list of all plugins that exist on disk, and get information about them.
my $dir = $config{plugin_dir}->{val}; my $dir = $config{plugin_dir}->{val};
foreach my $p_file ( <$dir/*.pm> ) { foreach my $p_file (glob($dir."/*.pm")) {
my ($package, $desc); my ($package, $desc);
eval { eval {
open my $p_in, "<", $p_file or die $OS_ERROR; open my $p_in, "<", $p_file or die $OS_ERROR;
@ -9192,7 +9205,7 @@ sub switch_var_set {
# edit_stmt_sleep_times {{{3 # edit_stmt_sleep_times {{{3
sub edit_stmt_sleep_times { sub edit_stmt_sleep_times {
$clear_screen_sub->(); $clear_screen_sub->();
my $stmt = prompt_list('Specify a statement', '', sub { return sort keys %stmt_maker_for }); my $stmt = prompt_list('Specify a statement', '', sub { my @tmparray = sort keys %stmt_maker_for; return @tmparray });
return unless $stmt && exists $stmt_maker_for{$stmt}; return unless $stmt && exists $stmt_maker_for{$stmt};
$clear_screen_sub->(); $clear_screen_sub->();
my $curr_val = $stmt_sleep_time_for{$stmt} || 0; my $curr_val = $stmt_sleep_time_for{$stmt} || 0;
@ -9843,7 +9856,7 @@ sub get_slave_status {
sub is_func { sub is_func {
my ( $word ) = @_; my ( $word ) = @_;
return defined(&$word) return defined(&$word)
|| eval "my \$x= sub { $word }; 1" || eval { my $x = sub { $word }; 1 }
|| $EVAL_ERROR !~ m/^Bareword/; || $EVAL_ERROR !~ m/^Bareword/;
} }

View File

@ -966,12 +966,20 @@ uint32_t fil_space_t::flush_freed(bool writable)
mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex); mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex);
mysql_mutex_assert_not_owner(&buf_pool.mutex); mysql_mutex_assert_not_owner(&buf_pool.mutex);
for (;;)
{
freed_range_mutex.lock(); freed_range_mutex.lock();
if (freed_ranges.empty() || log_sys.get_flushed_lsn() < get_last_freed_lsn()) if (freed_ranges.empty())
{ {
freed_range_mutex.unlock(); freed_range_mutex.unlock();
return 0; return 0;
} }
const lsn_t flush_lsn= last_freed_lsn;
if (log_sys.get_flushed_lsn() >= flush_lsn)
break;
freed_range_mutex.unlock();
log_write_up_to(flush_lsn, true);
}
const unsigned physical{physical_size()}; const unsigned physical{physical_size()};

View File

@ -265,9 +265,6 @@ buf_read_page_low(
buf_page_t* bpage; buf_page_t* bpage;
if (buf_dblwr.is_inside(page_id)) { if (buf_dblwr.is_inside(page_id)) {
ib::error() << "Trying to read doublewrite buffer page "
<< page_id;
ut_ad(0);
space->release(); space->release();
return DB_PAGE_CORRUPTED; return DB_PAGE_CORRUPTED;
} }

View File

@ -638,8 +638,6 @@ public:
/** Close all tablespace files at shutdown */ /** Close all tablespace files at shutdown */
static void close_all(); static void close_all();
/** @return last_freed_lsn */
lsn_t get_last_freed_lsn() { return last_freed_lsn; }
/** Update last_freed_lsn */ /** Update last_freed_lsn */
void update_last_freed_lsn(lsn_t lsn) { last_freed_lsn= lsn; } void update_last_freed_lsn(lsn_t lsn) { last_freed_lsn= lsn; }

View File

@ -1053,7 +1053,7 @@ public:
void close(); void close();
/** @return total number of active (non-prepared) transactions */ /** @return total number of active (non-prepared) transactions */
ulint any_active_transactions(); size_t any_active_transactions(size_t *prepared= nullptr);
/** /**

View File

@ -1514,7 +1514,7 @@ void srv_master_callback(void*)
} }
/** @return whether purge should exit due to shutdown */ /** @return whether purge should exit due to shutdown */
static bool srv_purge_should_exit() static bool srv_purge_should_exit(size_t old_history_size)
{ {
ut_ad(srv_shutdown_state <= SRV_SHUTDOWN_CLEANUP); ut_ad(srv_shutdown_state <= SRV_SHUTDOWN_CLEANUP);
@ -1525,8 +1525,12 @@ static bool srv_purge_should_exit()
return true; return true;
/* Slow shutdown was requested. */ /* Slow shutdown was requested. */
size_t prepared, active= trx_sys.any_active_transactions(&prepared);
const size_t history_size= trx_sys.history_size(); const size_t history_size= trx_sys.history_size();
if (history_size)
if (!history_size);
else if (!active && history_size == old_history_size && prepared);
else
{ {
static time_t progress_time; static time_t progress_time;
time_t now= time(NULL); time_t now= time(NULL);
@ -1543,7 +1547,7 @@ static bool srv_purge_should_exit()
return false; return false;
} }
return !trx_sys.any_active_transactions(); return !active;
} }
/*********************************************************************//** /*********************************************************************//**
@ -1686,7 +1690,7 @@ fewer_threads:
break; break;
} }
if (!srv_purge_should_exit()) if (!srv_purge_should_exit(history_size))
goto loop; goto loop;
} }
@ -1882,10 +1886,14 @@ ulint srv_get_task_queue_length()
/** Shut down the purge threads. */ /** Shut down the purge threads. */
void srv_purge_shutdown() void srv_purge_shutdown()
{ {
if (purge_sys.enabled()) { if (purge_sys.enabled())
{
if (!srv_fast_shutdown && !opt_bootstrap) if (!srv_fast_shutdown && !opt_bootstrap)
srv_update_purge_thread_count(innodb_purge_threads_MAX); srv_update_purge_thread_count(innodb_purge_threads_MAX);
while(!srv_purge_should_exit()) { size_t history_size= trx_sys.history_size();
while (!srv_purge_should_exit(history_size))
{
history_size= trx_sys.history_size();
ut_a(!purge_sys.paused()); ut_a(!purge_sys.paused());
srv_wake_purge_thread_if_not_active(); srv_wake_purge_thread_if_not_active();
purge_coordinator_task.wait(); purge_coordinator_task.wait();

View File

@ -369,19 +369,6 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
undo = NULL; undo = NULL;
} }
MY_ATTRIBUTE((nonnull, warn_unused_result))
/** Remove undo log header from the history list.
@param[in,out] rseg rollback segment header page
@param[in] log undo log segment header page
@param[in] offset byte offset in the undo log segment header page
@param[in,out] mtr mini-transaction */
static dberr_t trx_purge_remove_log_hdr(buf_block_t *rseg, buf_block_t* log,
uint16_t offset, mtr_t *mtr)
{
return flst_remove(rseg, TRX_RSEG + TRX_RSEG_HISTORY, log,
uint16_t(offset + TRX_UNDO_HISTORY_NODE), mtr);
}
/** 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 */
@ -391,7 +378,7 @@ static void trx_purge_free_segment(buf_block_t *block, mtr_t &mtr)
block->page.frame, &mtr)) block->page.frame, &mtr))
{ {
block->fix(); block->fix();
const page_id_t id{block->page.id()}; ut_d(const page_id_t id{block->page.id()});
mtr.commit(); mtr.commit();
/* NOTE: If the server is killed after the log that was produced /* NOTE: If the server is killed after the log that was produced
up to this point was written, and before the log from the mtr.commit() up to this point was written, and before the log from the mtr.commit()
@ -403,15 +390,7 @@ static void trx_purge_free_segment(buf_block_t *block, mtr_t &mtr)
log_free_check(); log_free_check();
mtr.start(); mtr.start();
block->page.lock.x_lock(); block->page.lock.x_lock();
if (UNIV_UNLIKELY(block->page.id() != id)) ut_ad(block->page.id() == id);
{
block->unfix();
block->page.lock.x_unlock();
block= buf_page_get_gen(id, 0, RW_X_LATCH, nullptr, BUF_GET, &mtr);
if (!block)
return;
}
else
mtr.memo_push(block, MTR_MEMO_PAGE_X_MODIFY); mtr.memo_push(block, MTR_MEMO_PAGE_X_MODIFY);
} }
@ -434,7 +413,6 @@ trx_purge_truncate_rseg_history(trx_rseg_t& rseg,
mtr.start(); mtr.start();
dberr_t err; dberr_t err;
reget:
buf_block_t *rseg_hdr= rseg.get(&mtr, &err); buf_block_t *rseg_hdr= rseg.get(&mtr, &err);
if (!rseg_hdr) if (!rseg_hdr)
{ {
@ -474,18 +452,16 @@ loop:
TRX_UNDO_HISTORY_NODE); TRX_UNDO_HISTORY_NODE);
prev_hdr_addr.boffset= static_cast<uint16_t>(prev_hdr_addr.boffset - prev_hdr_addr.boffset= static_cast<uint16_t>(prev_hdr_addr.boffset -
TRX_UNDO_HISTORY_NODE); TRX_UNDO_HISTORY_NODE);
err= trx_purge_remove_log_hdr(rseg_hdr, b, hdr_addr.boffset, &mtr);
err= flst_remove(rseg_hdr, TRX_RSEG + TRX_RSEG_HISTORY, b,
uint16_t(hdr_addr.boffset + TRX_UNDO_HISTORY_NODE), &mtr);
if (UNIV_UNLIKELY(err != DB_SUCCESS)) if (UNIV_UNLIKELY(err != DB_SUCCESS))
goto func_exit; goto func_exit;
rseg_hdr->fix(); rseg_hdr->fix();
if (mach_read_from_2(b->page.frame + hdr_addr.boffset + TRX_UNDO_NEXT_LOG) || if (mach_read_from_2(b->page.frame + hdr_addr.boffset + TRX_UNDO_NEXT_LOG))
rseg.is_referenced() || /* We cannot free the entire undo log segment. */;
rseg.needs_purge > (purge_sys.head.trx_no
? purge_sys.head.trx_no
: purge_sys.tail.trx_no))
/* We cannot free the entire undo page. */;
else else
{ {
const uint32_t seg_size= const uint32_t seg_size=
@ -535,12 +511,7 @@ loop:
log_free_check(); log_free_check();
mtr.start(); mtr.start();
rseg_hdr->page.lock.x_lock(); rseg_hdr->page.lock.x_lock();
if (UNIV_UNLIKELY(rseg_hdr->page.id() != rseg.page_id())) ut_ad(rseg_hdr->page.id() == rseg.page_id());
{
rseg_hdr->unfix();
rseg_hdr->page.lock.x_unlock();
goto reget;
}
mtr.memo_push(rseg_hdr, MTR_MEMO_PAGE_X_MODIFY); mtr.memo_push(rseg_hdr, MTR_MEMO_PAGE_X_MODIFY);
goto loop; goto loop;
@ -613,6 +584,7 @@ TRANSACTIONAL_TARGET static void trx_purge_truncate_history()
{ {
ut_ad(rseg.is_persistent()); ut_ad(rseg.is_persistent());
rseg.latch.wr_lock(SRW_LOCK_CALL); rseg.latch.wr_lock(SRW_LOCK_CALL);
if (!rseg.is_referenced() && rseg.needs_purge <= head.trx_no)
if (dberr_t e= trx_purge_truncate_rseg_history(rseg, head)) if (dberr_t e= trx_purge_truncate_rseg_history(rseg, head))
err= e; err= e;
rseg.latch.wr_unlock(); rseg.latch.wr_unlock();

View File

@ -343,15 +343,29 @@ trx_sys_t::close()
} }
/** @return total number of active (non-prepared) transactions */ /** @return total number of active (non-prepared) transactions */
ulint trx_sys_t::any_active_transactions() size_t trx_sys_t::any_active_transactions(size_t *prepared)
{ {
uint32_t total_trx= 0; size_t total_trx= 0, prepared_trx= 0;
trx_sys.trx_list.for_each([&total_trx](const trx_t &trx) { trx_sys.trx_list.for_each([&](const trx_t &trx) {
if (trx.state == TRX_STATE_COMMITTED_IN_MEMORY || switch (trx.state) {
(trx.state == TRX_STATE_ACTIVE && trx.id)) case TRX_STATE_NOT_STARTED:
break;
case TRX_STATE_ACTIVE:
if (!trx.id)
break;
/* fall through */
case TRX_STATE_COMMITTED_IN_MEMORY:
total_trx++; total_trx++;
break;
case TRX_STATE_PREPARED:
case TRX_STATE_PREPARED_RECOVERED:
prepared_trx++;
}
}); });
if (prepared)
*prepared= prepared_trx;
return total_trx; return total_trx;
} }