Skip to content

Commit 9929301

Browse files
committed
Merge 10.4 into 10.5
2 parents a3fd9e6 + 851058a commit 9929301

File tree

8 files changed

+222
-60
lines changed

8 files changed

+222
-60
lines changed

mysql-test/include/mtr_warnings.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ INSERT INTO global_suppressions VALUES
174174

175175
/* Added 2009-08-XX after fixing Bug #42408 */
176176

177-
("Although a path was specified for the .* option, log tables are used"),
177+
("Although a .* file was specified, log tables are used. To enable logging to files "),
178178
("Backup: Operation aborted"),
179179
("Restore: Operation aborted"),
180180
("Restore: The grant .* was skipped because the user does not exist"),
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
include/master-slave.inc
2+
[connection master]
3+
#
4+
# Set replica to ignore system mysql tables
5+
connection slave;
6+
include/stop_slave.inc
7+
SET @@GLOBAL.replicate_wild_ignore_table="mysql.%";
8+
include/start_slave.inc
9+
#
10+
# Execute grant-based commands on primary which modify mysql system
11+
# tables
12+
connection master;
13+
CREATE ROLE journalist;
14+
CREATE USER testuser@localhost IDENTIFIED by '';
15+
GRANT journalist to testuser@localhost;
16+
#
17+
# Execute SET commands which use the previous user/role data
18+
SET DEFAULT ROLE journalist for testuser@localhost;
19+
SET PASSWORD for testuser@localhost= PASSWORD('123');
20+
include/save_master_gtid.inc
21+
#
22+
# Verify primary's grant tables have the correct user/role data
23+
select count(*)=1 from mysql.user where User='testuser';
24+
count(*)=1
25+
1
26+
select count(*)=1 from mysql.roles_mapping where User='testuser';
27+
count(*)=1
28+
1
29+
#
30+
# Ensure that the replica receives all of the primary's events without
31+
# error
32+
connection slave;
33+
include/sync_with_master_gtid.inc
34+
Last_SQL_Error =
35+
Last_SQL_Errno = 0
36+
#
37+
# Verify that the replica did not execute the master's commands
38+
select count(*)=0 from mysql.user where User='testuser';
39+
count(*)=0
40+
1
41+
select count(*)=0 from mysql.roles_mapping where User='testuser';
42+
count(*)=0
43+
1
44+
#
45+
# Clean up
46+
connection master;
47+
DROP ROLE journalist;
48+
DROP USER testuser@localhost;
49+
include/save_master_gtid.inc
50+
connection slave;
51+
include/sync_with_master_gtid.inc
52+
include/stop_slave.inc
53+
SET @@GLOBAL.replicate_wild_ignore_table="";
54+
include/start_slave.inc
55+
include/rpl_end.inc
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#
2+
# Purpose:
3+
# This test ensures that the SET DEFAULT ROLE and SET PASSWORD commands can
4+
# be ignored by replica filter rules. MDEV-28294 exposed a bug in which
5+
# SET DEFAULT ROLE would check for the existence of the given roles/user even
6+
# when the targeted tables are ignored, resulting in errors if the targeted
7+
# data does not exist. More specifically, when previously issued
8+
# CREATE USER/ROLE commands are ignored by the replica because of the
9+
# replication filtering rules, SET DEFAULT ROLE would result in an error
10+
# because the targeted data does not exist.
11+
#
12+
# Methodology:
13+
# Using a replica configured with replicate_wild_ignore_table="mysql.%",
14+
# execute SET DEFAULT ROLE and SET PASSWORD on the primary and ensure that the
15+
# replica neither errors nor executes the commands which the primary sends.
16+
#
17+
# References:
18+
# MDEV-28294: set default role bypasses Replicate_Wild_Ignore_Table: mysql.%
19+
#
20+
21+
source include/master-slave.inc;
22+
source include/have_binlog_format_mixed.inc;
23+
24+
--echo #
25+
--echo # Set replica to ignore system mysql tables
26+
connection slave;
27+
let $old_filter= query_get_value(SHOW SLAVE STATUS, Replicate_Wild_Ignore_Table, 1);
28+
source include/stop_slave.inc;
29+
SET @@GLOBAL.replicate_wild_ignore_table="mysql.%";
30+
source include/start_slave.inc;
31+
32+
--echo #
33+
--echo # Execute grant-based commands on primary which modify mysql system
34+
--echo # tables
35+
connection master;
36+
CREATE ROLE journalist;
37+
CREATE USER testuser@localhost IDENTIFIED by '';
38+
GRANT journalist to testuser@localhost;
39+
40+
--echo #
41+
--echo # Execute SET commands which use the previous user/role data
42+
SET DEFAULT ROLE journalist for testuser@localhost;
43+
SET PASSWORD for testuser@localhost= PASSWORD('123');
44+
--source include/save_master_gtid.inc
45+
46+
--echo #
47+
--echo # Verify primary's grant tables have the correct user/role data
48+
select count(*)=1 from mysql.user where User='testuser';
49+
select count(*)=1 from mysql.roles_mapping where User='testuser';
50+
51+
--echo #
52+
--echo # Ensure that the replica receives all of the primary's events without
53+
--echo # error
54+
connection slave;
55+
--source include/sync_with_master_gtid.inc
56+
let $error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
57+
--echo Last_SQL_Error = $error
58+
let $errno= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
59+
--echo Last_SQL_Errno = $errno
60+
61+
--echo #
62+
--echo # Verify that the replica did not execute the master's commands
63+
select count(*)=0 from mysql.user where User='testuser';
64+
select count(*)=0 from mysql.roles_mapping where User='testuser';
65+
66+
--echo #
67+
--echo # Clean up
68+
69+
# The master has to drop the role/user combination while the slave still has
70+
# its filters active; otherwise, the slave would try to drop users/roles that
71+
# were never replicated.
72+
--connection master
73+
DROP ROLE journalist;
74+
DROP USER testuser@localhost;
75+
--source include/save_master_gtid.inc
76+
77+
--connection slave
78+
--source include/sync_with_master_gtid.inc
79+
source include/stop_slave.inc;
80+
--eval SET @@GLOBAL.replicate_wild_ignore_table="$old_filter"
81+
source include/start_slave.inc;
82+
83+
--source include/rpl_end.inc

