mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Merge 10.3 into 10.4
This commit is contained in:
@@ -174,7 +174,7 @@ INSERT INTO global_suppressions VALUES
|
|||||||
|
|
||||||
/* Added 2009-08-XX after fixing Bug #42408 */
|
/* Added 2009-08-XX after fixing Bug #42408 */
|
||||||
|
|
||||||
("Although a path was specified for the .* option, log tables are used"),
|
("Although a .* file was specified, log tables are used. To enable logging to files "),
|
||||||
("Backup: Operation aborted"),
|
("Backup: Operation aborted"),
|
||||||
("Restore: Operation aborted"),
|
("Restore: Operation aborted"),
|
||||||
("Restore: The grant .* was skipped because the user does not exist"),
|
("Restore: The grant .* was skipped because the user does not exist"),
|
||||||
|
@@ -0,0 +1,55 @@
|
|||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
#
|
||||||
|
# Set replica to ignore system mysql tables
|
||||||
|
connection slave;
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET @@GLOBAL.replicate_wild_ignore_table="mysql.%";
|
||||||
|
include/start_slave.inc
|
||||||
|
#
|
||||||
|
# Execute grant-based commands on primary which modify mysql system
|
||||||
|
# tables
|
||||||
|
connection master;
|
||||||
|
CREATE ROLE journalist;
|
||||||
|
CREATE USER testuser@localhost IDENTIFIED by '';
|
||||||
|
GRANT journalist to testuser@localhost;
|
||||||
|
#
|
||||||
|
# Execute SET commands which use the previous user/role data
|
||||||
|
SET DEFAULT ROLE journalist for testuser@localhost;
|
||||||
|
SET PASSWORD for testuser@localhost= PASSWORD('123');
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
#
|
||||||
|
# Verify primary's grant tables have the correct user/role data
|
||||||
|
select count(*)=1 from mysql.user where User='testuser';
|
||||||
|
count(*)=1
|
||||||
|
1
|
||||||
|
select count(*)=1 from mysql.roles_mapping where User='testuser';
|
||||||
|
count(*)=1
|
||||||
|
1
|
||||||
|
#
|
||||||
|
# Ensure that the replica receives all of the primary's events without
|
||||||
|
# error
|
||||||
|
connection slave;
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
|
Last_SQL_Error =
|
||||||
|
Last_SQL_Errno = 0
|
||||||
|
#
|
||||||
|
# Verify that the replica did not execute the master's commands
|
||||||
|
select count(*)=0 from mysql.user where User='testuser';
|
||||||
|
count(*)=0
|
||||||
|
1
|
||||||
|
select count(*)=0 from mysql.roles_mapping where User='testuser';
|
||||||
|
count(*)=0
|
||||||
|
1
|
||||||
|
#
|
||||||
|
# Clean up
|
||||||
|
connection master;
|
||||||
|
DROP ROLE journalist;
|
||||||
|
DROP USER testuser@localhost;
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
connection slave;
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET @@GLOBAL.replicate_wild_ignore_table="";
|
||||||
|
include/start_slave.inc
|
||||||
|
include/rpl_end.inc
|
83
mysql-test/suite/rpl/t/rpl_filter_set_var_missing_data.test
Normal file
83
mysql-test/suite/rpl/t/rpl_filter_set_var_missing_data.test
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#
|
||||||
|
# Purpose:
|
||||||
|
# This test ensures that the SET DEFAULT ROLE and SET PASSWORD commands can
|
||||||
|
# be ignored by replica filter rules. MDEV-28294 exposed a bug in which
|
||||||
|
# SET DEFAULT ROLE would check for the existence of the given roles/user even
|
||||||
|
# when the targeted tables are ignored, resulting in errors if the targeted
|
||||||
|
# data does not exist. More specifically, when previously issued
|
||||||
|
# CREATE USER/ROLE commands are ignored by the replica because of the
|
||||||
|
# replication filtering rules, SET DEFAULT ROLE would result in an error
|
||||||
|
# because the targeted data does not exist.
|
||||||
|
#
|
||||||
|
# Methodology:
|
||||||
|
# Using a replica configured with replicate_wild_ignore_table="mysql.%",
|
||||||
|
# execute SET DEFAULT ROLE and SET PASSWORD on the primary and ensure that the
|
||||||
|
# replica neither errors nor executes the commands which the primary sends.
|
||||||
|
#
|
||||||
|
# References:
|
||||||
|
# MDEV-28294: set default role bypasses Replicate_Wild_Ignore_Table: mysql.%
|
||||||
|
#
|
||||||
|
|
||||||
|
source include/master-slave.inc;
|
||||||
|
source include/have_binlog_format_mixed.inc;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Set replica to ignore system mysql tables
|
||||||
|
connection slave;
|
||||||
|
let $old_filter= query_get_value(SHOW SLAVE STATUS, Replicate_Wild_Ignore_Table, 1);
|
||||||
|
source include/stop_slave.inc;
|
||||||
|
SET @@GLOBAL.replicate_wild_ignore_table="mysql.%";
|
||||||
|
source include/start_slave.inc;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Execute grant-based commands on primary which modify mysql system
|
||||||
|
--echo # tables
|
||||||
|
connection master;
|
||||||
|
CREATE ROLE journalist;
|
||||||
|
CREATE USER testuser@localhost IDENTIFIED by '';
|
||||||
|
GRANT journalist to testuser@localhost;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Execute SET commands which use the previous user/role data
|
||||||
|
SET DEFAULT ROLE journalist for testuser@localhost;
|
||||||
|
SET PASSWORD for testuser@localhost= PASSWORD('123');
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Verify primary's grant tables have the correct user/role data
|
||||||
|
select count(*)=1 from mysql.user where User='testuser';
|
||||||
|
select count(*)=1 from mysql.roles_mapping where User='testuser';
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Ensure that the replica receives all of the primary's events without
|
||||||
|
--echo # error
|
||||||
|
connection slave;
|
||||||
|
--source include/sync_with_master_gtid.inc
|
||||||
|
let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
|
||||||
|
--echo Last_SQL_Error = $error
|
||||||
|
let $errno= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
|
||||||
|
--echo Last_SQL_Errno = $errno
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Verify that the replica did not execute the master's commands
|
||||||
|
select count(*)=0 from mysql.user where User='testuser';
|
||||||
|
select count(*)=0 from mysql.roles_mapping where User='testuser';
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Clean up
|
||||||
|
|
||||||
|
# The master has to drop the role/user combination while the slave still has
|
||||||
|
# its filters active; otherwise, the slave would try to drop users/roles that
|
||||||
|
# were never replicated.
|
||||||
|
--connection master
|
||||||
|
DROP ROLE journalist;
|
||||||
|
DROP USER testuser@localhost;
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
|
--connection slave
|
||||||
|
--source include/sync_with_master_gtid.inc
|
||||||
|
source include/stop_slave.inc;
|
||||||
|
--eval SET @@GLOBAL.replicate_wild_ignore_table="$old_filter"
|
||||||
|
source include/start_slave.inc;
|
||||||
|
|
||||||
|
--source include/rpl_end.inc
|
@@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
|
/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
|
||||||
Copyright (c) 2009, 2020, MariaDB
|
Copyright (c) 2009, 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
|
||||||
@@ -1814,10 +1814,17 @@ class Grant_tables
|
|||||||
public:
|
public:
|
||||||
Grant_tables() : p_user_table(&m_user_table_json) { }
|
Grant_tables() : p_user_table(&m_user_table_json) { }
|
||||||
|
|
||||||
int open_and_lock(THD *thd, int which_tables, enum thr_lock_type lock_type)
|
/**
|
||||||
|
An auxiliary to build a list of involved tables.
|
||||||
|
|
||||||
|
@retval 0 Success
|
||||||
|
@retval -1 A my_error reported error
|
||||||
|
*/
|
||||||
|
int build_table_list(THD *thd, TABLE_LIST** ptr_first,
|
||||||
|
int which_tables, enum thr_lock_type lock_type,
|
||||||
|
TABLE_LIST *tables)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Grant_tables::open_and_lock");
|
DBUG_ENTER("Grant_tables::build_table_list");
|
||||||
TABLE_LIST tables[USER_TABLE+1], *first= NULL;
|
|
||||||
|
|
||||||
DBUG_ASSERT(which_tables); /* At least one table must be opened. */
|
DBUG_ASSERT(which_tables); /* At least one table must be opened. */
|
||||||
/*
|
/*
|
||||||
@@ -1842,12 +1849,23 @@ class Grant_tables
|
|||||||
tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE;
|
tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE;
|
||||||
if (i >= FIRST_OPTIONAL_TABLE)
|
if (i >= FIRST_OPTIONAL_TABLE)
|
||||||
tl->open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
|
tl->open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
|
||||||
tl->next_global= tl->next_local= first;
|
tl->next_global= tl->next_local= *ptr_first;
|
||||||
first= tl;
|
*ptr_first= tl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tl->table= NULL;
|
tl->table= NULL;
|
||||||
}
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int open_and_lock(THD *thd, int which_tables, enum thr_lock_type lock_type)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Grant_tables::open_and_lock");
|
||||||
|
|
||||||
|
TABLE_LIST tables[USER_TABLE+1], *first= NULL;
|
||||||
|
|
||||||
|
if (build_table_list(thd, &first, which_tables, lock_type, tables))
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
uint counter;
|
uint counter;
|
||||||
int res= really_open(thd, first, &counter);
|
int res= really_open(thd, first, &counter);
|
||||||
@@ -1916,6 +1934,48 @@ class Grant_tables
|
|||||||
inline const Roles_mapping_table& roles_mapping_table() const
|
inline const Roles_mapping_table& roles_mapping_table() const
|
||||||
{ return m_roles_mapping_table; }
|
{ return m_roles_mapping_table; }
|
||||||
|
|
||||||
|
#ifdef HAVE_REPLICATION
|
||||||
|
/**
|
||||||
|
Checks if the tables targeted by a grant command should be ignored because
|
||||||
|
of the configured replication filters
|
||||||
|
|
||||||
|
@retval 1 Tables are excluded for replication
|
||||||
|
@retval 0 tables are included for replication
|
||||||
|
*/
|
||||||
|
int rpl_ignore_tables(THD *thd, TABLE_LIST* tables, int which_tables= 0,
|
||||||
|
enum thr_lock_type lock_type= TL_IGNORE)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Grant_tables::rpl_ignore_tables");
|
||||||
|
|
||||||
|
if (!(thd->slave_thread && !thd->spcont))
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
TABLE_LIST all_tables[USER_TABLE+1];
|
||||||
|
|
||||||
|
if (!tables)
|
||||||
|
{
|
||||||
|
int rc __attribute__((unused))=
|
||||||
|
build_table_list(thd, &tables, which_tables, lock_type, all_tables);
|
||||||
|
|
||||||
|
DBUG_ASSERT(!rc); // Grant_tables must be already initialized
|
||||||
|
DBUG_ASSERT(tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tables->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
||||||
|
some kind of updates to the mysql.% tables.
|
||||||
|
*/
|
||||||
|
Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
|
||||||
|
|
||||||
|
if (rpl_filter->is_on() && !rpl_filter->tables_ok(0, tables))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/* Before any operation is possible on grant tables, they must be opened.
|
/* Before any operation is possible on grant tables, they must be opened.
|
||||||
@@ -1929,16 +1989,9 @@ class Grant_tables
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Grant_tables::really_open:");
|
DBUG_ENTER("Grant_tables::really_open:");
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
if (tables->lock_type >= TL_WRITE_ALLOW_WRITE &&
|
if (rpl_ignore_tables(thd, tables))
|
||||||
thd->slave_thread && !thd->spcont)
|
|
||||||
{
|
{
|
||||||
/*
|
DBUG_RETURN(1);
|
||||||
GRANT and REVOKE are applied the slave in/exclusion rules as they are
|
|
||||||
some kind of updates to the mysql.% tables.
|
|
||||||
*/
|
|
||||||
Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
|
|
||||||
if (rpl_filter->is_on() && !rpl_filter->tables_ok(0, tables))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (open_tables(thd, &tables, counter, MYSQL_LOCK_IGNORE_TIMEOUT))
|
if (open_tables(thd, &tables, counter, MYSQL_LOCK_IGNORE_TIMEOUT))
|
||||||
@@ -3940,6 +3993,17 @@ int acl_check_set_default_role(THD *thd, const char *host, const char *user,
|
|||||||
const char *role)
|
const char *role)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("acl_check_set_default_role");
|
DBUG_ENTER("acl_check_set_default_role");
|
||||||
|
#ifdef HAVE_REPLICATION
|
||||||
|
/*
|
||||||
|
If the roles_mapping table is excluded by the replication filter, we return
|
||||||
|
successful without validating the user/role data because the command will
|
||||||
|
be ignored in a later call to `acl_set_default_role()` for a graceful exit.
|
||||||
|
*/
|
||||||
|
Grant_tables tables;
|
||||||
|
TABLE_LIST* first= NULL;
|
||||||
|
if (tables.rpl_ignore_tables(thd, first, Table_roles_mapping, TL_WRITE))
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
#endif
|
||||||
DBUG_RETURN(check_alter_user(thd, host, user) ||
|
DBUG_RETURN(check_alter_user(thd, host, user) ||
|
||||||
check_user_can_set_role(thd, user, host, NULL, role, NULL));
|
check_user_can_set_role(thd, user, host, NULL, role, NULL));
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
Copyright (c) 2008, Google Inc.
|
Copyright (c) 2008, Google Inc.
|
||||||
Copyright (c) 2017, 2021, MariaDB Corporation.
|
Copyright (c) 2017, 2022, MariaDB Corporation.
|
||||||
|
|
||||||
Portions of this file contain modifications contributed and copyrighted by
|
Portions of this file contain modifications contributed and copyrighted by
|
||||||
Google, Inc. Those modifications are gratefully acknowledged and are described
|
Google, Inc. Those modifications are gratefully acknowledged and are described
|
||||||
@@ -1116,9 +1116,6 @@ void btr_search_drop_page_hash_index(buf_block_t* block,
|
|||||||
rw_lock_t* latch;
|
rw_lock_t* latch;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
/* This debug check uses a dirty read that could theoretically cause
|
|
||||||
false positives while buf_pool_clear_hash_index() is executing. */
|
|
||||||
assert_block_ahi_valid(block);
|
|
||||||
ut_ad(!btr_search_own_any(RW_LOCK_S));
|
ut_ad(!btr_search_own_any(RW_LOCK_S));
|
||||||
ut_ad(!btr_search_own_any(RW_LOCK_X));
|
ut_ad(!btr_search_own_any(RW_LOCK_X));
|
||||||
|
|
||||||
|
@@ -3897,42 +3897,6 @@ buf_wait_for_read(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BTR_CUR_HASH_ADAPT
|
|
||||||
/** If a stale adaptive hash index exists on the block, drop it.
|
|
||||||
Multiple executions of btr_search_drop_page_hash_index() on the
|
|
||||||
same block must be prevented by exclusive page latch. */
|
|
||||||
ATTRIBUTE_COLD
|
|
||||||
static void buf_defer_drop_ahi(buf_block_t *block, mtr_memo_type_t fix_type)
|
|
||||||
{
|
|
||||||
switch (fix_type) {
|
|
||||||
case MTR_MEMO_BUF_FIX:
|
|
||||||
/* We do not drop the adaptive hash index, because safely doing
|
|
||||||
so would require acquiring block->lock, and that is not safe
|
|
||||||
to acquire in some RW_NO_LATCH access paths. Those code paths
|
|
||||||
should have no business accessing the adaptive hash index anyway. */
|
|
||||||
break;
|
|
||||||
case MTR_MEMO_PAGE_S_FIX:
|
|
||||||
/* Temporarily release our S-latch. */
|
|
||||||
rw_lock_s_unlock(&block->lock);
|
|
||||||
rw_lock_x_lock(&block->lock);
|
|
||||||
btr_search_drop_page_hash_index(block, true);
|
|
||||||
rw_lock_x_unlock(&block->lock);
|
|
||||||
rw_lock_s_lock(&block->lock);
|
|
||||||
break;
|
|
||||||
case MTR_MEMO_PAGE_SX_FIX:
|
|
||||||
rw_lock_sx_unlock(&block->lock);
|
|
||||||
rw_lock_x_lock(&block->lock);
|
|
||||||
btr_search_drop_page_hash_index(block, true);
|
|
||||||
rw_lock_x_unlock(&block->lock);
|
|
||||||
rw_lock_sx_lock(&block->lock);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ut_ad(fix_type == MTR_MEMO_PAGE_X_FIX);
|
|
||||||
btr_search_drop_page_hash_index(block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* BTR_CUR_HASH_ADAPT */
|
|
||||||
|
|
||||||
/** Lock the page with the given latch type.
|
/** Lock the page with the given latch type.
|
||||||
@param[in,out] block block to be locked
|
@param[in,out] block block to be locked
|
||||||
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
|
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
|
||||||
@@ -3968,10 +3932,7 @@ static buf_block_t* buf_page_mtr_lock(buf_block_t *block,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BTR_CUR_HASH_ADAPT
|
#ifdef BTR_CUR_HASH_ADAPT
|
||||||
{
|
btr_search_drop_page_hash_index(block, true);
|
||||||
if (block->index)
|
|
||||||
buf_defer_drop_ahi(block, fix_type);
|
|
||||||
}
|
|
||||||
#endif /* BTR_CUR_HASH_ADAPT */
|
#endif /* BTR_CUR_HASH_ADAPT */
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@@ -1159,7 +1159,7 @@ dict_create_table_step(
|
|||||||
if (node->state == TABLE_ADD_TO_CACHE) {
|
if (node->state == TABLE_ADD_TO_CACHE) {
|
||||||
DBUG_EXECUTE_IF("ib_ddl_crash_during_create", DBUG_SUICIDE(););
|
DBUG_EXECUTE_IF("ib_ddl_crash_during_create", DBUG_SUICIDE(););
|
||||||
|
|
||||||
node->table->can_be_evicted = true;
|
node->table->can_be_evicted = !node->table->fts;
|
||||||
node->table->add_to_cache();
|
node->table->add_to_cache();
|
||||||
|
|
||||||
err = DB_SUCCESS;
|
err = DB_SUCCESS;
|
||||||
|
@@ -14397,9 +14397,11 @@ ha_innobase::info_low(
|
|||||||
stats.index_file_length
|
stats.index_file_length
|
||||||
= ulonglong(stat_sum_of_other_index_sizes)
|
= ulonglong(stat_sum_of_other_index_sizes)
|
||||||
* size;
|
* size;
|
||||||
|
rw_lock_s_lock(&space->latch);
|
||||||
stats.delete_length = 1024
|
stats.delete_length = 1024
|
||||||
* fsp_get_available_space_in_free_extents(
|
* fsp_get_available_space_in_free_extents(
|
||||||
*space);
|
*space);
|
||||||
|
rw_lock_s_unlock(&space->latch);
|
||||||
}
|
}
|
||||||
stats.check_time = 0;
|
stats.check_time = 0;
|
||||||
stats.mrr_length_per_rec= (uint)ref_length + 8; // 8 = max(sizeof(void *));
|
stats.mrr_length_per_rec= (uint)ref_length + 8; // 8 = max(sizeof(void *));
|
||||||
|
Reference in New Issue
Block a user