Commit 4ef44cc2 authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.5 into 10.6

parents dafc5fb9 73fee39e
...@@ -1037,7 +1037,7 @@ sub get_tags_from_file($$) { ...@@ -1037,7 +1037,7 @@ sub get_tags_from_file($$) {
} }
# Check for a sourced include file. # Check for a sourced include file.
if ($line =~ /^(--)?[[:space:]]*source[[:space:]]+([^;[:space:]]+)/) if ($line =~ /^[[:space:]]*(--)?[[:space:]]*source[[:space:]]+([^;[:space:]]+)/)
{ {
my $include= $2; my $include= $2;
# The rules below must match open_file() function of mysqltest.cc # The rules below must match open_file() function of mysqltest.cc
......
#
# MDEV-14429 sql_safe_updates in my.cnf not work
#
select @@sql_safe_updates; select @@sql_safe_updates;
@@sql_safe_updates @@sql_safe_updates
1 1
#
# MDEV-18304 sql_safe_updates does not work with OR clauses
#
create table t1 (a int, b int, primary key (a), key (b));
update t1 set b=2 where a=1 or b=2;
ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
explain update t1 set b=2 where a=1 or b=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 1 Using where
delete from t1 where a=1 or b=2;
ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
explain delete from t1 where a=1 or b=2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 1 Using where
insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);
update t1 set b=2 where a=1 or b=2;
delete from t1 where a=1 or b=2;
drop table t1;
#
# End of 10.3 tests
#
# --echo #
# MDEV-14429 sql_safe_updates in my.cnf not work --echo # MDEV-14429 sql_safe_updates in my.cnf not work
# --echo #
select @@sql_safe_updates; select @@sql_safe_updates;
--echo #
--echo # MDEV-18304 sql_safe_updates does not work with OR clauses
--echo #
create table t1 (a int, b int, primary key (a), key (b));
--error ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE
update t1 set b=2 where a=1 or b=2;
explain update t1 set b=2 where a=1 or b=2;
--error ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE
delete from t1 where a=1 or b=2;
explain delete from t1 where a=1 or b=2;
insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);
update t1 set b=2 where a=1 or b=2;
delete from t1 where a=1 or b=2;
drop table t1;
--echo #
--echo # End of 10.3 tests
--echo #
...@@ -451,4 +451,13 @@ ALTER TABLE t ADD d INT; ...@@ -451,4 +451,13 @@ ALTER TABLE t ADD d INT;
affected rows: 0 affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0 info: Records: 0 Duplicates: 0 Warnings: 0
DROP TABLE t; DROP TABLE t;
#
# MDEV-28060 Online DDL fails while checking for instant
# alter condition
#
CREATE TABLE t1(f1 CHAR(10) NOT NULL)ROW_FORMAT=REDUNDANT,ENGINE=InnoDB;
ALTER TABLE t1 ADD COLUMN(f2 INT NOT NULL, f3 INT NOT NULL,
f4 INT NOT NULL, f5 INT NOT NULL),
CHANGE COLUMN f1 f1 CHAR(10) DEFAULT NULL;
DROP TABLE t1;
SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency;
...@@ -28,6 +28,8 @@ connection con2; ...@@ -28,6 +28,8 @@ connection con2;
commit; commit;
disconnect con2; disconnect con2;
connection default; connection default;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
SET GLOBAL innodb_max_purge_lag_wait=0;
set global innodb_fast_shutdown=0; set global innodb_fast_shutdown=0;
# restart # restart
drop table t1, t2; drop table t1, t2;
...@@ -473,4 +473,13 @@ ALTER TABLE t ADD d INT; ...@@ -473,4 +473,13 @@ ALTER TABLE t ADD d INT;
--disable_info --disable_info
DROP TABLE t; DROP TABLE t;
--echo #
--echo # MDEV-28060 Online DDL fails while checking for instant
--echo # alter condition
--echo #
CREATE TABLE t1(f1 CHAR(10) NOT NULL)ROW_FORMAT=REDUNDANT,ENGINE=InnoDB;
ALTER TABLE t1 ADD COLUMN(f2 INT NOT NULL, f3 INT NOT NULL,
f4 INT NOT NULL, f5 INT NOT NULL),
CHANGE COLUMN f1 f1 CHAR(10) DEFAULT NULL;
DROP TABLE t1;
SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency;
...@@ -46,6 +46,8 @@ connection default; ...@@ -46,6 +46,8 @@ connection default;
let $trx_before= `SHOW ENGINE INNODB STATUS`; let $trx_before= `SHOW ENGINE INNODB STATUS`;
let $trx_before= `select substr('$trx_before',9)+2`; let $trx_before= `select substr('$trx_before',9)+2`;
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
SET GLOBAL innodb_max_purge_lag_wait=0;
set global innodb_fast_shutdown=0; set global innodb_fast_shutdown=0;
--source include/restart_mysqld.inc --source include/restart_mysqld.inc
--replace_regex /.*Trx id counter ([0-9]+).*/\1/ --replace_regex /.*Trx id counter ([0-9]+).*/\1/
......
/* /*
Copyright (c) 2000, 2019, Oracle and/or its affiliates. Copyright (c) 2000, 2019, Oracle and/or its affiliates.
Copyright (c) 2010, 2021, MariaDB Copyright (c) 2010, 2022, MariaDB
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -417,7 +417,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -417,7 +417,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
const_cond= (!conds || conds->const_item()); const_cond= (!conds || conds->const_item());
safe_update= MY_TEST(thd->variables.option_bits & OPTION_SAFE_UPDATES); safe_update= (thd->variables.option_bits & OPTION_SAFE_UPDATES) &&
!thd->lex->describe;
if (safe_update && const_cond) if (safe_update && const_cond)
{ {
my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
...@@ -542,7 +543,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -542,7 +543,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
} }
/* If running in safe sql mode, don't allow updates without keys */ /* If running in safe sql mode, don't allow updates without keys */
if (table->opt_range_keys.is_clear_all()) if (!select || !select->quick)
{ {
thd->set_status_no_index_used(); thd->set_status_no_index_used();
if (safe_update && !using_limit) if (safe_update && !using_limit)
......
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. /* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2011, 2021, MariaDB Copyright (c) 2011, 2022, MariaDB
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -370,7 +370,8 @@ int mysql_update(THD *thd, ...@@ -370,7 +370,8 @@ int mysql_update(THD *thd,
ha_rows *found_return, ha_rows *updated_return) ha_rows *found_return, ha_rows *updated_return)
{ {
bool using_limit= limit != HA_POS_ERROR; bool using_limit= limit != HA_POS_ERROR;
bool safe_update= thd->variables.option_bits & OPTION_SAFE_UPDATES; bool safe_update= (thd->variables.option_bits & OPTION_SAFE_UPDATES)
&& !thd->lex->describe;
bool used_key_is_modified= FALSE, transactional_table; bool used_key_is_modified= FALSE, transactional_table;
bool will_batch= FALSE; bool will_batch= FALSE;
bool can_compare_record; bool can_compare_record;
...@@ -597,7 +598,7 @@ int mysql_update(THD *thd, ...@@ -597,7 +598,7 @@ int mysql_update(THD *thd,
} }
/* If running in safe sql mode, don't allow updates without keys */ /* If running in safe sql mode, don't allow updates without keys */
if (table->opt_range_keys.is_clear_all()) if (!select || !select->quick)
{ {
thd->set_status_no_index_used(); thd->set_status_no_index_used();
if (safe_update && !using_limit) if (safe_update && !using_limit)
......
...@@ -1006,42 +1006,52 @@ static page_id_t buf_flush_check_neighbors(const fil_space_t &space, ...@@ -1006,42 +1006,52 @@ static page_id_t buf_flush_check_neighbors(const fil_space_t &space,
return i; return i;
} }
MY_ATTRIBUTE((nonnull)) MY_ATTRIBUTE((nonnull, warn_unused_result))
/** Write punch-hole or zeroes of the freed ranges when /** Write punch-hole or zeroes of the freed ranges when
innodb_immediate_scrub_data_uncompressed from the freed ranges. innodb_immediate_scrub_data_uncompressed from the freed ranges.
@param space tablespace which may contain ranges of freed pages */ @param space tablespace which may contain ranges of freed pages
static void buf_flush_freed_pages(fil_space_t *space) @param writable whether the tablespace is writable
@return number of pages written or hole-punched */
static uint32_t buf_flush_freed_pages(fil_space_t *space, bool writable)
{ {
const bool punch_hole= space->chain.start->punch_hole == 1; const bool punch_hole= space->chain.start->punch_hole == 1;
if (!punch_hole && !srv_immediate_scrub_data_uncompressed) if (!punch_hole && !srv_immediate_scrub_data_uncompressed)
return; return 0;
lsn_t flush_to_disk_lsn= log_sys.get_flushed_lsn();
mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex);
mysql_mutex_assert_not_owner(&buf_pool.mutex);
std::unique_lock<std::mutex> freed_lock(space->freed_range_mutex); space->freed_range_mutex.lock();
if (space->freed_ranges.empty() if (space->freed_ranges.empty() ||
|| flush_to_disk_lsn < space->get_last_freed_lsn()) log_sys.get_flushed_lsn() < space->get_last_freed_lsn())
{ {
freed_lock.unlock(); space->freed_range_mutex.unlock();
return; return 0;
} }
const unsigned physical_size{space->physical_size()};
range_set freed_ranges= std::move(space->freed_ranges); range_set freed_ranges= std::move(space->freed_ranges);
freed_lock.unlock(); uint32_t written= 0;
for (const auto &range : freed_ranges) if (!writable);
else if (punch_hole)
{ {
const ulint physical_size= space->physical_size(); for (const auto &range : freed_ranges)
if (punch_hole)
{ {
written+= range.last - range.first + 1;
space->reacquire(); space->reacquire();
space->io(IORequest(IORequest::PUNCH_RANGE), space->io(IORequest(IORequest::PUNCH_RANGE),
os_offset_t{range.first} * physical_size, os_offset_t{range.first} * physical_size,
(range.last - range.first + 1) * physical_size, (range.last - range.first + 1) * physical_size,
nullptr); nullptr);
} }
else }
else
{
for (const auto &range : freed_ranges)
{ {
written+= range.last - range.first + 1;
for (os_offset_t i= range.first; i <= range.last; i++) for (os_offset_t i= range.first; i <= range.last; i++)
{ {
space->reacquire(); space->reacquire();
...@@ -1050,8 +1060,10 @@ static void buf_flush_freed_pages(fil_space_t *space) ...@@ -1050,8 +1060,10 @@ static void buf_flush_freed_pages(fil_space_t *space)
const_cast<byte*>(field_ref_zero)); const_cast<byte*>(field_ref_zero));
} }
} }
buf_pool.stat.n_pages_written+= (range.last - range.first + 1);
} }
space->freed_range_mutex.unlock();
return written;
} }
/** Flushes to disk all flushable pages within the flush area /** Flushes to disk all flushable pages within the flush area
...@@ -1174,14 +1186,12 @@ static ulint buf_free_from_unzip_LRU_list_batch(ulint max) ...@@ -1174,14 +1186,12 @@ static ulint buf_free_from_unzip_LRU_list_batch(ulint max)
/** Start writing out pages for a tablespace. /** Start writing out pages for a tablespace.
@param id tablespace identifier @param id tablespace identifier
@return tablespace @return tablespace and number of pages written */
@retval nullptr if the pages for this tablespace should be discarded */ static std::pair<fil_space_t*, uint32_t> buf_flush_space(const uint32_t id)
static fil_space_t *buf_flush_space(const uint32_t id)
{ {
fil_space_t *space= fil_space_t::get(id); if (fil_space_t *space= fil_space_t::get(id))
if (space) return {space, buf_flush_freed_pages(space, true)};
buf_flush_freed_pages(space); return {nullptr, 0};
return space;
} }
struct flush_counters_t struct flush_counters_t
...@@ -1242,6 +1252,7 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) ...@@ -1242,6 +1252,7 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n)
n->flushed + n->evicted < max) || n->flushed + n->evicted < max) ||
recv_recovery_is_on()); ++scanned) recv_recovery_is_on()); ++scanned)
{ {
retry:
buf_page_t *prev= UT_LIST_GET_PREV(LRU, bpage); buf_page_t *prev= UT_LIST_GET_PREV(LRU, bpage);
const lsn_t oldest_modification= bpage->oldest_modification(); const lsn_t oldest_modification= bpage->oldest_modification();
buf_pool.lru_hp.set(prev); buf_pool.lru_hp.set(prev);
...@@ -1267,10 +1278,18 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) ...@@ -1267,10 +1278,18 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n)
{ {
if (last_space_id != space_id) if (last_space_id != space_id)
{ {
buf_pool.lru_hp.set(bpage);
mysql_mutex_unlock(&buf_pool.mutex);
if (space) if (space)
space->release(); space->release();
space= buf_flush_space(space_id); auto p= buf_flush_space(space_id);
space= p.first;
last_space_id= space_id; last_space_id= space_id;
mysql_mutex_lock(&buf_pool.mutex);
if (p.second)
buf_pool.stat.n_pages_written+= p.second;
bpage= buf_pool.lru_hp.get();
goto retry;
} }
else else
ut_ad(!space); ut_ad(!space);
...@@ -1405,10 +1424,28 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn) ...@@ -1405,10 +1424,28 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn)
{ {
if (last_space_id != space_id) if (last_space_id != space_id)
{ {
mysql_mutex_lock(&buf_pool.flush_list_mutex);
buf_pool.flush_hp.set(bpage);
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
mysql_mutex_unlock(&buf_pool.mutex);
if (space) if (space)
space->release(); space->release();
space= buf_flush_space(space_id); auto p= buf_flush_space(space_id);
space= p.first;
last_space_id= space_id; last_space_id= space_id;
mysql_mutex_lock(&buf_pool.mutex);
if (p.second)
buf_pool.stat.n_pages_written+= p.second;
mysql_mutex_lock(&buf_pool.flush_list_mutex);
bpage= buf_pool.flush_hp.get();
if (!bpage)
break;
if (bpage->id() != page_id)
continue;
buf_pool.flush_hp.set(UT_LIST_GET_PREV(list, bpage));
if (bpage->oldest_modification() <= 1 || !bpage->ready_for_flush())
goto next;
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
} }
else else
ut_ad(!space); ut_ad(!space);
...@@ -1436,6 +1473,7 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn) ...@@ -1436,6 +1473,7 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn)
} }
mysql_mutex_lock(&buf_pool.flush_list_mutex); mysql_mutex_lock(&buf_pool.flush_list_mutex);
next:
bpage= buf_pool.flush_hp.get(); bpage= buf_pool.flush_hp.get();
} }
...@@ -1532,11 +1570,14 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed) ...@@ -1532,11 +1570,14 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed)
bool may_have_skipped= false; bool may_have_skipped= false;
ulint max_n_flush= srv_io_capacity; ulint max_n_flush= srv_io_capacity;
mysql_mutex_lock(&buf_pool.mutex);
mysql_mutex_lock(&buf_pool.flush_list_mutex);
bool acquired= space->acquire(); bool acquired= space->acquire();
buf_flush_freed_pages(space); {
const uint32_t written{buf_flush_freed_pages(space, acquired)};
mysql_mutex_lock(&buf_pool.mutex);
if (written)
buf_pool.stat.n_pages_written+= written;
}
mysql_mutex_lock(&buf_pool.flush_list_mutex);
for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; ) for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.flush_list); bpage; )
{ {
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2021, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2021, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2021, MariaDB Corporation. Copyright (c) 2014, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
...@@ -86,7 +86,9 @@ bool fil_space_t::try_to_close(bool print_info) ...@@ -86,7 +86,9 @@ bool fil_space_t::try_to_close(bool print_info)
of fil_system.space_list, so that they would be less likely to be of fil_system.space_list, so that they would be less likely to be
closed here. */ closed here. */
fil_node_t *node= UT_LIST_GET_FIRST(space.chain); fil_node_t *node= UT_LIST_GET_FIRST(space.chain);
ut_ad(node); if (!node)
/* fil_ibd_create() did not invoke fil_space_t::add() yet */
continue;
ut_ad(!UT_LIST_GET_NEXT(chain, node)); ut_ad(!UT_LIST_GET_NEXT(chain, node));
if (!node->is_open()) if (!node->is_open())
...@@ -446,6 +448,8 @@ static bool fil_node_open_file(fil_node_t *node) ...@@ -446,6 +448,8 @@ static bool fil_node_open_file(fil_node_t *node)
/* Flush tablespaces so that we can close modified files. */ /* Flush tablespaces so that we can close modified files. */
fil_flush_file_spaces(); fil_flush_file_spaces();
mysql_mutex_lock(&fil_system.mutex); mysql_mutex_lock(&fil_system.mutex);
if (node->is_open())
return true;
} }
} }
......
...@@ -1760,8 +1760,13 @@ instant_alter_column_possible( ...@@ -1760,8 +1760,13 @@ instant_alter_column_possible(
Field** af = altered_table->field; Field** af = altered_table->field;
Field** const end = altered_table->field Field** const end = altered_table->field
+ altered_table->s->fields; + altered_table->s->fields;
List_iterator_fast<Create_field> cf_it(
ha_alter_info->alter_info->create_list);
for (unsigned c = 0; af < end; af++) { for (unsigned c = 0; af < end; af++) {
if (!(*af)->stored_in_db()) { const Create_field* cf = cf_it++;
if (!cf->field || !(*af)->stored_in_db()) {
/* Ignore virtual or newly created
column */
continue; continue;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment