mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge 10.7 into 10.8
This commit is contained in:
@ -3697,6 +3697,25 @@ SELECT * FROM t1 LEFT JOIN t2 ON a = pk WHERE b >= 0 AND pk IS NULL;
|
|||||||
a pk b
|
a pk b
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
SET @@optimizer_switch= @save_optimizer_switch;
|
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
|
# End of 10.5 tests
|
||||||
#
|
#
|
||||||
|
@ -2492,6 +2492,24 @@ DROP TABLE t1, t2;
|
|||||||
|
|
||||||
SET @@optimizer_switch= @save_optimizer_switch;
|
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 #
|
||||||
--echo # End of 10.5 tests
|
--echo # End of 10.5 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -3686,6 +3686,25 @@ SELECT * FROM t1 LEFT JOIN t2 ON a = pk WHERE b >= 0 AND pk IS NULL;
|
|||||||
a pk b
|
a pk b
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
SET @@optimizer_switch= @save_optimizer_switch;
|
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
|
# End of 10.5 tests
|
||||||
#
|
#
|
||||||
|
@ -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: 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: 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: 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("InnoDB: Plugin initialization aborted");
|
||||||
call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed");
|
call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed");
|
||||||
call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space=");
|
call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space=");
|
||||||
|
@ -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: 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: 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: 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("InnoDB: Plugin initialization aborted");
|
||||||
call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed");
|
call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed");
|
||||||
# for innodb_checksum_algorithm=full_crc32 only
|
# for innodb_checksum_algorithm=full_crc32 only
|
||||||
|
@ -29971,11 +29971,12 @@ bool build_notnull_conds_for_range_scans(JOIN *join, Item *cond,
|
|||||||
|
|
||||||
DBUG_ENTER("build_notnull_conds_for_range_scans");
|
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++)
|
s < join->join_tab + join->table_count ; s++)
|
||||||
{
|
{
|
||||||
/* Clear all needed bitmaps to mark found fields */
|
/* 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);
|
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
|
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.
|
constructed for all found fields if they are included in some indexes.
|
||||||
If the construction of the conjunction succeeds attach the formula to
|
If the construction of the conjunction succeeds attach the formula to
|
||||||
t->table->notnull_cond. The condition will be used to look for complementary
|
t->table->notnull_cond. The condition will be used to look for
|
||||||
range scans.
|
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++)
|
s < join->join_tab + join->table_count ; s++)
|
||||||
{
|
{
|
||||||
TABLE *tab= s->table;
|
TABLE *tab= s->table;
|
||||||
List<Item> notnull_list;
|
List<Item> notnull_list;
|
||||||
Item *notnull_cond= 0;
|
Item *notnull_cond= 0;
|
||||||
|
|
||||||
if (!(allowed & tab->map))
|
if (!(allowed & tab->map) ||
|
||||||
|
(s->table->map && join->const_table_map))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (Field** field_ptr= tab->field; *field_ptr; field_ptr++)
|
for (Field** field_ptr= tab->field; *field_ptr; field_ptr++)
|
||||||
|
@ -234,7 +234,6 @@ SET(INNOBASE_SOURCES
|
|||||||
include/trx0i_s.h
|
include/trx0i_s.h
|
||||||
include/trx0purge.h
|
include/trx0purge.h
|
||||||
include/trx0rec.h
|
include/trx0rec.h
|
||||||
include/trx0rec.inl
|
|
||||||
include/trx0roll.h
|
include/trx0roll.h
|
||||||
include/trx0rseg.h
|
include/trx0rseg.h
|
||||||
include/trx0sys.h
|
include/trx0sys.h
|
||||||
|
@ -33,10 +33,6 @@ Created 3/26/1996 Heikki Tuuri
|
|||||||
|
|
||||||
#include <queue>
|
#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.
|
/** Prepend the history list with an undo log.
|
||||||
Remove the undo log segment from the rseg slot if it is too big for reuse.
|
Remove the undo log segment from the rseg slot if it is too big for reuse.
|
||||||
@param[in] trx transaction
|
@param[in] trx transaction
|
||||||
|
@ -24,8 +24,7 @@ Transaction undo log record
|
|||||||
Created 3/26/1996 Heikki Tuuri
|
Created 3/26/1996 Heikki Tuuri
|
||||||
*******************************************************/
|
*******************************************************/
|
||||||
|
|
||||||
#ifndef trx0rec_h
|
#pragma once
|
||||||
#define trx0rec_h
|
|
||||||
|
|
||||||
#include "trx0types.h"
|
#include "trx0types.h"
|
||||||
#include "row0types.h"
|
#include "row0types.h"
|
||||||
@ -37,29 +36,31 @@ Created 3/26/1996 Heikki Tuuri
|
|||||||
|
|
||||||
/***********************************************************************//**
|
/***********************************************************************//**
|
||||||
Copies the undo record to the heap.
|
Copies the undo record to the heap.
|
||||||
@return own: copy of undo log record */
|
@param undo_rec record in an undo log page
|
||||||
UNIV_INLINE
|
@param heap memory heap
|
||||||
trx_undo_rec_t*
|
@return copy of undo_rec
|
||||||
trx_undo_rec_copy(
|
@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,
|
||||||
const trx_undo_rec_t* undo_rec, /*!< in: undo log record */
|
mem_heap_t *heap)
|
||||||
mem_heap_t* heap); /*!< in: heap where copied */
|
{
|
||||||
/**********************************************************************//**
|
const size_t offset= ut_align_offset(undo_rec, srv_page_size);
|
||||||
Reads the undo log record type.
|
const size_t end= mach_read_from_2(undo_rec);
|
||||||
@return record type */
|
if (end <= offset || end >= srv_page_size - FIL_PAGE_DATA_END)
|
||||||
UNIV_INLINE
|
return nullptr;
|
||||||
ulint
|
const size_t len= end - offset;
|
||||||
trx_undo_rec_get_type(
|
trx_undo_rec_t *rec= static_cast<trx_undo_rec_t*>
|
||||||
/*==================*/
|
(mem_heap_dup(heap, undo_rec, len));
|
||||||
const trx_undo_rec_t* undo_rec); /*!< in: undo log record */
|
mach_write_to_2(rec, len);
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Reads the undo log record number.
|
Reads the undo log record number.
|
||||||
@return undo no */
|
@return undo no */
|
||||||
UNIV_INLINE
|
inline undo_no_t trx_undo_rec_get_undo_no(const trx_undo_rec_t *undo_rec)
|
||||||
undo_no_t
|
{
|
||||||
trx_undo_rec_get_undo_no(
|
return mach_u64_read_much_compressed(undo_rec + 3);
|
||||||
/*=====================*/
|
}
|
||||||
const trx_undo_rec_t* undo_rec); /*!< in: undo log record */
|
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Returns the start of the undo record data area. */
|
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);
|
mach_read_next_much_compressed(&rec);
|
||||||
return mach_read_next_much_compressed(&rec);
|
return mach_read_next_much_compressed(&rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "trx0rec.inl"
|
|
||||||
|
|
||||||
#endif /* trx0rec_h */
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -360,7 +360,7 @@ public:
|
|||||||
page_id_t get_page_id() const { return page_id; }
|
page_id_t get_page_id() const { return page_id; }
|
||||||
|
|
||||||
/** Handle the DML undo log and apply it on online indexes */
|
/** Handle the DML undo log and apply it on online indexes */
|
||||||
void apply_undo_rec();
|
inline void apply_undo_rec();
|
||||||
|
|
||||||
~UndorecApplier()
|
~UndorecApplier()
|
||||||
{
|
{
|
||||||
|
@ -1185,12 +1185,9 @@ inline size_t recv_sys_t::files_size()
|
|||||||
@param[in] space_id the tablespace ID
|
@param[in] space_id the tablespace ID
|
||||||
@param[in] deleted whether this is a FILE_DELETE record
|
@param[in] deleted whether this is a FILE_DELETE record
|
||||||
@param[in] lsn lsn of the redo log
|
@param[in] lsn lsn of the redo log
|
||||||
@param[in] store whether the redo log has to
|
@param[in] store whether the redo log has to be stored */
|
||||||
stored */
|
static void fil_name_process(const char *name, ulint len, uint32_t space_id,
|
||||||
static
|
bool deleted, lsn_t lsn, store_t store)
|
||||||
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
|
if (srv_operation == SRV_OPERATION_BACKUP
|
||||||
|| srv_operation == SRV_OPERATION_BACKUP_NO_DEFER) {
|
|| 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;
|
file_name_t& f = p.first->second;
|
||||||
|
|
||||||
if (deleted) {
|
if (auto d = deferred_spaces.find(space_id)) {
|
||||||
/* Got FILE_DELETE */
|
if (deleted) {
|
||||||
if (auto d = deferred_spaces.find(static_cast<uint32_t>(
|
|
||||||
space_id))) {
|
|
||||||
d->deleted = true;
|
d->deleted = true;
|
||||||
|
goto got_deleted;
|
||||||
}
|
}
|
||||||
|
goto reload;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deleted) {
|
||||||
|
got_deleted:
|
||||||
|
/* Got FILE_DELETE */
|
||||||
if (!p.second && f.status != file_name_t::DELETED) {
|
if (!p.second && f.status != file_name_t::DELETED) {
|
||||||
f.status = file_name_t::DELETED;
|
f.status = file_name_t::DELETED;
|
||||||
if (f.space != NULL) {
|
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);
|
ut_ad(f.space == NULL);
|
||||||
} else if (p.second // the first FILE_MODIFY or FILE_RENAME
|
} else if (p.second // the first FILE_MODIFY or FILE_RENAME
|
||||||
|| f.name != fname.name) {
|
|| f.name != fname.name) {
|
||||||
|
reload:
|
||||||
fil_space_t* space;
|
fil_space_t* space;
|
||||||
|
|
||||||
/* Check if the tablespace file exists and contains
|
/* 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:
|
case FIL_LOAD_OK:
|
||||||
ut_ad(space != NULL);
|
ut_ad(space != NULL);
|
||||||
|
|
||||||
deferred_spaces.remove(
|
deferred_spaces.remove(space_id);
|
||||||
static_cast<uint32_t>(space_id));
|
|
||||||
if (!f.space) {
|
if (!f.space) {
|
||||||
if (f.size
|
if (f.size
|
||||||
|| f.flags != f.initial_flags) {
|
|| f.flags != f.initial_flags) {
|
||||||
@ -1304,8 +1305,7 @@ same_space:
|
|||||||
when lsn is already processed */
|
when lsn is already processed */
|
||||||
if (store != store_t::STORE_IF_EXISTS) {
|
if (store != store_t::STORE_IF_EXISTS) {
|
||||||
deferred_spaces.add(
|
deferred_spaces.add(
|
||||||
static_cast<uint32_t>(space_id),
|
space_id, fname.name.c_str(), lsn);
|
||||||
fname.name.c_str(), lsn);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FIL_LOAD_INVALID:
|
case FIL_LOAD_INVALID:
|
||||||
|
@ -1114,7 +1114,7 @@ row_purge(
|
|||||||
trx_undo_rec_t* undo_rec, /*!< in: record to purge */
|
trx_undo_rec_t* undo_rec, /*!< in: record to purge */
|
||||||
que_thr_t* thr) /*!< in: query thread */
|
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;
|
bool updated_extern;
|
||||||
|
|
||||||
while (row_purge_parse_undo_rec(
|
while (row_purge_parse_undo_rec(
|
||||||
|
@ -342,7 +342,11 @@ static bool row_undo_rec_get(undo_node_t* node)
|
|||||||
node->heap);
|
node->heap);
|
||||||
mtr.commit();
|
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:
|
case TRX_UNDO_INSERT_METADATA:
|
||||||
/* This record type was introduced in MDEV-11369
|
/* This record type was introduced in MDEV-11369
|
||||||
instant ADD COLUMN, which was implemented after
|
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_INSERT_REC:
|
||||||
case TRX_UNDO_EMPTY:
|
case TRX_UNDO_EMPTY:
|
||||||
node->roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS;
|
node->roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS;
|
||||||
node->state = undo == temp
|
node->state = is_temp
|
||||||
? UNDO_INSERT_TEMPORARY : UNDO_INSERT_PERSISTENT;
|
? UNDO_INSERT_TEMPORARY : UNDO_INSERT_PERSISTENT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
node->state = undo == temp
|
node->state = is_temp
|
||||||
? UNDO_UPDATE_TEMPORARY : UNDO_UPDATE_PERSISTENT;
|
? UNDO_UPDATE_TEMPORARY : UNDO_UPDATE_PERSISTENT;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trx->undo_no = node->undo_no = trx_undo_rec_get_undo_no(
|
trx->undo_no = node->undo_no = trx_undo_rec_get_undo_no(
|
||||||
|
@ -55,10 +55,6 @@ ulong srv_max_purge_lag_delay = 0;
|
|||||||
/** The global data structure coordinating a purge */
|
/** The global data structure coordinating a purge */
|
||||||
purge_sys_t purge_sys;
|
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
|
#ifdef UNIV_DEBUG
|
||||||
my_bool srv_purge_view_update_only_debug;
|
my_bool srv_purge_view_update_only_debug;
|
||||||
#endif /* UNIV_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.
|
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
|
static
|
||||||
trx_undo_rec_t*
|
trx_undo_rec_t*
|
||||||
trx_purge_get_next_rec(
|
trx_purge_get_next_rec(
|
||||||
@ -1048,11 +1046,10 @@ trx_purge_get_next_rec(
|
|||||||
/* Look for the next undo log and record to purge */
|
/* Look for the next undo log and record to purge */
|
||||||
|
|
||||||
trx_purge_choose_next_log();
|
trx_purge_choose_next_log();
|
||||||
|
return reinterpret_cast<trx_undo_rec_t*>(-1);
|
||||||
return(&trx_purge_dummy_rec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mtr_start(&mtr);
|
mtr.start();
|
||||||
|
|
||||||
const buf_block_t* undo_page
|
const buf_block_t* undo_page
|
||||||
= buf_page_get_gen(page_id, 0, RW_S_LATCH, nullptr,
|
= 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)) {
|
if (UNIV_UNLIKELY(!undo_page)) {
|
||||||
corrupted:
|
corrupted:
|
||||||
mtr.commit();
|
mtr.commit();
|
||||||
return &trx_purge_dummy_rec;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const buf_block_t* rec2_page = undo_page;
|
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
|
trx_undo_rec_t* rec_copy = trx_undo_rec_copy(undo_page->page.frame
|
||||||
+ offset, heap);
|
+ offset, heap);
|
||||||
|
|
||||||
mtr_commit(&mtr);
|
mtr.commit();
|
||||||
|
return rec_copy;
|
||||||
return(rec_copy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************//**
|
/********************************************************************//**
|
||||||
Fetches the next undo log record from the history list to purge. It must be
|
Fetches the next undo log record from the history list to purge. It must be
|
||||||
released with the corresponding release function.
|
released with the corresponding release function.
|
||||||
@return copy of an undo log record or pointer to trx_purge_dummy_rec,
|
@return copy of an undo log record
|
||||||
if the whole undo log can skipped in purge; NULL if none left */
|
@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))
|
static MY_ATTRIBUTE((warn_unused_result))
|
||||||
trx_undo_rec_t*
|
trx_undo_rec_t*
|
||||||
trx_purge_fetch_next_rec(
|
trx_purge_fetch_next_rec(
|
||||||
@ -1130,13 +1127,12 @@ trx_purge_fetch_next_rec(
|
|||||||
if (!purge_sys.next_stored) {
|
if (!purge_sys.next_stored) {
|
||||||
DBUG_PRINT("ib_purge",
|
DBUG_PRINT("ib_purge",
|
||||||
("no logs left in the history list"));
|
("no logs left in the history list"));
|
||||||
return(NULL);
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (purge_sys.tail.trx_no >= purge_sys.low_limit_no()) {
|
if (purge_sys.tail.trx_no >= purge_sys.low_limit_no()) {
|
||||||
|
return nullptr;
|
||||||
return(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fprintf(stderr, "Thread %lu purging trx %llu undo record %llu\n",
|
/* 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
|
/* The following call will advance the stored values of the
|
||||||
purge iterator. */
|
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.
|
/** Run a purge batch.
|
||||||
@ -1229,7 +1225,8 @@ trx_purge_attach_undo_recs(ulint n_purge_threads)
|
|||||||
|
|
||||||
if (purge_rec.undo_rec == NULL) {
|
if (purge_rec.undo_rec == NULL) {
|
||||||
break;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
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;
|
bool updated_extern= false;
|
||||||
undo_no_t undo_no= 0;
|
undo_no_t undo_no= 0;
|
||||||
table_id_t table_id= 0;
|
table_id_t table_id= 0;
|
||||||
|
@ -327,21 +327,22 @@ public:
|
|||||||
int m_period;
|
int m_period;
|
||||||
std::mutex m_mtx;
|
std::mutex m_mtx;
|
||||||
bool m_on;
|
bool m_on;
|
||||||
std::atomic<bool> m_running;
|
std::atomic<int> m_running;
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
In rare cases, multiple callbacks can be scheduled,
|
In rare cases, multiple callbacks can be scheduled,
|
||||||
e.g with set_time(0,0) in a loop.
|
at the same time,. e.g with set_time(0,0) in a loop.
|
||||||
We do not allow parallel execution, as user is not prepared.
|
We do not allow parallel execution, since it is against the expectations.
|
||||||
*/
|
*/
|
||||||
bool expected = false;
|
if (m_running.fetch_add(1, std::memory_order_acquire) > 0)
|
||||||
if (!m_running.compare_exchange_strong(expected, true))
|
|
||||||
return;
|
return;
|
||||||
|
do
|
||||||
m_callback(m_data);
|
{
|
||||||
m_running = false;
|
m_callback(m_data);
|
||||||
|
}
|
||||||
|
while (m_running.fetch_sub(1, std::memory_order_release) != 1);
|
||||||
|
|
||||||
if (m_pool && m_period)
|
if (m_pool && m_period)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user