Skip to content

Commit

Permalink
Merge 10.5 into 10.6
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-m committed Aug 25, 2022
2 parents 8ff1096 + 9929301 commit 76bb671
Show file tree
Hide file tree
Showing 13 changed files with 317 additions and 121 deletions.
2 changes: 1 addition & 1 deletion mysql-test/include/mtr_warnings.sql
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ INSERT INTO global_suppressions VALUES

/* 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"),
("Restore: Operation aborted"),
("Restore: The grant .* was skipped because the user does not exist"),
Expand Down
55 changes: 55 additions & 0 deletions mysql-test/suite/rpl/r/rpl_filter_set_var_missing_data.result
Original file line number Diff line number Diff line change
@@ -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 changes: 83 additions & 0 deletions mysql-test/suite/rpl/t/rpl_filter_set_var_missing_data.test
Original file line number Diff line number Diff line change
@@ -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
94 changes: 79 additions & 15 deletions sql/sql_acl.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
Copyright (c) 2009, 2021, MariaDB
Copyright (c) 2009, 2022, MariaDB

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
Expand Down Expand Up @@ -1937,10 +1937,17 @@ class Grant_tables
public:
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");
TABLE_LIST tables[USER_TABLE+1], *first= NULL;
DBUG_ENTER("Grant_tables::build_table_list");

DBUG_ASSERT(which_tables); /* At least one table must be opened. */
/*
Expand All @@ -1965,12 +1972,23 @@ class Grant_tables
tl->updating= lock_type >= TL_FIRST_WRITE;
if (i >= FIRST_OPTIONAL_TABLE)
tl->open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
tl->next_global= tl->next_local= first;
first= tl;
tl->next_global= tl->next_local= *ptr_first;
*ptr_first= tl;
}
else
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;
int res= really_open(thd, first, &counter);
Expand Down Expand Up @@ -2041,6 +2059,48 @@ class Grant_tables
inline const Roles_mapping_table& roles_mapping_table() const
{ 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_FIRST_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:

/* Before any operation is possible on grant tables, they must be opened.
Expand All @@ -2054,16 +2114,9 @@ class Grant_tables
{
DBUG_ENTER("Grant_tables::really_open:");
#ifdef HAVE_REPLICATION
if (tables->lock_type >= TL_FIRST_WRITE &&
thd->slave_thread && !thd->spcont)
if (rpl_ignore_tables(thd, tables))
{
/*
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(1);
}
#endif
if (open_tables(thd, &tables, counter, MYSQL_LOCK_IGNORE_TIMEOUT))
Expand Down Expand Up @@ -4074,6 +4127,17 @@ int acl_check_set_default_role(THD *thd, const char *host, const char *user,
const char *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) ||
check_user_can_set_role(thd, user, host, NULL, role, NULL));
}
Expand Down
6 changes: 2 additions & 4 deletions storage/innobase/btr/btr0btr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,7 @@ btr_page_alloc_low(
mtr->u_lock_register(savepoint);
root->page.lock.u_lock();
#ifdef BTR_CUR_HASH_ADAPT
if (root->index)
mtr_t::defer_drop_ahi(root, MTR_MEMO_PAGE_SX_FIX);
btr_search_drop_page_hash_index(root, true);
#endif
}

Expand Down Expand Up @@ -645,8 +644,7 @@ dberr_t btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
mtr->u_lock_register(savepoint);
root->page.lock.u_lock();
#ifdef BTR_CUR_HASH_ADAPT
if (root->index)
mtr_t::defer_drop_ahi(root, MTR_MEMO_PAGE_SX_FIX);
btr_search_drop_page_hash_index(root, true);
#endif
}
err= fseg_free_page(&root->page.frame[blob ||
Expand Down
4 changes: 0 additions & 4 deletions storage/innobase/btr/btr0sea.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1292,10 +1292,6 @@ void btr_search_drop_page_hash_index(buf_block_t* block,
rec_offs* offsets;

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);

if (!block->index) {
return;
}
Expand Down
6 changes: 2 additions & 4 deletions storage/innobase/buf/buf0buf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2818,12 +2818,10 @@ buf_page_get_low(
goto page_id_mismatch;
}
get_latch_valid:
mtr->memo_push(block, fix_type);
#ifdef BTR_CUR_HASH_ADAPT
if (block->index) {
mtr_t::defer_drop_ahi(block, fix_type);
}
btr_search_drop_page_hash_index(block, true);
#endif /* BTR_CUR_HASH_ADAPT */
mtr->memo_push(block, fix_type);
break;
case RW_SX_LATCH:
fix_type = MTR_MEMO_PAGE_SX_FIX;
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/dict/dict0crea.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,7 @@ dict_create_table_step(
if (node->state == TABLE_ADD_TO_CACHE) {
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();

err = DB_SUCCESS;
Expand Down
2 changes: 2 additions & 0 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14845,9 +14845,11 @@ ha_innobase::info_low(
stats.index_file_length
= ulonglong(stat_sum_of_other_index_sizes)
* size;
space->s_lock();
stats.delete_length = 1024
* fsp_get_available_space_in_free_extents(
*space);
space->s_unlock();
}
stats.check_time = 0;
stats.mrr_length_per_rec= (uint)ref_length + 8; // 8 = max(sizeof(void *));
Expand Down
6 changes: 0 additions & 6 deletions storage/innobase/include/mtr0mtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -622,12 +622,6 @@ struct mtr_t {
PAGE_FLUSH_SYNC
};

#ifdef BTR_CUR_HASH_ADAPT
/** If a stale adaptive hash index exists on the block, drop it. */
ATTRIBUTE_COLD
static void defer_drop_ahi(buf_block_t *block, mtr_memo_type_t fix_type);
#endif

private:
/** Log a write of a byte string to a page.
@param block buffer page
Expand Down
Loading

0 comments on commit 76bb671

Please sign in to comment.