summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2022-06-23 13:46:23 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2022-06-23 13:46:23 +0300
commitb3563098400b8fd954fb779c6868be0c7bd318e5 (patch)
tree1bc6e8f4b596a09234d890b5ca57653ecabb213f
parent3a66c0153afde8051590d9dea1f40b48d094afd8 (diff)
parent5d0496c749dcdbed5974ccbd9f679a778982b4a8 (diff)
downloadmariadb-git-b3563098400b8fd954fb779c6868be0c7bd318e5.tar.gz
Merge 10.7 into 10.8
-rw-r--r--mysql-test/main/range.result19
-rw-r--r--mysql-test/main/range.test18
-rw-r--r--mysql-test/main/range_mrr_icp.result19
-rw-r--r--mysql-test/suite/encryption/r/innodb-redo-badkey.result2
-rw-r--r--mysql-test/suite/encryption/t/innodb-redo-badkey.test2
-rw-r--r--sql/sql_select.cc14
-rw-r--r--storage/innobase/CMakeLists.txt1
-rw-r--r--storage/innobase/include/trx0purge.h4
-rw-r--r--storage/innobase/include/trx0rec.h49
-rw-r--r--storage/innobase/include/trx0rec.inl73
-rw-r--r--storage/innobase/include/trx0undo.h2
-rw-r--r--storage/innobase/log/log0recv.cc28
-rw-r--r--storage/innobase/row/row0purge.cc2
-rw-r--r--storage/innobase/row/row0undo.cc11
-rw-r--r--storage/innobase/trx/trx0purge.cc35
-rw-r--r--storage/innobase/trx/trx0undo.cc4
-rw-r--r--tpool/tpool_generic.cc17
17 files changed, 142 insertions, 158 deletions
diff --git a/mysql-test/main/range.result b/mysql-test/main/range.result
index 11bf47f4500..9edf7c5a070 100644
--- a/mysql-test/main/range.result
+++ b/mysql-test/main/range.result
@@ -3697,6 +3697,25 @@ SELECT * FROM t1 LEFT JOIN t2 ON a = pk WHERE b >= 0 AND pk IS NULL;
a pk b
DROP TABLE t1, t2;
SET @@optimizer_switch= @save_optimizer_switch;
+
+# MDEV-28858 Wrong result with table elimination combined with
+# not_null_range_scan
+#
+CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (10,1),(null,2);
+CREATE TABLE t2 (pk INT PRIMARY KEY) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(2);
+SET @save_optimizer_switch= @@optimizer_switch;
+SET optimizer_switch= 'not_null_range_scan=on';
+SELECT t1.b FROM t1 LEFT JOIN t2 ON t1.a = t2.pk WHERE t1.a IS NULL ORDER BY t1.b;
+b
+2
+SET optimizer_switch= 'not_null_range_scan=off';
+SELECT t1.b FROM t1 LEFT JOIN t2 ON t1.a = t2.pk WHERE t1.a IS NULL ORDER BY t1.b;
+b
+2
+SET @@optimizer_switch=@save_optimizer_switch;
+drop table t1,t2;
#
# End of 10.5 tests
#
diff --git a/mysql-test/main/range.test b/mysql-test/main/range.test
index 6a2e318e732..a785726cb22 100644
--- a/mysql-test/main/range.test
+++ b/mysql-test/main/range.test
@@ -2492,6 +2492,24 @@ DROP TABLE t1, t2;
SET @@optimizer_switch= @save_optimizer_switch;
+--echo
+--echo # MDEV-28858 Wrong result with table elimination combined with
+--echo # not_null_range_scan
+--echo #
+
+CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (10,1),(null,2);
+CREATE TABLE t2 (pk INT PRIMARY KEY) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(2);
+
+SET @save_optimizer_switch= @@optimizer_switch;
+SET optimizer_switch= 'not_null_range_scan=on';
+SELECT t1.b FROM t1 LEFT JOIN t2 ON t1.a = t2.pk WHERE t1.a IS NULL ORDER BY t1.b;
+SET optimizer_switch= 'not_null_range_scan=off';
+SELECT t1.b FROM t1 LEFT JOIN t2 ON t1.a = t2.pk WHERE t1.a IS NULL ORDER BY t1.b;
+SET @@optimizer_switch=@save_optimizer_switch;
+drop table t1,t2;
+
--echo #
--echo # End of 10.5 tests
--echo #
diff --git a/mysql-test/main/range_mrr_icp.result b/mysql-test/main/range_mrr_icp.result
index 6da0fc9bd68..60e1f5ac3f3 100644
--- a/mysql-test/main/range_mrr_icp.result
+++ b/mysql-test/main/range_mrr_icp.result
@@ -3686,6 +3686,25 @@ SELECT * FROM t1 LEFT JOIN t2 ON a = pk WHERE b >= 0 AND pk IS NULL;
a pk b
DROP TABLE t1, t2;
SET @@optimizer_switch= @save_optimizer_switch;
+
+# MDEV-28858 Wrong result with table elimination combined with
+# not_null_range_scan
+#
+CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (10,1),(null,2);
+CREATE TABLE t2 (pk INT PRIMARY KEY) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(2);
+SET @save_optimizer_switch= @@optimizer_switch;
+SET optimizer_switch= 'not_null_range_scan=on';
+SELECT t1.b FROM t1 LEFT JOIN t2 ON t1.a = t2.pk WHERE t1.a IS NULL ORDER BY t1.b;
+b
+2
+SET optimizer_switch= 'not_null_range_scan=off';
+SELECT t1.b FROM t1 LEFT JOIN t2 ON t1.a = t2.pk WHERE t1.a IS NULL ORDER BY t1.b;
+b
+2
+SET @@optimizer_switch=@save_optimizer_switch;
+drop table t1,t2;
#
# End of 10.5 tests
#
diff --git a/mysql-test/suite/encryption/r/innodb-redo-badkey.result b/mysql-test/suite/encryption/r/innodb-redo-badkey.result
index b1c4ae913fa..aa4fcde7a6c 100644
--- a/mysql-test/suite/encryption/r/innodb-redo-badkey.result
+++ b/mysql-test/suite/encryption/r/innodb-redo-badkey.result
@@ -6,6 +6,8 @@ call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]
call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t[12]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]");
call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t[12]\\.ibd'");
call mtr.add_suppression("InnoDB: Failed to read page .* from file '.*'");
+call mtr.add_suppression("InnoDB: OPT_PAGE_CHECKSUM mismatch");
+call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore corruption");
call mtr.add_suppression("InnoDB: Plugin initialization aborted");
call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed");
call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space=");
diff --git a/mysql-test/suite/encryption/t/innodb-redo-badkey.test b/mysql-test/suite/encryption/t/innodb-redo-badkey.test
index 81febb92c5b..5ba4f86ed5c 100644
--- a/mysql-test/suite/encryption/t/innodb-redo-badkey.test
+++ b/mysql-test/suite/encryption/t/innodb-redo-badkey.test
@@ -15,6 +15,8 @@ call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]
call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t[12]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]");
call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t[12]\\.ibd'");
call mtr.add_suppression("InnoDB: Failed to read page .* from file '.*'");
+call mtr.add_suppression("InnoDB: OPT_PAGE_CHECKSUM mismatch");
+call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore corruption");
call mtr.add_suppression("InnoDB: Plugin initialization aborted");
call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed");
# for innodb_checksum_algorithm=full_crc32 only
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 325c6dcb43e..254b475e8b3 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -29971,11 +29971,12 @@ bool build_notnull_conds_for_range_scans(JOIN *join, Item *cond,
DBUG_ENTER("build_notnull_conds_for_range_scans");
- for (JOIN_TAB *s= join->join_tab + join->const_tables ;
+ for (JOIN_TAB *s= join->join_tab;
s < join->join_tab + join->table_count ; s++)
{
/* Clear all needed bitmaps to mark found fields */
- if (allowed & s->table->map)
+ if ((allowed & s->table->map) &&
+ !(s->table->map && join->const_table_map))
bitmap_clear_all(&s->table->tmp_set);
}
@@ -29990,17 +29991,18 @@ bool build_notnull_conds_for_range_scans(JOIN *join, Item *cond,
For each table t from 'allowed' build a conjunction of NOT NULL predicates
constructed for all found fields if they are included in some indexes.
If the construction of the conjunction succeeds attach the formula to
- t->table->notnull_cond. The condition will be used to look for complementary
- range scans.
+ t->table->notnull_cond. The condition will be used to look for
+ complementary range scans.
*/
- for (JOIN_TAB *s= join->join_tab + join->const_tables ;
+ for (JOIN_TAB *s= join->join_tab ;
s < join->join_tab + join->table_count ; s++)
{
TABLE *tab= s->table;
List<Item> notnull_list;
Item *notnull_cond= 0;
- if (!(allowed & tab->map))
+ if (!(allowed & tab->map) ||
+ (s->table->map && join->const_table_map))
continue;
for (Field** field_ptr= tab->field; *field_ptr; field_ptr++)
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index 96613ba1b72..f5f8ad34242 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -234,7 +234,6 @@ SET(INNOBASE_SOURCES
include/trx0i_s.h
include/trx0purge.h
include/trx0rec.h
- include/trx0rec.inl
include/trx0roll.h
include/trx0rseg.h
include/trx0sys.h
diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h
index ef9111845a6..0896d9c79a1 100644
--- a/storage/innobase/include/trx0purge.h
+++ b/storage/innobase/include/trx0purge.h
@@ -33,10 +33,6 @@ Created 3/26/1996 Heikki Tuuri
#include <queue>
-/** A dummy undo record used as a return value when we have a whole undo log
-which needs no purge */
-extern trx_undo_rec_t trx_purge_dummy_rec;
-
/** Prepend the history list with an undo log.
Remove the undo log segment from the rseg slot if it is too big for reuse.
@param[in] trx transaction
diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h
index 28b049ca729..389fb98d063 100644
--- a/storage/innobase/include/trx0rec.h
+++ b/storage/innobase/include/trx0rec.h
@@ -24,8 +24,7 @@ Transaction undo log record
Created 3/26/1996 Heikki Tuuri
*******************************************************/
-#ifndef trx0rec_h
-#define trx0rec_h
+#pragma once
#include "trx0types.h"
#include "row0types.h"
@@ -37,29 +36,31 @@ Created 3/26/1996 Heikki Tuuri
/***********************************************************************//**
Copies the undo record to the heap.
-@return own: copy of undo log record */
-UNIV_INLINE
-trx_undo_rec_t*
-trx_undo_rec_copy(
-/*==============*/
- const trx_undo_rec_t* undo_rec, /*!< in: undo log record */
- mem_heap_t* heap); /*!< in: heap where copied */
-/**********************************************************************//**
-Reads the undo log record type.
-@return record type */
-UNIV_INLINE
-ulint
-trx_undo_rec_get_type(
-/*==================*/
- const trx_undo_rec_t* undo_rec); /*!< in: undo log record */
+@param undo_rec record in an undo log page
+@param heap memory heap
+@return copy of undo_rec
+@retval nullptr if the undo log record is corrupted */
+inline trx_undo_rec_t* trx_undo_rec_copy(const trx_undo_rec_t *undo_rec,
+ mem_heap_t *heap)
+{
+ const size_t offset= ut_align_offset(undo_rec, srv_page_size);
+ const size_t end= mach_read_from_2(undo_rec);
+ if (end <= offset || end >= srv_page_size - FIL_PAGE_DATA_END)
+ return nullptr;
+ const size_t len= end - offset;
+ trx_undo_rec_t *rec= static_cast<trx_undo_rec_t*>
+ (mem_heap_dup(heap, undo_rec, len));
+ mach_write_to_2(rec, len);
+ return rec;
+}
+
/**********************************************************************//**
Reads the undo log record number.
@return undo no */
-UNIV_INLINE
-undo_no_t
-trx_undo_rec_get_undo_no(
-/*=====================*/
- const trx_undo_rec_t* undo_rec); /*!< in: undo log record */
+inline undo_no_t trx_undo_rec_get_undo_no(const trx_undo_rec_t *undo_rec)
+{
+ return mach_u64_read_much_compressed(undo_rec + 3);
+}
/**********************************************************************//**
Returns the start of the undo record data area. */
@@ -345,7 +346,3 @@ inline table_id_t trx_undo_rec_get_table_id(const trx_undo_rec_t *rec)
mach_read_next_much_compressed(&rec);
return mach_read_next_much_compressed(&rec);
}
-
-#include "trx0rec.inl"
-
-#endif /* trx0rec_h */
diff --git a/storage/innobase/include/trx0rec.inl b/storage/innobase/include/trx0rec.inl
deleted file mode 100644
index 02244d68b6f..00000000000
--- a/storage/innobase/include/trx0rec.inl
+++ /dev/null
@@ -1,73 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/trx0rec.ic
-Transaction undo log record
-
-Created 3/26/1996 Heikki Tuuri
-*******************************************************/
-
-/**********************************************************************//**
-Reads from an undo log record the record type.
-@return record type */
-UNIV_INLINE
-ulint
-trx_undo_rec_get_type(
-/*==================*/
- const trx_undo_rec_t* undo_rec) /*!< in: undo log record */
-{
- return(mach_read_from_1(undo_rec + 2) & (TRX_UNDO_CMPL_INFO_MULT - 1));
-}
-
-/**********************************************************************//**
-Reads the undo log record number.
-@return undo no */
-UNIV_INLINE
-undo_no_t
-trx_undo_rec_get_undo_no(
-/*=====================*/
- const trx_undo_rec_t* undo_rec) /*!< in: undo log record */
-{
- const byte* ptr;
-
- ptr = undo_rec + 3;
-
- return(mach_u64_read_much_compressed(ptr));
-}
-
-/***********************************************************************//**
-Copies the undo record to the heap.
-@return own: copy of undo log record */
-UNIV_INLINE
-trx_undo_rec_t*
-trx_undo_rec_copy(
-/*==============*/
- const trx_undo_rec_t* undo_rec, /*!< in: undo log record */
- mem_heap_t* heap) /*!< in: heap where copied */
-{
- ulint len;
-
- len = mach_read_from_2(undo_rec)
- - ut_align_offset(undo_rec, srv_page_size);
- ut_ad(len < srv_page_size);
- trx_undo_rec_t* rec = static_cast<trx_undo_rec_t*>(
- mem_heap_dup(heap, undo_rec, len));
- mach_write_to_2(rec, len);
- return rec;
-}
diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h
index abfa7c61c1f..a8cddd6575d 100644
--- a/storage/innobase/include/trx0undo.h
+++ b/storage/innobase/include/trx0undo.h
@@ -360,7 +360,7 @@ public:
page_id_t get_page_id() const { return page_id; }
/** Handle the DML undo log and apply it on online indexes */
- void apply_undo_rec();
+ inline void apply_undo_rec();
~UndorecApplier()
{
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index df8e6376371..4999fe17278 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -1185,12 +1185,9 @@ inline size_t recv_sys_t::files_size()
@param[in] space_id the tablespace ID
@param[in] deleted whether this is a FILE_DELETE record
@param[in] lsn lsn of the redo log
-@param[in] store whether the redo log has to
- stored */
-static
-void
-fil_name_process(const char* name, ulint len, uint32_t space_id,
- bool deleted, lsn_t lsn, store_t store)
+@param[in] store whether the redo log has to be stored */
+static void fil_name_process(const char *name, ulint len, uint32_t space_id,
+ bool deleted, lsn_t lsn, store_t store)
{
if (srv_operation == SRV_OPERATION_BACKUP
|| srv_operation == SRV_OPERATION_BACKUP_NO_DEFER) {
@@ -1212,13 +1209,17 @@ fil_name_process(const char* name, ulint len, uint32_t space_id,
file_name_t& f = p.first->second;
- if (deleted) {
- /* Got FILE_DELETE */
- if (auto d = deferred_spaces.find(static_cast<uint32_t>(
- space_id))) {
+ if (auto d = deferred_spaces.find(space_id)) {
+ if (deleted) {
d->deleted = true;
+ goto got_deleted;
}
+ goto reload;
+ }
+ if (deleted) {
+got_deleted:
+ /* Got FILE_DELETE */
if (!p.second && f.status != file_name_t::DELETED) {
f.status = file_name_t::DELETED;
if (f.space != NULL) {
@@ -1230,6 +1231,7 @@ fil_name_process(const char* name, ulint len, uint32_t space_id,
ut_ad(f.space == NULL);
} else if (p.second // the first FILE_MODIFY or FILE_RENAME
|| f.name != fname.name) {
+reload:
fil_space_t* space;
/* Check if the tablespace file exists and contains
@@ -1240,8 +1242,7 @@ fil_name_process(const char* name, ulint len, uint32_t space_id,
case FIL_LOAD_OK:
ut_ad(space != NULL);
- deferred_spaces.remove(
- static_cast<uint32_t>(space_id));
+ deferred_spaces.remove(space_id);
if (!f.space) {
if (f.size
|| f.flags != f.initial_flags) {
@@ -1304,8 +1305,7 @@ same_space:
when lsn is already processed */
if (store != store_t::STORE_IF_EXISTS) {
deferred_spaces.add(
- static_cast<uint32_t>(space_id),
- fname.name.c_str(), lsn);
+ space_id, fname.name.c_str(), lsn);
}
break;
case FIL_LOAD_INVALID:
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index 5b330e4e6a7..effa5a2cb0f 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -1114,7 +1114,7 @@ row_purge(
trx_undo_rec_t* undo_rec, /*!< in: record to purge */
que_thr_t* thr) /*!< in: query thread */
{
- if (undo_rec != &trx_purge_dummy_rec) {
+ if (undo_rec != reinterpret_cast<trx_undo_rec_t*>(-1)) {
bool updated_extern;
while (row_purge_parse_undo_rec(
diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc
index 9c41862e0b4..4d6d779eee6 100644
--- a/storage/innobase/row/row0undo.cc
+++ b/storage/innobase/row/row0undo.cc
@@ -342,7 +342,11 @@ static bool row_undo_rec_get(undo_node_t* node)
node->heap);
mtr.commit();
- switch (trx_undo_rec_get_type(node->undo_rec)) {
+ if (UNIV_UNLIKELY(!node->undo_rec)) {
+ return false;
+ }
+
+ switch (node->undo_rec[2] & (TRX_UNDO_CMPL_INFO_MULT - 1)) {
case TRX_UNDO_INSERT_METADATA:
/* This record type was introduced in MDEV-11369
instant ADD COLUMN, which was implemented after
@@ -356,13 +360,12 @@ static bool row_undo_rec_get(undo_node_t* node)
case TRX_UNDO_INSERT_REC:
case TRX_UNDO_EMPTY:
node->roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS;
- node->state = undo == temp
+ node->state = is_temp
? UNDO_INSERT_TEMPORARY : UNDO_INSERT_PERSISTENT;
break;
default:
- node->state = undo == temp
+ node->state = is_temp
? UNDO_UPDATE_TEMPORARY : UNDO_UPDATE_PERSISTENT;
- break;
}
trx->undo_no = node->undo_no = trx_undo_rec_get_undo_no(
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index b61187d7392..bed88b7e374 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -55,10 +55,6 @@ ulong srv_max_purge_lag_delay = 0;
/** The global data structure coordinating a purge */
purge_sys_t purge_sys;
-/** A dummy undo record used as a return value when we have a whole undo log
-which needs no purge */
-trx_undo_rec_t trx_purge_dummy_rec;
-
#ifdef UNIV_DEBUG
my_bool srv_purge_view_update_only_debug;
#endif /* UNIV_DEBUG */
@@ -1022,7 +1018,9 @@ TRANSACTIONAL_TARGET static void trx_purge_choose_next_log()
/***********************************************************************//**
Gets the next record to purge and updates the info in the purge system.
-@return copy of an undo log record or pointer to the dummy undo log record */
+@return copy of an undo log record
+@retval -1 if there is nothing to purge
+@retval nullptr on corruption */
static
trx_undo_rec_t*
trx_purge_get_next_rec(
@@ -1048,11 +1046,10 @@ trx_purge_get_next_rec(
/* Look for the next undo log and record to purge */
trx_purge_choose_next_log();
-
- return(&trx_purge_dummy_rec);
+ return reinterpret_cast<trx_undo_rec_t*>(-1);
}
- mtr_start(&mtr);
+ mtr.start();
const buf_block_t* undo_page
= buf_page_get_gen(page_id, 0, RW_S_LATCH, nullptr,
@@ -1060,7 +1057,7 @@ trx_purge_get_next_rec(
if (UNIV_UNLIKELY(!undo_page)) {
corrupted:
mtr.commit();
- return &trx_purge_dummy_rec;
+ return nullptr;
}
const buf_block_t* rec2_page = undo_page;
@@ -1105,16 +1102,16 @@ corrupted:
trx_undo_rec_t* rec_copy = trx_undo_rec_copy(undo_page->page.frame
+ offset, heap);
- mtr_commit(&mtr);
-
- return(rec_copy);
+ mtr.commit();
+ return rec_copy;
}
/********************************************************************//**
Fetches the next undo log record from the history list to purge. It must be
released with the corresponding release function.
-@return copy of an undo log record or pointer to trx_purge_dummy_rec,
-if the whole undo log can skipped in purge; NULL if none left */
+@return copy of an undo log record
+@retval -1 if the whole undo log can skipped in purge
+@retval nullptr if nothing is left, or on corruption */
static MY_ATTRIBUTE((warn_unused_result))
trx_undo_rec_t*
trx_purge_fetch_next_rec(
@@ -1130,13 +1127,12 @@ trx_purge_fetch_next_rec(
if (!purge_sys.next_stored) {
DBUG_PRINT("ib_purge",
("no logs left in the history list"));
- return(NULL);
+ return nullptr;
}
}
if (purge_sys.tail.trx_no >= purge_sys.low_limit_no()) {
-
- return(NULL);
+ return nullptr;
}
/* fprintf(stderr, "Thread %lu purging trx %llu undo record %llu\n",
@@ -1152,7 +1148,7 @@ trx_purge_fetch_next_rec(
/* The following call will advance the stored values of the
purge iterator. */
- return(trx_purge_get_next_rec(n_pages_handled, heap));
+ return trx_purge_get_next_rec(n_pages_handled, heap);
}
/** Run a purge batch.
@@ -1229,7 +1225,8 @@ trx_purge_attach_undo_recs(ulint n_purge_threads)
if (purge_rec.undo_rec == NULL) {
break;
- } else if (purge_rec.undo_rec == &trx_purge_dummy_rec) {
+ } else if (purge_rec.undo_rec
+ == reinterpret_cast<trx_undo_rec_t*>(-1)) {
continue;
}
diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc
index 353d82c89cf..56bef29cc70 100644
--- a/storage/innobase/trx/trx0undo.cc
+++ b/storage/innobase/trx/trx0undo.cc
@@ -307,8 +307,10 @@ inline void UndorecApplier::assign_rec(const buf_block_t &block,
this->undo_rec= trx_undo_rec_copy(block.page.frame + offset, heap);
}
-void UndorecApplier::apply_undo_rec()
+inline void UndorecApplier::apply_undo_rec()
{
+ if (!undo_rec)
+ return;
bool updated_extern= false;
undo_no_t undo_no= 0;
table_id_t table_id= 0;
diff --git a/tpool/tpool_generic.cc b/tpool/tpool_generic.cc
index dfd780e7ea3..5d99783e8b9 100644
--- a/tpool/tpool_generic.cc
+++ b/tpool/tpool_generic.cc
@@ -327,21 +327,22 @@ public:
int m_period;
std::mutex m_mtx;
bool m_on;
- std::atomic<bool> m_running;
+ std::atomic<int> m_running;
void run()
{
/*
In rare cases, multiple callbacks can be scheduled,
- e.g with set_time(0,0) in a loop.
- We do not allow parallel execution, as user is not prepared.
+ at the same time,. e.g with set_time(0,0) in a loop.
+ We do not allow parallel execution, since it is against the expectations.
*/
- bool expected = false;
- if (!m_running.compare_exchange_strong(expected, true))
+ if (m_running.fetch_add(1, std::memory_order_acquire) > 0)
return;
-
- m_callback(m_data);
- m_running = false;
+ do
+ {
+ m_callback(m_data);
+ }
+ while (m_running.fetch_sub(1, std::memory_order_release) != 1);
if (m_pool && m_period)
{