sql/sql_acl.cc

Lines changed: 79 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
2-
Copyright (c) 2009, 2021, MariaDB
2+
Copyright (c) 2009, 2022, MariaDB
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -1937,10 +1937,17 @@ class Grant_tables
19371937
public:
19381938
Grant_tables() : p_user_table(&m_user_table_json) { }
19391939

1940-
int open_and_lock(THD *thd, int which_tables, enum thr_lock_type lock_type)
1940+
/**
1941+
An auxiliary to build a list of involved tables.
1942+
1943+
@retval 0 Success
1944+
@retval -1 A my_error reported error
1945+
*/
1946+
int build_table_list(THD *thd, TABLE_LIST** ptr_first,
1947+
int which_tables, enum thr_lock_type lock_type,
1948+
TABLE_LIST *tables)
19411949
{
1942-
DBUG_ENTER("Grant_tables::open_and_lock");
1943-
TABLE_LIST tables[USER_TABLE+1], *first= NULL;
1950+
DBUG_ENTER("Grant_tables::build_table_list");
19441951

19451952
DBUG_ASSERT(which_tables); /* At least one table must be opened. */
19461953
/*
@@ -1965,12 +1972,23 @@ class Grant_tables
19651972
tl->updating= lock_type >= TL_WRITE_ALLOW_WRITE;
19661973
if (i >= FIRST_OPTIONAL_TABLE)
19671974
tl->open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
1968-
tl->next_global= tl->next_local= first;
1969-
first= tl;
1975+
tl->next_global= tl->next_local= *ptr_first;
1976+
*ptr_first= tl;
19701977
}
19711978
else
19721979
tl->table= NULL;
19731980
}
1981+
DBUG_RETURN(0);
1982+
}
1983+
1984+
int open_and_lock(THD *thd, int which_tables, enum thr_lock_type lock_type)
1985+
{
1986+
DBUG_ENTER("Grant_tables::open_and_lock");
1987+
1988+
TABLE_LIST tables[USER_TABLE+1], *first= NULL;
1989+
1990+
if (build_table_list(thd, &first, which_tables, lock_type, tables))
1991+
DBUG_RETURN(-1);
19741992

19751993
uint counter;
19761994
int res= really_open(thd, first, &counter);
@@ -2041,6 +2059,48 @@ class Grant_tables
20412059
inline const Roles_mapping_table& roles_mapping_table() const
20422060
{ return m_roles_mapping_table; }
20432061

2062+
#ifdef HAVE_REPLICATION
2063+
/**
2064+
Checks if the tables targeted by a grant command should be ignored because
2065+
of the configured replication filters
2066+
2067+
@retval 1 Tables are excluded for replication
2068+
@retval 0 tables are included for replication
2069+
*/
2070+
int rpl_ignore_tables(THD *thd, TABLE_LIST* tables, int which_tables= 0,
2071+
enum thr_lock_type lock_type= TL_IGNORE)
2072+
{
2073+
DBUG_ENTER("Grant_tables::rpl_ignore_tables");
2074+
2075+
if (!(thd->slave_thread && !thd->spcont))
2076+
DBUG_RETURN(0);
2077+
2078+
TABLE_LIST all_tables[USER_TABLE+1];
2079+
2080+
if (!tables)
2081+
{
2082+
int rc __attribute__((unused))=
2083+
build_table_list(thd, &tables, which_tables, lock_type, all_tables);
2084+
2085+
DBUG_ASSERT(!rc); // Grant_tables must be already initialized
2086+
DBUG_ASSERT(tables);
2087+
}
2088+
2089+
if (tables->lock_type >= TL_WRITE_ALLOW_WRITE)
2090+
{
2091+
/*
2092+
GRANT and REVOKE are applied the slave in/exclusion rules as they are
2093+
some kind of updates to the mysql.% tables.
2094+
*/
2095+
Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
2096+
2097+
if (rpl_filter->is_on() && !rpl_filter->tables_ok(0, tables))
2098+
DBUG_RETURN(1);
2099+
}
2100+
DBUG_RETURN(0);
2101+
}
2102+
#endif
2103+
20442104
private:
20452105

20462106
/* Before any operation is possible on grant tables, they must be opened.
@@ -2054,16 +2114,9 @@ class Grant_tables
20542114
{
20552115
DBUG_ENTER("Grant_tables::really_open:");
20562116
#ifdef HAVE_REPLICATION
2057-
if (tables->lock_type >= TL_WRITE_ALLOW_WRITE &&
2058-
thd->slave_thread && !thd->spcont)
2117+
if (rpl_ignore_tables(thd, tables))
20592118
{
2060-
/*
2061-
GRANT and REVOKE are applied the slave in/exclusion rules as they are
2062-
some kind of updates to the mysql.% tables.
2063-
*/
2064-
Rpl_filter *rpl_filter= thd->system_thread_info.rpl_sql_info->rpl_filter;
2065-
if (rpl_filter->is_on() && !rpl_filter->tables_ok(0, tables))
2066-
DBUG_RETURN(1);
2119+
DBUG_RETURN(1);
20672120
}
20682121
#endif
20692122
if (open_tables(thd, &tables, counter, MYSQL_LOCK_IGNORE_TIMEOUT))
@@ -4075,6 +4128,17 @@ int acl_check_set_default_role(THD *thd, const char *host, const char *user,
40754128
const char *role)
40764129
{
40774130
DBUG_ENTER("acl_check_set_default_role");
4131+
#ifdef HAVE_REPLICATION
4132+
/*
4133+
If the roles_mapping table is excluded by the replication filter, we return
4134+
successful without validating the user/role data because the command will
4135+
be ignored in a later call to `acl_set_default_role()` for a graceful exit.
4136+
*/
4137+
Grant_tables tables;
4138+
TABLE_LIST* first= NULL;
4139+
if (tables.rpl_ignore_tables(thd, first, Table_roles_mapping, TL_WRITE))
4140+
DBUG_RETURN(0);
4141+
#endif
40784142
DBUG_RETURN(check_alter_user(thd, host, user) ||
40794143
check_user_can_set_role(thd, user, host, NULL, role, NULL));
40804144
}

storage/innobase/btr/btr0sea.cc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,9 +1266,6 @@ void btr_search_drop_page_hash_index(buf_block_t* block,
12661266
rec_offs* offsets;
12671267

12681268
retry:
1269-
/* This debug check uses a dirty read that could theoretically cause
1270-
false positives while buf_pool.clear_hash_index() is executing. */
1271-
assert_block_ahi_valid(block);
12721269
ut_ad(!btr_search_own_any(RW_LOCK_S));
12731270
ut_ad(!btr_search_own_any(RW_LOCK_X));
12741271

storage/innobase/buf/buf0buf.cc

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2583,42 +2583,6 @@ buf_wait_for_read(
25832583
}
25842584
}
25852585

2586-
#ifdef BTR_CUR_HASH_ADAPT
2587-
/** If a stale adaptive hash index exists on the block, drop it.
2588-
Multiple executions of btr_search_drop_page_hash_index() on the
2589-
same block must be prevented by exclusive page latch. */
2590-
ATTRIBUTE_COLD
2591-
static void buf_defer_drop_ahi(buf_block_t *block, mtr_memo_type_t fix_type)
2592-
{
2593-
switch (fix_type) {
2594-
case MTR_MEMO_BUF_FIX:
2595-
/* We do not drop the adaptive hash index, because safely doing
2596-
so would require acquiring block->lock, and that is not safe
2597-
to acquire in some RW_NO_LATCH access paths. Those code paths
2598-
should have no business accessing the adaptive hash index anyway. */
2599-
break;
2600-
case MTR_MEMO_PAGE_S_FIX:
2601-
/* Temporarily release our S-latch. */
2602-
rw_lock_s_unlock(&block->lock);
2603-
rw_lock_x_lock(&block->lock);
2604-
btr_search_drop_page_hash_index(block, true);
2605-
rw_lock_x_unlock(&block->lock);
2606-
rw_lock_s_lock(&block->lock);
2607-
break;
2608-
case MTR_MEMO_PAGE_SX_FIX:
2609-
rw_lock_sx_unlock(&block->lock);
2610-
rw_lock_x_lock(&block->lock);
2611-
btr_search_drop_page_hash_index(block, true);
2612-
rw_lock_x_unlock(&block->lock);
2613-
rw_lock_sx_lock(&block->lock);
2614-
break;
2615-
default:
2616-
ut_ad(fix_type == MTR_MEMO_PAGE_X_FIX);
2617-
btr_search_drop_page_hash_index(block);
2618-
}
2619-
}
2620-
#endif /* BTR_CUR_HASH_ADAPT */
2621-
26222586
/** Lock the page with the given latch type.
26232587
@param[in,out] block block to be locked
26242588
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
@@ -2654,10 +2618,7 @@ static buf_block_t* buf_page_mtr_lock(buf_block_t *block,
26542618
}
26552619

26562620
#ifdef BTR_CUR_HASH_ADAPT
2657-
{
2658-
if (block->index)
2659-
buf_defer_drop_ahi(block, fix_type);
2660-
}
2621+
btr_search_drop_page_hash_index(block, true);
26612622
#endif /* BTR_CUR_HASH_ADAPT */
26622623

26632624
done:

storage/innobase/dict/dict0crea.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,7 @@ dict_create_table_step(
11591159
if (node->state == TABLE_ADD_TO_CACHE) {
11601160
DBUG_EXECUTE_IF("ib_ddl_crash_during_create", DBUG_SUICIDE(););
11611161

1162-
node->table->can_be_evicted = true;
1162+
node->table->can_be_evicted = !node->table->fts;
11631163
node->table->add_to_cache();
11641164

11651165
err = DB_SUCCESS;

storage/innobase/handler/ha_innodb.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14431,9 +14431,11 @@ ha_innobase::info_low(
1443114431
stats.index_file_length
1443214432
= ulonglong(stat_sum_of_other_index_sizes)
1443314433
* size;
14434+
rw_lock_s_lock(&space->latch);
1443414435
stats.delete_length = 1024
1443514436
* fsp_get_available_space_in_free_extents(
1443614437
*space);
14438+
rw_lock_s_unlock(&space->latch);
1443714439
}
1443814440
stats.check_time = 0;
1443914441
stats.mrr_length_per_rec= (uint)ref_length + 8; // 8 = max(sizeof(void *));

0 commit comments

Comments
 (0)