summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-11-13 21:54:21 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-11-13 21:54:21 +0200
commitd7a582489900ea175d9659304c4fdc39b3880014 (patch)
tree06a2485b15b84fedf197c573276441ea8d8bccb0
parent97569d3c37a66bc941b933ac7c2cefa5430a5175 (diff)
parentb2029c0300bf8c311ff5d9fdc4b73a9e48bf6930 (diff)
downloadmariadb-git-d7a582489900ea175d9659304c4fdc39b3880014.tar.gz
Merge 10.4 into 10.5
-rw-r--r--include/wsrep.h26
-rw-r--r--mysql-test/main/lock_user.result37
-rw-r--r--mysql-test/main/lock_user.test26
-rwxr-xr-xmysql-test/mysql-test-run.pl3
-rw-r--r--mysql-test/suite/galera/r/MDEV-24063.result8
-rw-r--r--mysql-test/suite/galera/r/galera_ddl_fk_conflict.result657
-rw-r--r--mysql-test/suite/galera/r/galera_trigger.result48
-rw-r--r--mysql-test/suite/galera/t/MDEV-24063.test20
-rw-r--r--mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc192
-rw-r--r--mysql-test/suite/galera/t/galera_ddl_fk_conflict.test37
-rw-r--r--mysql-test/suite/galera/t/galera_ddl_fk_conflict_with_tmp.inc69
-rw-r--r--mysql-test/suite/galera/t/galera_trigger.test8
-rw-r--r--mysql-test/suite/galera/t/mysql-wsrep#198-master.opt1
-rw-r--r--mysql-test/suite/galera/t/mysql-wsrep#198.cnf9
-rw-r--r--mysql-test/suite/galera/t/mysql-wsrep#198.test1
-rw-r--r--mysql-test/suite/maria/repair.result16
-rw-r--r--mysql-test/suite/maria/repair.test11
-rw-r--r--mysql-test/suite/perfschema/r/sxlock_func.result1
-rw-r--r--mysql-test/suite/period/r/create.result4
-rw-r--r--mysql-test/suite/period/t/create.test6
-rw-r--r--mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result2
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test12
-rw-r--r--scripts/mysqld_safe.sh3
-rw-r--r--sql/log.h2
-rw-r--r--sql/rpl_rli.cc4
-rw-r--r--sql/rpl_rli.h3
-rw-r--r--sql/slave.cc4
-rw-r--r--sql/sql_acl.cc6
-rw-r--r--sql/sql_admin.cc108
-rw-r--r--sql/sql_alter.cc33
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_lex.h6
-rw-r--r--sql/sql_truncate.cc20
-rw-r--r--sql/sql_yacc.yy35
-rw-r--r--sql/wsrep_client_service.cc27
-rw-r--r--sql/wsrep_client_service.h11
-rw-r--r--sql/wsrep_mysqld.cc76
-rw-r--r--sql/wsrep_mysqld.h9
-rw-r--r--storage/innobase/buf/buf0buf.cc8
-rw-r--r--storage/innobase/dict/dict0dict.cc84
-rw-r--r--storage/innobase/handler/ha_innodb.cc20
-rw-r--r--storage/innobase/handler/ha_innodb.h7
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc83
-rw-r--r--storage/innobase/include/dict0dict.h27
-rw-r--r--storage/innobase/include/ibuf0ibuf.h18
-rw-r--r--storage/innobase/include/trx0trx.h14
-rw-r--r--storage/innobase/os/os0file.cc240
-rw-r--r--storage/innobase/trx/trx0rec.cc6
-rw-r--r--storage/innobase/trx/trx0trx.cc4
-rw-r--r--storage/maria/ma_check.c34
-rw-r--r--storage/maria/ma_delete_table.c9
-rw-r--r--storage/maria/ma_open.c2
m---------wsrep-lib0
53 files changed, 1627 insertions, 472 deletions
diff --git a/include/wsrep.h b/include/wsrep.h
index f8a1863b966..703b89f966a 100644
--- a/include/wsrep.h
+++ b/include/wsrep.h
@@ -25,21 +25,24 @@
#define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A)
#define WSREP_MYSQL_DB (char *)"mysql"
+#define WSREP_TO_ISOLATION_BEGIN_IF(db_, table_, table_list_) \
+ if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_))
-#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \
- if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \
+#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \
+ if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \
goto wsrep_error_label;
#define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_) \
- if (WSREP(thd) && \
+ if (WSREP_ON && WSREP(thd) && \
wsrep_to_isolation_begin(thd, db_, table_, \
- table_list_, NULL, create_info_)) \
+ table_list_, nullptr, nullptr, create_info_))\
goto wsrep_error_label;
-#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, create_info_) \
- if (WSREP(thd) && wsrep_thd_is_local(thd) && \
- wsrep_to_isolation_begin(thd, db_, table_, \
- table_list_, alter_info_, create_info_)) \
+#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, fk_tables_, create_info_) \
+ if (WSREP(thd) && wsrep_thd_is_local(thd) && \
+ wsrep_to_isolation_begin(thd, db_, table_, \
+ table_list_, alter_info_, \
+ fk_tables_, create_info_)) \
goto wsrep_error_label;
#define WSREP_TO_ISOLATION_END \
@@ -55,6 +58,10 @@
if (WSREP(thd) && !thd->lex->no_write_to_binlog \
&& wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto wsrep_error_label;
+#define WSREP_TO_ISOLATION_BEGIN_FK_TABLES(db_, table_, table_list_, fk_tables) \
+ if (WSREP(thd) && !thd->lex->no_write_to_binlog \
+ && wsrep_to_isolation_begin(thd, db_, table_, table_list_, NULL, fk_tables))
+
#define WSREP_SYNC_WAIT(thd_, before_) \
{ if (WSREP_CLIENT(thd_) && \
wsrep_sync_wait(thd_, before_)) goto wsrep_error_label; }
@@ -68,7 +75,8 @@
#define WSREP_DEBUG(...)
#define WSREP_ERROR(...)
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) do { } while(0)
-#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, create_info_)
+#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, fk_tables_, create_info_)
+#define WSREP_TO_ISOLATION_BEGIN_FK_TABLES(db_, table_, table_list_, fk_tables_)
#define WSREP_TO_ISOLATION_END
#define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_)
#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_)
diff --git a/mysql-test/main/lock_user.result b/mysql-test/main/lock_user.result
index 5048c5a9bee..d2221e2cd8c 100644
--- a/mysql-test/main/lock_user.result
+++ b/mysql-test/main/lock_user.result
@@ -130,5 +130,42 @@ connection default;
#
alter user user1@localhost account lock;
ERROR HY000: Access denied, this account is locked
+#
+# MDEV-24098 SHOW CREATE USER invalid for both PASSWORD EXPIRE and
+# and LOCKED
+#
+alter user user1@localhost PASSWORD EXPIRE;
+show create user user1@localhost;
+CREATE USER for user1@localhost
+CREATE USER `user1`@`localhost` ACCOUNT LOCK PASSWORD EXPIRE
+drop user user1@localhost;
+#
+# MDEV-24098 CREATE USER/ALTER USER PASSWORD EXPIRE/LOCK in
+# either order.
+#
+create user user1@localhost PASSWORD EXPIRE ACCOUNT LOCK;
+show create user user1@localhost;
+CREATE USER for user1@localhost
+CREATE USER `user1`@`localhost` ACCOUNT LOCK PASSWORD EXPIRE
+drop user user1@localhost;
+create user user1@localhost ACCOUNT LOCK PASSWORD EXPIRE;
+show create user user1@localhost;
+CREATE USER for user1@localhost
+CREATE USER `user1`@`localhost` ACCOUNT LOCK PASSWORD EXPIRE
+alter user user1@localhost PASSWORD EXPIRE NEVER ACCOUNT UNLOCK ;
+show create user user1@localhost;
+CREATE USER for user1@localhost
+CREATE USER `user1`@`localhost` PASSWORD EXPIRE
+alter user user1@localhost ACCOUNT LOCK PASSWORD EXPIRE DEFAULT;
+show create user user1@localhost;
+CREATE USER for user1@localhost
+CREATE USER `user1`@`localhost` ACCOUNT LOCK PASSWORD EXPIRE
+alter user user1@localhost PASSWORD EXPIRE INTERVAL 60 DAY ACCOUNT UNLOCK;
+select * from mysql.global_priv where user='user1';
+Host User Priv
+localhost user1 {"access":0,"version_id":100509,"plugin":"mysql_native_password","authentication_string":"","account_locked":false,"password_last_changed":0,"password_lifetime":60}
+show create user user1@localhost;
+CREATE USER for user1@localhost
+CREATE USER `user1`@`localhost` PASSWORD EXPIRE
drop user user1@localhost;
drop user user2@localhost;
diff --git a/mysql-test/main/lock_user.test b/mysql-test/main/lock_user.test
index 17ce1cc79da..530883f33ef 100644
--- a/mysql-test/main/lock_user.test
+++ b/mysql-test/main/lock_user.test
@@ -137,6 +137,32 @@ alter user user1@localhost account lock;
--error ER_ACCOUNT_HAS_BEEN_LOCKED
--change_user user1
+--echo #
+--echo # MDEV-24098 SHOW CREATE USER invalid for both PASSWORD EXPIRE and
+--echo # and LOCKED
+--echo #
+alter user user1@localhost PASSWORD EXPIRE;
+show create user user1@localhost;
+drop user user1@localhost;
+
+--echo #
+--echo # MDEV-24098 CREATE USER/ALTER USER PASSWORD EXPIRE/LOCK in
+--echo # either order.
+--echo #
+create user user1@localhost PASSWORD EXPIRE ACCOUNT LOCK;
+show create user user1@localhost;
+drop user user1@localhost;
+create user user1@localhost ACCOUNT LOCK PASSWORD EXPIRE;
+show create user user1@localhost;
+alter user user1@localhost PASSWORD EXPIRE NEVER ACCOUNT UNLOCK ;
+show create user user1@localhost;
+alter user user1@localhost ACCOUNT LOCK PASSWORD EXPIRE DEFAULT;
+show create user user1@localhost;
+# note output needs to be corrected by MDEV-24114: password expire users cannot be unexpired
+alter user user1@localhost PASSWORD EXPIRE INTERVAL 60 DAY ACCOUNT UNLOCK;
+select * from mysql.global_priv where user='user1';
+show create user user1@localhost;
+
drop user user1@localhost;
drop user user2@localhost;
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 37089f6dec6..b2f948fe31d 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -647,6 +647,7 @@ sub run_test_server ($$$) {
# Client disconnected
mtr_verbose("Child closed socket");
$s->remove($sock);
+ $sock->close;
if (--$childs == 0){
return ("Completed", $test_failure, $completed, $extra_warnings);
}
@@ -816,6 +817,7 @@ sub run_test_server ($$$) {
# Test failure due to warnings, force is off
return ("Warnings in log", 1, $completed, $extra_warnings);
}
+ next;
}
elsif ($line =~ /^SPENT/) {
add_total_times($line);
@@ -4102,6 +4104,7 @@ sub run_testcase ($$) {
if (start_servers($tinfo))
{
report_failure_and_restart($tinfo);
+ unlink $path_current_testlog;
return 1;
}
}
diff --git a/mysql-test/suite/galera/r/MDEV-24063.result b/mysql-test/suite/galera/r/MDEV-24063.result
new file mode 100644
index 00000000000..757cc07a642
--- /dev/null
+++ b/mysql-test/suite/galera/r/MDEV-24063.result
@@ -0,0 +1,8 @@
+connection node_2;
+connection node_1;
+connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
+connection node_2a;
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
+connection node_2;
+SET GLOBAL wsrep_on=OFF;
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result b/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result
new file mode 100644
index 00000000000..5f09345b79b
--- /dev/null
+++ b/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result
@@ -0,0 +1,657 @@
+connection node_2;
+connection node_1;
+connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_1a;
+SET SESSION wsrep_sync_wait=0;
+connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1;
+connection node_1b;
+SET SESSION wsrep_sync_wait=0;
+######################################################################
+# Test for OPTIMIZE
+######################################################################
+######################################################################
+#
+# Scenario #1: DML working on FK parent table BF aborted by DDL
+# over child table
+#
+######################################################################
+connection node_1;
+SET SESSION wsrep_sync_wait=0;
+CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
+CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p2 VALUES (1, 'INITIAL VALUE');
+INSERT INTO p2 VALUES (2, 'INITIAL VALUE');
+CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
+INSERT INTO c1 VALUES (1,1);
+CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk));
+INSERT INTO c2 VALUES (1,1,1), (2,1,2);
+connection node_1;
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+connection node_2;
+SET SESSION wsrep_sync_wait=0;
+OPTIMIZE TABLE c1 ;
+Table Op Msg_type Msg_text
+test.c1 optimize note Table does not support optimize, doing recreate + analyze instead
+test.c1 optimize status OK
+connection node_1;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+######################################################################
+#
+# Scenario #2: DML working on FK parent table tries to replicate, but
+# fails in certification for earlier DDL on child table
+#
+######################################################################
+connection node_1;
+BEGIN;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+OPTIMIZE TABLE c1 ;
+Table Op Msg_type Msg_text
+test.c1 optimize note Table does not support optimize, doing recreate + analyze instead
+test.c1 optimize status OK
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+COMMIT;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+######################################################################
+#
+# Scenario #3: 2 DMLs working on two FK parent tables try to replicate,
+# but fails in certification for earlier DDL on child table
+# which is child to both FK parents
+#
+######################################################################
+connection node_1;
+BEGIN;
+connection node_1b;
+BEGIN;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+OPTIMIZE TABLE c2 ;
+Table Op Msg_type Msg_text
+test.c2 optimize note Table does not support optimize, doing recreate + analyze instead
+test.c2 optimize status OK
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+COMMIT;
+connection node_1b;
+UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2;
+COMMIT;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+connection node_1b;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+DROP TABLE c1, c2;
+DROP TABLE p1, p2;
+######################################################################
+# Test for OPTIMIZE
+######################################################################
+connection node_1;
+SET SESSION wsrep_sync_wait=0;
+CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
+CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
+INSERT INTO c1 VALUES (1,1);
+######################################################################
+#
+# Scenario #4: DML working on FK parent table tries to replicate, but
+# fails in certification for earlier DDL on child table
+# and another temporary table. TMP table should be skipped
+# but FK child table should be replicated with proper keys
+#
+######################################################################
+connection node_1;
+BEGIN;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+CREATE TEMPORARY TABLE tmp (i int);
+OPTIMIZE TABLE c1, tmp ;
+Table Op Msg_type Msg_text
+test.c1 optimize note Table does not support optimize, doing recreate + analyze instead
+test.c1 optimize status OK
+test.tmp optimize note Table does not support optimize, doing recreate + analyze instead
+test.tmp optimize status OK
+DROP TABLE tmp;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+COMMIT;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+DROP TABLE c1;
+DROP TABLE p1;
+######################################################################
+# Test for REPAIR
+######################################################################
+######################################################################
+#
+# Scenario #1: DML working on FK parent table BF aborted by DDL
+# over child table
+#
+######################################################################
+connection node_1;
+SET SESSION wsrep_sync_wait=0;
+CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
+CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p2 VALUES (1, 'INITIAL VALUE');
+INSERT INTO p2 VALUES (2, 'INITIAL VALUE');
+CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
+INSERT INTO c1 VALUES (1,1);
+CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk));
+INSERT INTO c2 VALUES (1,1,1), (2,1,2);
+connection node_1;
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+connection node_2;
+SET SESSION wsrep_sync_wait=0;
+REPAIR TABLE c1 ;
+Table Op Msg_type Msg_text
+test.c1 repair note The storage engine for the table doesn't support repair
+connection node_1;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+######################################################################
+#
+# Scenario #2: DML working on FK parent table tries to replicate, but
+# fails in certification for earlier DDL on child table
+#
+######################################################################
+connection node_1;
+BEGIN;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+REPAIR TABLE c1 ;
+Table Op Msg_type Msg_text
+test.c1 repair note The storage engine for the table doesn't support repair
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+COMMIT;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+######################################################################
+#
+# Scenario #3: 2 DMLs working on two FK parent tables try to replicate,
+# but fails in certification for earlier DDL on child table
+# which is child to both FK parents
+#
+######################################################################
+connection node_1;
+BEGIN;
+connection node_1b;
+BEGIN;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+REPAIR TABLE c2 ;
+Table Op Msg_type Msg_text
+test.c2 repair note The storage engine for the table doesn't support repair
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+COMMIT;
+connection node_1b;
+UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2;
+COMMIT;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+connection node_1b;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+DROP TABLE c1, c2;
+DROP TABLE p1, p2;
+######################################################################
+# Test for REPAIR
+######################################################################
+connection node_1;
+SET SESSION wsrep_sync_wait=0;
+CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
+CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
+INSERT INTO c1 VALUES (1,1);
+######################################################################
+#
+# Scenario #4: DML working on FK parent table tries to replicate, but
+# fails in certification for earlier DDL on child table
+# and another temporary table. TMP table should be skipped
+# but FK child table should be replicated with proper keys
+#
+######################################################################
+connection node_1;
+BEGIN;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+CREATE TEMPORARY TABLE tmp (i int);
+REPAIR TABLE c1, tmp ;
+Table Op Msg_type Msg_text
+test.c1 repair note The storage engine for the table doesn't support repair
+test.tmp repair note The storage engine for the table doesn't support repair
+DROP TABLE tmp;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+COMMIT;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+DROP TABLE c1;
+DROP TABLE p1;
+######################################################################
+# Test for ALTER ENGINE=INNODB
+######################################################################
+######################################################################
+#
+# Scenario #1: DML working on FK parent table BF aborted by DDL
+# over child table
+#
+######################################################################
+connection node_1;
+SET SESSION wsrep_sync_wait=0;
+CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
+CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p2 VALUES (1, 'INITIAL VALUE');
+INSERT INTO p2 VALUES (2, 'INITIAL VALUE');
+CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
+INSERT INTO c1 VALUES (1,1);
+CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk));
+INSERT INTO c2 VALUES (1,1,1), (2,1,2);
+connection node_1;
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+connection node_2;
+SET SESSION wsrep_sync_wait=0;
+ALTER TABLE c1 ENGINE=INNODB;
+connection node_1;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+######################################################################
+#
+# Scenario #2: DML working on FK parent table tries to replicate, but
+# fails in certification for earlier DDL on child table
+#
+######################################################################
+connection node_1;
+BEGIN;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+ALTER TABLE c1 ENGINE=INNODB;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+COMMIT;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+######################################################################
+#
+# Scenario #3: 2 DMLs working on two FK parent tables try to replicate,
+# but fails in certification for earlier DDL on child table
+# which is child to both FK parents
+#
+######################################################################
+connection node_1;
+BEGIN;
+connection node_1b;
+BEGIN;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+ALTER TABLE c2 ENGINE=INNODB;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+COMMIT;
+connection node_1b;
+UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2;
+COMMIT;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+connection node_1b;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+DROP TABLE c1, c2;
+DROP TABLE p1, p2;
+######################################################################
+# Test for TRUNCATE
+######################################################################
+######################################################################
+#
+# Scenario #1: DML working on FK parent table BF aborted by DDL
+# over child table
+#
+######################################################################
+connection node_1;
+SET SESSION wsrep_sync_wait=0;
+CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
+CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p2 VALUES (1, 'INITIAL VALUE');
+INSERT INTO p2 VALUES (2, 'INITIAL VALUE');
+CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
+INSERT INTO c1 VALUES (1,1);
+CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk));
+INSERT INTO c2 VALUES (1,1,1), (2,1,2);
+connection node_1;
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+connection node_2;
+SET SESSION wsrep_sync_wait=0;
+TRUNCATE TABLE c1 ;
+connection node_1;
+COMMIT;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+######################################################################
+#
+# Scenario #2: DML working on FK parent table tries to replicate, but
+# fails in certification for earlier DDL on child table
+#
+######################################################################
+connection node_1;
+BEGIN;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+TRUNCATE TABLE c1 ;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+COMMIT;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+######################################################################
+#
+# Scenario #3: 2 DMLs working on two FK parent tables try to replicate,
+# but fails in certification for earlier DDL on child table
+# which is child to both FK parents
+#
+######################################################################
+connection node_1;
+BEGIN;
+connection node_1b;
+BEGIN;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+TRUNCATE TABLE c2 ;
+connection node_1a;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+connection node_1;
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+COMMIT;
+connection node_1b;
+UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2;
+COMMIT;
+connection node_1a;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+connection node_1b;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SELECT 'I deadlocked';
+I deadlocked
+I deadlocked
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+connection node_2;
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+EXPECT_1
+1
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+EXPECT_2
+2
+DROP TABLE c1, c2;
+DROP TABLE p1, p2;
diff --git a/mysql-test/suite/galera/r/galera_trigger.result b/mysql-test/suite/galera/r/galera_trigger.result
index 40b63b327af..2a31a104404 100644
--- a/mysql-test/suite/galera/r/galera_trigger.result
+++ b/mysql-test/suite/galera/r/galera_trigger.result
@@ -45,34 +45,34 @@ connection node_2;
set session wsrep_sync_wait=15;
insert into t1(value) values (3);
insert into t1(value) values (4);
-select * from t2;
-id tbl action
-1 t1 INSERT
-3 t1 INSERT
-4 t1 INSERT
-6 t1 INSERT
+select tbl, action from t2;
+tbl action
+t1 INSERT
+t1 INSERT
+t1 INSERT
+t1 INSERT
connection node_1;
drop trigger if exists log_insert;
insert into t1(value) values (5);
-select * from t2;
-id tbl action
-1 t1 INSERT
-3 t1 INSERT
-4 t1 INSERT
-6 t1 INSERT
+select tbl, action from t2;
+tbl action
+t1 INSERT
+t1 INSERT
+t1 INSERT
+t1 INSERT
connection node_2;
insert into t1(value) values (6);
-select * from t2;
-id tbl action
-1 t1 INSERT
-3 t1 INSERT
-4 t1 INSERT
-6 t1 INSERT
+select tbl, action from t2;
+tbl action
+t1 INSERT
+t1 INSERT
+t1 INSERT
+t1 INSERT
connection node_1;
-select * from t2;
-id tbl action
-1 t1 INSERT
-3 t1 INSERT
-4 t1 INSERT
-6 t1 INSERT
+select tbl, action from t2;
+tbl action
+t1 INSERT
+t1 INSERT
+t1 INSERT
+t1 INSERT
drop table t1, t2;
diff --git a/mysql-test/suite/galera/t/MDEV-24063.test b/mysql-test/suite/galera/t/MDEV-24063.test
new file mode 100644
index 00000000000..24c5071cb15
--- /dev/null
+++ b/mysql-test/suite/galera/t/MDEV-24063.test
@@ -0,0 +1,20 @@
+#
+# MDEV-24063
+#
+# my_bool wsrep_thd_is_aborting(const THD*):
+# Assertion `((&(&thd->LOCK_thd_data)->m_mutex)->count > 0 &&
+# pthread_equal(pthread_self(), (&(&thd->LOCK_thd_data)->m_mutex)->thread))' failed.
+#
+
+--source include/galera_cluster.inc
+
+--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
+--connection node_2a
+CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
+
+--connection node_2
+SET GLOBAL wsrep_on=OFF;
+--source include/shutdown_mysqld.inc
+--source include/start_mysqld.inc
+
+DROP TABLE t1;
diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc
new file mode 100644
index 00000000000..06b7bbe41c4
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc
@@ -0,0 +1,192 @@
+#
+# Test for MDL BF-BF lock conflict
+# There are some DDL statements, which take extensive MDL lock for
+# a table referenced by foreign key constraint from the actual affetec table.
+# This extensive MDL lock may cause MDL BF-BF confclict situations, if the
+# FK parent table is not listed as certification key in the replication write set.
+# i.e. if replication allows such DDL to apply in parallel with regular DML operating
+# on the FK parent table.
+#
+# This test has two scenarios, where DML modifies FK parent table in node 1,
+# and offending DDL for FK child table is sent from node 2.
+#
+# param: $table_admin_command
+# DDL table command to test, script will build full SQL statement:
+# $table_admin_command TABLE c;
+#
+# param: $table_admin_command_end
+# Optional additional SQL syntax to end the SQL statement, if any
+# $table_admin_command TABLE c $table_admin_command_end;
+#
+# scenario 1, can be used to test if a DDL statement causes such MDL locking vulnerability.
+# call this test script with some table DDL command in $table_admin_command
+# if scenario 1 passes (especially COMMIT does fail for ER_LOCK_DEADLOCK),
+# then this particular DDL is vulnerable. scenraio 2 should fail for this DDL
+# unless code has not been fixed to append parent table certification keys for it.
+#
+
+--echo ######################################################################
+--echo # Test for $table_admin_command $table_admin_command_end
+--echo ######################################################################
+
+
+--echo ######################################################################
+--echo #
+--echo # Scenario #1: DML working on FK parent table BF aborted by DDL
+--echo # over child table
+--echo #
+--echo ######################################################################
+
+--connection node_1
+SET SESSION wsrep_sync_wait=0;
+
+CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
+
+
+CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p2 VALUES (1, 'INITIAL VALUE');
+INSERT INTO p2 VALUES (2, 'INITIAL VALUE');
+
+CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
+INSERT INTO c1 VALUES (1,1);
+
+CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk));
+INSERT INTO c2 VALUES (1,1,1), (2,1,2);
+
+--connection node_1
+SET AUTOCOMMIT=ON;
+START TRANSACTION;
+
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+
+--connection node_2
+SET SESSION wsrep_sync_wait=0;
+# wait for tables to be created in node 2 and all rows inserted as well
+--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/c%'
+--source include/wait_condition.inc
+--let $wait_condition = SELECT COUNT(*) = 2 FROM c2
+--source include/wait_condition.inc
+
+# replicate the DDL to be tested
+--eval $table_admin_command TABLE c1 $table_admin_command_end
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+COMMIT;
+
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+
+--connection node_2
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+
+--echo ######################################################################
+--echo #
+--echo # Scenario #2: DML working on FK parent table tries to replicate, but
+--echo # fails in certification for earlier DDL on child table
+--echo #
+--echo ######################################################################
+
+--connection node_1
+BEGIN;
+
+# Block the applier on node #1 and issue DDL on node 2
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+--eval $table_admin_command TABLE c1 $table_admin_command_end
+
+--connection node_1a
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+--let $expected_cert_failures = `SELECT VARIABLE_VALUE+1 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'`
+
+--connection node_1
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+--send COMMIT
+
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'
+--source include/wait_condition.inc
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+
+SELECT 'I deadlocked';
+
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+
+--connection node_2
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+
+
+--echo ######################################################################
+--echo #
+--echo # Scenario #3: 2 DMLs working on two FK parent tables try to replicate,
+--echo # but fails in certification for earlier DDL on child table
+--echo # which is child to both FK parents
+--echo #
+--echo ######################################################################
+
+--connection node_1
+BEGIN;
+
+--connection node_1b
+BEGIN;
+
+--connection node_1a
+# Block the applier on node #1 and issue DDL on node 2
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+--eval $table_admin_command TABLE c2 $table_admin_command_end
+
+--connection node_1a
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+--let $expected_cert_failures = `SELECT VARIABLE_VALUE+2 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'`
+
+--connection node_1
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+--send COMMIT
+
+--connection node_1b
+UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2;
+--send COMMIT
+
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'
+--source include/wait_condition.inc
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+SELECT 'I deadlocked';
+
+--connection node_1b
+--error ER_LOCK_DEADLOCK
+--reap
+SELECT 'I deadlocked';
+
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+
+--connection node_2
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
+
+DROP TABLE c1, c2;
+DROP TABLE p1, p2;
diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test
new file mode 100644
index 00000000000..88837933e5a
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test
@@ -0,0 +1,37 @@
+#
+# MDL BF-BF lock conflict
+#
+
+--source include/galera_cluster.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+--source include/galera_have_debug_sync.inc
+
+# sync point controlling session
+--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1a
+SET SESSION wsrep_sync_wait=0;
+
+# secondary conflicting DML victim session
+--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
+--connection node_1b
+SET SESSION wsrep_sync_wait=0;
+
+--let $table_admin_command = OPTIMIZE
+--source galera_ddl_fk_conflict.inc
+--source galera_ddl_fk_conflict_with_tmp.inc
+
+--let $table_admin_command = REPAIR
+--source galera_ddl_fk_conflict.inc
+--source galera_ddl_fk_conflict_with_tmp.inc
+
+--let $table_admin_command = ALTER
+--let $table_admin_command_end = ENGINE=INNODB
+--source galera_ddl_fk_conflict.inc
+
+--let $table_admin_command = TRUNCATE
+--let $table_admin_command_end =
+--source galera_ddl_fk_conflict.inc
+
+# CHECK and ANALYZE are not affected
+
diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict_with_tmp.inc b/mysql-test/suite/galera/t/galera_ddl_fk_conflict_with_tmp.inc
new file mode 100644
index 00000000000..acf3c54180b
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict_with_tmp.inc
@@ -0,0 +1,69 @@
+--echo ######################################################################
+--echo # Test for $table_admin_command $table_admin_command_end
+--echo ######################################################################
+
+
+--connection node_1
+SET SESSION wsrep_sync_wait=0;
+
+CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
+INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
+
+
+CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
+INSERT INTO c1 VALUES (1,1);
+
+--echo ######################################################################
+--echo #
+--echo # Scenario #4: DML working on FK parent table tries to replicate, but
+--echo # fails in certification for earlier DDL on child table
+--echo # and another temporary table. TMP table should be skipped
+--echo # but FK child table should be replicated with proper keys
+--echo #
+--echo ######################################################################
+
+--connection node_1
+BEGIN;
+
+# Block the applier on node #1 and issue DDL on node 2
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+# wait for tables to be created in node 2 and all rows inserted as well
+--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/c1'
+--source include/wait_condition.inc
+--let $wait_condition = SELECT COUNT(*) = 1 FROM c1
+--source include/wait_condition.inc
+CREATE TEMPORARY TABLE tmp (i int);
+--eval $table_admin_command TABLE c1, tmp $table_admin_command_end
+DROP TABLE tmp;
+
+--connection node_1a
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+--let $expected_cert_failures = `SELECT VARIABLE_VALUE+1 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'`
+
+--connection node_1
+UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
+--send COMMIT
+
+--connection node_1a
+--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'
+--source include/wait_condition.inc
+
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+
+SELECT 'I deadlocked';
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+
+--connection node_2
+SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
+
+DROP TABLE c1;
+DROP TABLE p1;
diff --git a/mysql-test/suite/galera/t/galera_trigger.test b/mysql-test/suite/galera/t/galera_trigger.test
index f85a75d0ff1..3c66b941e32 100644
--- a/mysql-test/suite/galera/t/galera_trigger.test
+++ b/mysql-test/suite/galera/t/galera_trigger.test
@@ -55,18 +55,18 @@ insert into t1(value) values (2);
set session wsrep_sync_wait=15;
insert into t1(value) values (3);
insert into t1(value) values (4);
-select * from t2;
+select tbl, action from t2;
--connection node_1
drop trigger if exists log_insert;
insert into t1(value) values (5);
-select * from t2;
+select tbl, action from t2;
--connection node_2
insert into t1(value) values (6);
-select * from t2;
+select tbl, action from t2;
--connection node_1
-select * from t2;
+select tbl, action from t2;
drop table t1, t2;
diff --git a/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt b/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt
deleted file mode 100644
index beae84b3862..00000000000
--- a/mysql-test/suite/galera/t/mysql-wsrep#198-master.opt
+++ /dev/null
@@ -1 +0,0 @@
---log-bin
diff --git a/mysql-test/suite/galera/t/mysql-wsrep#198.cnf b/mysql-test/suite/galera/t/mysql-wsrep#198.cnf
new file mode 100644
index 00000000000..d599f3940e4
--- /dev/null
+++ b/mysql-test/suite/galera/t/mysql-wsrep#198.cnf
@@ -0,0 +1,9 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+log-bin
+wsrep-debug=1
+
+[mysqld.1]
+log-bin
+wsrep-debug=1
diff --git a/mysql-test/suite/galera/t/mysql-wsrep#198.test b/mysql-test/suite/galera/t/mysql-wsrep#198.test
index a80d030a8b0..a8190f2ae61 100644
--- a/mysql-test/suite/galera/t/mysql-wsrep#198.test
+++ b/mysql-test/suite/galera/t/mysql-wsrep#198.test
@@ -1,5 +1,6 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
+--source include/force_restart.inc
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
diff --git a/mysql-test/suite/maria/repair.result b/mysql-test/suite/maria/repair.result
index 6bb9e1b5b9e..296f251aa36 100644
--- a/mysql-test/suite/maria/repair.result
+++ b/mysql-test/suite/maria/repair.result
@@ -22,3 +22,19 @@ i
1
UNLOCK TABLES;
DROP TABLE t1;
+#
+# MDEV-23824 SIGSEGV in end_io_cache on REPAIR LOCAL TABLE for Aria table
+#
+CREATE TABLE t1 (i INT) ENGINE=Aria;
+INSERT INTO t1 VALUES (1);
+SET max_session_mem_used=50000;
+REPAIR LOCAL TABLE t1 USE_FRM;
+Table Op Msg_type Msg_text
+t1 repair error Failed to open partially repaired table
+Warnings:
+Error 1290 The MariaDB server is running with the --max-thread-mem-used=50000 option so it cannot execute this statement
+REPAIR LOCAL TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 repair Error The MariaDB server is running with the --max-thread-mem-used=50000 option so it cannot execute this statement
+test.t1 repair error Corrupt
+DROP TABLE t1;
diff --git a/mysql-test/suite/maria/repair.test b/mysql-test/suite/maria/repair.test
index 2f713950d3e..9603a949f9b 100644
--- a/mysql-test/suite/maria/repair.test
+++ b/mysql-test/suite/maria/repair.test
@@ -22,3 +22,14 @@ SELECT * FROM INFORMATION_SCHEMA.TABLES;
SELECT * FROM t1;
UNLOCK TABLES;
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-23824 SIGSEGV in end_io_cache on REPAIR LOCAL TABLE for Aria table
+--echo #
+
+CREATE TABLE t1 (i INT) ENGINE=Aria;
+INSERT INTO t1 VALUES (1);
+SET max_session_mem_used=50000;
+REPAIR LOCAL TABLE t1 USE_FRM;
+REPAIR LOCAL TABLE t1;
+DROP TABLE t1;
diff --git a/mysql-test/suite/perfschema/r/sxlock_func.result b/mysql-test/suite/perfschema/r/sxlock_func.result
index ad544f78a28..b51234feda6 100644
--- a/mysql-test/suite/perfschema/r/sxlock_func.result
+++ b/mysql-test/suite/perfschema/r/sxlock_func.result
@@ -16,7 +16,6 @@ wait/synch/sxlock/innodb/dict_operation_lock
wait/synch/sxlock/innodb/fil_space_latch
wait/synch/sxlock/innodb/fts_cache_init_rw_lock
wait/synch/sxlock/innodb/fts_cache_rw_lock
-wait/synch/sxlock/innodb/index_online_log
wait/synch/sxlock/innodb/index_tree_rw_lock
wait/synch/sxlock/innodb/trx_i_s_cache_lock
wait/synch/sxlock/innodb/trx_purge_latch
diff --git a/mysql-test/suite/period/r/create.result b/mysql-test/suite/period/r/create.result
index b454661afc9..69d7e918804 100644
--- a/mysql-test/suite/period/r/create.result
+++ b/mysql-test/suite/period/r/create.result
@@ -45,6 +45,10 @@ ERROR 42000: Incorrect column specifier for column 's'
create or replace table t (id int primary key, s date, e date,
period for mytime(s,x));
ERROR 42S22: Unknown column 'x' in 'mytime'
+# MDEV-18842: Unfortunate error message when the same column is used
+# for application period start and end
+create or replace table t (s date, t date, period for apt(s,s));
+ERROR 42000: Column 's' specified twice
create or replace table t (id int primary key, s date, e date,
period for mytime(s,e),
period for mytime2(s,e));
diff --git a/mysql-test/suite/period/t/create.test b/mysql-test/suite/period/t/create.test
index 2e3de795698..49dcc6ad3c7 100644
--- a/mysql-test/suite/period/t/create.test
+++ b/mysql-test/suite/period/t/create.test
@@ -31,6 +31,12 @@ create or replace table t (id int primary key, s time, e time,
--error ER_BAD_FIELD_ERROR
create or replace table t (id int primary key, s date, e date,
period for mytime(s,x));
+
+--echo # MDEV-18842: Unfortunate error message when the same column is used
+--echo # for application period start and end
+--error ER_FIELD_SPECIFIED_TWICE
+create or replace table t (s date, t date, period for apt(s,s));
+
--error ER_MORE_THAN_ONE_PERIOD
create or replace table t (id int primary key, s date, e date,
period for mytime(s,e),
diff --git a/mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result b/mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result
index 74648501fbe..9c36973427a 100644
--- a/mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result
+++ b/mysql-test/suite/rpl/r/rpl_gtid_delete_domain.result
@@ -22,7 +22,7 @@ START SLAVE IO_THREAD;
include/wait_for_slave_io_error.inc [errno=1236]
connection master;
FLUSH BINARY LOGS;
-PURGE BINARY LOGS TO 'master-bin.000002';;
+include/wait_for_purge.inc "master-bin.000002"
FLUSH BINARY LOGS DELETE_DOMAIN_ID=(11);
SELECT @@global.gtid_binlog_pos, @@global.gtid_binlog_state;
@@global.gtid_binlog_pos @@global.gtid_binlog_state
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test b/mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test
index 0262998798a..5537b6fbf86 100644
--- a/mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test
+++ b/mysql-test/suite/rpl/t/rpl_gtid_delete_domain.test
@@ -53,17 +53,11 @@ START SLAVE IO_THREAD;
# adjust the master binlog state
FLUSH BINARY LOGS;
--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
---eval PURGE BINARY LOGS TO '$purge_to_binlog';
+--let $purge_binlogs_to=$purge_to_binlog
+--source include/wait_for_purge.inc
+
# with final removal of the extra domain
-###adding to debug info to catch the failure (1076):
---error 0,1076
--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID=($extra_domain_id)
-
-if ($mysql_errno == 1076) {
- --echo ### Failure "Could not delete gtid domain"
- --source include/show_rpl_debug_info.inc
- }
-
SELECT @@global.gtid_binlog_pos, @@global.gtid_binlog_state;
--connection slave
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index c284e75a248..85c9363081c 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -449,7 +449,8 @@ mysqld_ld_preload_text() {
set_malloc_lib() {
malloc_lib="$1"
if expr "$malloc_lib" : "\(tcmalloc\|jemalloc\)" > /dev/null ; then
- if ! my_which ldconfig > /dev/null 2>&1
+ export PATH=$PATH:/sbin
+ if ! command -v ldconfig > /dev/null 2>&1
then
log_error "ldconfig command not found, required for ldconfig -p"
exit 1
diff --git a/sql/log.h b/sql/log.h
index 58e681985eb..eaf7cde1c07 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -728,7 +728,7 @@ public:
{
bytes_written = 0;
}
- void harvest_bytes_written(ulonglong* counter)
+ void harvest_bytes_written(Atomic_counter<uint64> *counter)
{
#ifndef DBUG_OFF
char buf1[22],buf2[22];
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index 941616a26d5..b7127d86fcd 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -461,7 +461,7 @@ static inline int add_relay_log(Relay_log_info* rli,LOG_INFO* linfo)
DBUG_RETURN(1);
}
rli->log_space_total += s.st_size;
- DBUG_PRINT("info",("log_space_total: %llu", rli->log_space_total));
+ DBUG_PRINT("info",("log_space_total: %llu", uint64(rli->log_space_total)));
DBUG_RETURN(0);
}
@@ -1254,7 +1254,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
mysql_mutex_unlock(rli->relay_log.get_log_lock());
}
err:
- DBUG_PRINT("info",("log_space_total: %llu",rli->log_space_total));
+ DBUG_PRINT("info",("log_space_total: %llu", uint64(rli->log_space_total)));
mysql_mutex_unlock(&rli->data_lock);
DBUG_RETURN(error);
}
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index 4223e015ecd..e3b59aa615c 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -240,7 +240,8 @@ public:
threads, the SQL thread sets it to unblock the I/O thread and make it
temporarily forget about the constraint.
*/
- ulonglong log_space_limit,log_space_total;
+ ulonglong log_space_limit;
+ Atomic_counter<uint64> log_space_total;
bool ignore_log_space_limit;
/*
diff --git a/sql/slave.cc b/sql/slave.cc
index c302ba1de64..cfefe5746d4 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2819,7 +2819,7 @@ static bool wait_for_relay_log_space(Relay_log_info* rli)
DBUG_PRINT("info", ("log_space_limit=%llu log_space_total=%llu "
"ignore_log_space_limit=%d "
"sql_force_rotate_relay=%d",
- rli->log_space_limit, rli->log_space_total,
+ rli->log_space_limit, uint64(rli->log_space_total),
(int) rli->ignore_log_space_limit,
(int) rli->sql_force_rotate_relay));
}
@@ -5085,7 +5085,7 @@ Stopping slave I/O thread due to out-of-memory error from master");
{
DBUG_PRINT("info", ("log_space_limit=%llu log_space_total=%llu "
"ignore_log_space_limit=%d",
- rli->log_space_limit, rli->log_space_total,
+ rli->log_space_limit, uint64(rli->log_space_total),
(int) rli->ignore_log_space_limit));
}
#endif
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index ef96e8f2484..483be6e39d6 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -9087,6 +9087,9 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
append_identifier(thd, &result, username, strlen(username));
add_user_parameters(thd, &result, acl_user, false);
+ if (acl_user->account_locked)
+ result.append(STRING_WITH_LEN(" ACCOUNT LOCK"));
+
if (acl_user->password_expired)
result.append(STRING_WITH_LEN(" PASSWORD EXPIRE"));
else if (!acl_user->password_lifetime)
@@ -9098,9 +9101,6 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
result.append(STRING_WITH_LEN(" DAY"));
}
- if (acl_user->account_locked)
- result.append(STRING_WITH_LEN(" ACCOUNT LOCK"));
-
protocol->prepare_for_resend();
protocol->store(result.ptr(), result.length(), result.charset());
if (protocol->write())
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index dc9b971f2ed..2d6f891f56f 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2010, 2015, Oracle and/or its affiliates.
- Copyright (c) 2011, 2019, MariaDB
+ Copyright (c) 2011, 2020, 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
@@ -31,7 +31,7 @@
#include "strfunc.h"
#include "sql_admin.h"
#include "sql_statistics.h"
-
+#include "wsrep_mysqld.h"
/* Prepare, run and cleanup for mysql_recreate_table() */
static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
@@ -90,10 +90,10 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table,
static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
HA_CHECK_OPT *check_opt)
{
- int error= 0;
+ int error= 0, create_error= 0;
TABLE tmp_table, *table;
TABLE_LIST *pos_in_locked_tables= 0;
- TABLE_SHARE *share;
+ TABLE_SHARE *share= 0;
bool has_mdl_lock= FALSE;
char from[FN_REFLEN],tmp[FN_REFLEN+32];
const char **ext;
@@ -206,6 +206,17 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
HA_EXTRA_NOT_USED, NULL);
table_list->table= 0;
}
+ else
+ {
+ /*
+ Table open failed, maybe because we run out of memory.
+ Close all open tables and relaese all MDL locks
+ */
+ tdc_release_share(share);
+ share->tdc->flush(thd, true);
+ share= 0;
+ }
+
/*
After this point we have an exclusive metadata lock on our table
in both cases when table was successfully open in mysql_admin_table()
@@ -219,11 +230,8 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
goto end;
}
if (dd_recreate_table(thd, table_list->db.str, table_list->table_name.str))
- {
- error= send_check_errmsg(thd, table_list, "repair",
- "Failed generating table from .frm file");
- goto end;
- }
+ create_error= send_check_errmsg(thd, table_list, "repair",
+ "Failed generating table from .frm file");
/*
'FALSE' for 'using_transactions' means don't postpone
invalidation till the end of a transaction, but do it
@@ -236,6 +244,8 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
"Failed restoring .MYD file");
goto end;
}
+ if (create_error)
+ goto end;
if (thd->locked_tables_list.locked_tables())
{
@@ -263,7 +273,8 @@ end:
if (table == &tmp_table)
{
closefrm(table);
- tdc_release_share(table->s);
+ if (share)
+ tdc_release_share(share);
}
/* In case of a temporary table there will be no metadata lock. */
if (unlikely(error) && has_mdl_lock)
@@ -418,6 +429,50 @@ dbug_err:
return open_error;
}
+#ifdef WITH_WSREP
+ /*
+ OPTIMIZE, REPAIR and ALTER may take MDL locks not only for the affected table, but
+ also for the table referenced by foreign key constraint.
+ This wsrep_toi_replication() function handles TOI replication for OPTIMIZE and REPAIR
+ so that certification keys for potential FK parent tables are also appended in the
+ write set.
+ ALTER TABLE case is handled elsewhere.
+ */
+static bool wsrep_toi_replication(THD *thd, TABLE_LIST *tables)
+{
+ if (!WSREP(thd) || !WSREP_CLIENT(thd)) return false;
+
+ LEX *lex= thd->lex;
+ /* only handle OPTIMIZE and REPAIR here */
+ switch (lex->sql_command)
+ {
+ case SQLCOM_OPTIMIZE:
+ case SQLCOM_REPAIR:
+ break;
+ default:
+ return false;
+ }
+
+ close_thread_tables(thd);
+ wsrep::key_array keys;
+
+ wsrep_append_fk_parent_table(thd, tables, &keys);
+
+ /* now TOI replication, with no locks held */
+ if (keys.empty())
+ {
+ WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, tables);
+ } else {
+ WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, tables, &keys) {
+ return true;
+ }
+ }
+ return false;
+
+ wsrep_error_label:
+ return true;
+}
+#endif /* WITH_WSREP */
/*
RETURN VALUES
@@ -486,6 +541,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
close_thread_tables(thd);
for (table= tables; table; table= table->next_local)
table->table= NULL;
+#ifdef WITH_WSREP
+ if (wsrep_toi_replication(thd, tables))
+ {
+ WSREP_INFO("wsrep TOI replication of has failed, skipping OPTIMIZE");
+ goto err;
+ }
+#endif /* WITH_WSREP */
for (table= tables; table; table= table->next_local)
{
@@ -592,6 +654,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
#endif
DBUG_PRINT("admin", ("table: %p", table->table));
+ if (table->schema_table)
+ {
+ result_code= HA_ADMIN_NOT_IMPLEMENTED;
+ goto send_result;
+ }
+
if (prepare_func)
{
DBUG_PRINT("admin", ("calling prepare_func"));
@@ -650,12 +718,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
goto send_result;
}
- if (table->schema_table)
- {
- result_code= HA_ADMIN_NOT_IMPLEMENTED;
- goto send_result;
- }
-
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
/* purecov: begin inspected */
@@ -1338,10 +1400,10 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
-error:
#ifdef WITH_WSREP
-wsrep_error_label:
-#endif
+ wsrep_error_label:
+#endif /* WITH_WSREP */
+error:
DBUG_RETURN(res);
}
@@ -1380,7 +1442,6 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
- WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
res= (specialflag & SPECIAL_NO_NEW_FUNC) ?
mysql_recreate_table(thd, first_table, true) :
@@ -1399,9 +1460,6 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
m_lex->query_tables= first_table;
error:
-#ifdef WITH_WSREP
-wsrep_error_label:
-#endif
DBUG_RETURN(res);
}
@@ -1416,7 +1474,6 @@ bool Sql_cmd_repair_table::execute(THD *thd)
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
- WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "repair",
TL_WRITE, 1,
MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM),
@@ -1435,8 +1492,5 @@ bool Sql_cmd_repair_table::execute(THD *thd)
m_lex->query_tables= first_table;
error:
-#ifdef WITH_WSREP
-wsrep_error_label:
-#endif
DBUG_RETURN(res);
}
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index ede30263e48..0184f6beaf4 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -490,6 +490,25 @@ bool Sql_cmd_alter_table::execute(THD *thd)
if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
DBUG_RETURN(TRUE); /* purecov: inspected */
+#ifdef WITH_WSREP
+ if (WSREP(thd) && WSREP_CLIENT(thd) &&
+ (!thd->is_current_stmt_binlog_format_row() ||
+ !thd->find_temporary_table(first_table)))
+ {
+ wsrep::key_array keys;
+ wsrep_append_fk_parent_table(thd, first_table, &keys);
+
+ WSREP_TO_ISOLATION_BEGIN_ALTER(lex->name.str ? select_lex->db.str
+ : first_table->db.str,
+ lex->name.str ? lex->name.str
+ : first_table->table_name.str,
+ first_table, &alter_info, &keys,
+ used_engine ? &create_info : nullptr);
+
+ thd->variables.auto_increment_offset = 1;
+ thd->variables.auto_increment_increment = 1;
+ }
+#endif
if (lex->name.str && !test_all_bits(priv, INSERT_ACL | CREATE_ACL))
{
@@ -517,20 +536,6 @@ bool Sql_cmd_alter_table::execute(THD *thd)
thd->work_part_info= 0;
#endif
-#ifdef WITH_WSREP
- if (WSREP(thd) &&
- (!thd->is_current_stmt_binlog_format_row() ||
- !thd->find_temporary_table(first_table)))
- {
- WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : first_table->db.str),
- (lex->name.str ? lex->name.str : first_table->table_name.str),
- first_table, &alter_info, used_engine ? &create_info : NULL);
-
- thd->variables.auto_increment_offset = 1;
- thd->variables.auto_increment_increment = 1;
- }
-#endif
-
result= mysql_alter_table(thd, &select_lex->db, &lex->name,
&create_info,
first_table,
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 87773b8338a..e3e3b18472b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3448,7 +3448,7 @@ public:
void awake_no_mutex(killed_state state_to_set);
void awake(killed_state state_to_set)
{
- bool wsrep_on_local= WSREP_NNULL(this);
+ bool wsrep_on_local= variables.wsrep_on;
/*
mutex locking order (LOCK_thd_data - LOCK_thd_kill)) requires
to grab LOCK_thd_data here
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 3e59ad3afc9..861eb614592 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -4469,6 +4469,12 @@ public:
int add_period(Lex_ident name, Lex_ident_sys_st start, Lex_ident_sys_st end)
{
+ if (lex_string_cmp(system_charset_info, &start, &end) == 0)
+ {
+ my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), start.str);
+ return 1;
+ }
+
Table_period_info &info= create_info.period_info;
if (check_exists && info.name.streq(name))
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 8ed996c0a8d..5e89c4d19ee 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -427,9 +427,23 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
bool hton_can_recreate;
#ifdef WITH_WSREP
- if (WSREP(thd) &&
- wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, NULL))
- DBUG_RETURN(TRUE);
+ if (WSREP(thd))
+ {
+ wsrep::key_array keys;
+ wsrep_append_fk_parent_table(thd, table_ref, &keys);
+ if (keys.empty())
+ {
+ WSREP_TO_ISOLATION_BEGIN_IF(table_ref->db.str, table_ref->table_name.str, NULL)
+ {
+ DBUG_RETURN(TRUE);
+ }
+ } else {
+ WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, table_ref, &keys)
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
#endif /* WITH_WSREP */
if (lock_table(thd, table_ref, &hton_can_recreate))
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 1b37896f18b..607a68caf43 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2501,7 +2501,7 @@ create:
Lex->pop_select(); //main select
}
| create_or_replace USER_SYM opt_if_not_exists clear_privileges
- grant_list opt_require_clause opt_resource_options opt_account_locking opt_password_expiration
+ grant_list opt_require_clause opt_resource_options opt_account_locking_and_opt_password_expiration
{
if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER,
$1 | $3)))
@@ -7312,7 +7312,7 @@ alter:
} OPTIONS_SYM '(' server_options_list ')' { }
/* ALTER USER foo is allowed for MySQL compatibility. */
| ALTER USER_SYM opt_if_exists clear_privileges grant_list
- opt_require_clause opt_resource_options opt_account_locking opt_password_expiration
+ opt_require_clause opt_resource_options opt_account_locking_and_opt_password_expiration
{
Lex->create_info.set($3);
Lex->sql_command= SQLCOM_ALTER_USER;
@@ -7348,39 +7348,46 @@ alter:
} stmt_end {}
;
-opt_account_locking:
- /* Nothing */ {}
- | ACCOUNT_SYM LOCK_SYM
+account_locking_option:
+ LOCK_SYM
{
Lex->account_options.account_locked= ACCOUNTLOCK_LOCKED;
}
- | ACCOUNT_SYM UNLOCK_SYM
+ | UNLOCK_SYM
{
Lex->account_options.account_locked= ACCOUNTLOCK_UNLOCKED;
}
;
-opt_password_expiration:
- /* Nothing */ {}
- | PASSWORD_SYM EXPIRE_SYM
+
+opt_password_expire_option:
+ /* empty */
{
Lex->account_options.password_expire= PASSWORD_EXPIRE_NOW;
}
- | PASSWORD_SYM EXPIRE_SYM NEVER_SYM
+ | NEVER_SYM
{
Lex->account_options.password_expire= PASSWORD_EXPIRE_NEVER;
}
- | PASSWORD_SYM EXPIRE_SYM DEFAULT
+ | DEFAULT
{
Lex->account_options.password_expire= PASSWORD_EXPIRE_DEFAULT;
}
- | PASSWORD_SYM EXPIRE_SYM INTERVAL_SYM NUM DAY_SYM
+ | INTERVAL_SYM NUM DAY_SYM
{
Lex->account_options.password_expire= PASSWORD_EXPIRE_INTERVAL;
- if (!(Lex->account_options.num_expiration_days= atoi($4.str)))
- my_yyabort_error((ER_WRONG_VALUE, MYF(0), "DAY", $4.str));
+ if (!(Lex->account_options.num_expiration_days= atoi($2.str)))
+ my_yyabort_error((ER_WRONG_VALUE, MYF(0), "DAY", $2.str));
}
;
+opt_account_locking_and_opt_password_expiration:
+ /* empty */
+ | ACCOUNT_SYM account_locking_option
+ | PASSWORD_SYM EXPIRE_SYM opt_password_expire_option
+ | ACCOUNT_SYM account_locking_option PASSWORD_SYM EXPIRE_SYM opt_password_expire_option
+ | PASSWORD_SYM EXPIRE_SYM opt_password_expire_option ACCOUNT_SYM account_locking_option
+ ;
+
ev_alter_on_schedule_completion:
/* empty */ { $$= 0;}
| ON SCHEDULE_SYM ev_schedule_time { $$= 1; }
diff --git a/sql/wsrep_client_service.cc b/sql/wsrep_client_service.cc
index b9c59623e6c..c01c256e872 100644
--- a/sql/wsrep_client_service.cc
+++ b/sql/wsrep_client_service.cc
@@ -245,6 +245,16 @@ void Wsrep_client_service::will_replay()
mysql_mutex_unlock(&LOCK_wsrep_replaying);
}
+void Wsrep_client_service::signal_replayed()
+{
+ DBUG_ASSERT(m_thd == current_thd);
+ mysql_mutex_lock(&LOCK_wsrep_replaying);
+ --wsrep_replaying;
+ DBUG_ASSERT(wsrep_replaying >= 0);
+ mysql_cond_broadcast(&COND_wsrep_replaying);
+ mysql_mutex_unlock(&LOCK_wsrep_replaying);
+}
+
enum wsrep::provider::status Wsrep_client_service::replay()
{
@@ -273,14 +283,15 @@ enum wsrep::provider::status Wsrep_client_service::replay()
}
delete replayer_thd;
-
- mysql_mutex_lock(&LOCK_wsrep_replaying);
- --wsrep_replaying;
- mysql_cond_broadcast(&COND_wsrep_replaying);
- mysql_mutex_unlock(&LOCK_wsrep_replaying);
DBUG_RETURN(ret);
}
+enum wsrep::provider::status Wsrep_client_service::replay_unordered()
+{
+ DBUG_ASSERT(0);
+ return wsrep::provider::error_not_implemented;
+}
+
void Wsrep_client_service::wait_for_replayers(wsrep::unique_lock<wsrep::mutex>& lock)
{
DBUG_ASSERT(m_thd == current_thd);
@@ -300,6 +311,12 @@ void Wsrep_client_service::wait_for_replayers(wsrep::unique_lock<wsrep::mutex>&
lock.lock();
}
+enum wsrep::provider::status Wsrep_client_service::commit_by_xid()
+{
+ DBUG_ASSERT(0);
+ return wsrep::provider::error_not_implemented;
+}
+
void Wsrep_client_service::debug_sync(const char* sync_point)
{
DBUG_ASSERT(m_thd == current_thd);
diff --git a/sql/wsrep_client_service.h b/sql/wsrep_client_service.h
index aa58d99c3cf..253d2f43ac3 100644
--- a/sql/wsrep_client_service.h
+++ b/sql/wsrep_client_service.h
@@ -48,8 +48,19 @@ public:
void emergency_shutdown()
{ throw wsrep::not_implemented_error(); }
void will_replay();
+ void signal_replayed();
enum wsrep::provider::status replay();
+ enum wsrep::provider::status replay_unordered();
void wait_for_replayers(wsrep::unique_lock<wsrep::mutex>&);
+ enum wsrep::provider::status commit_by_xid();
+ bool is_explicit_xa()
+ {
+ return false;
+ }
+ bool is_xa_rollback()
+ {
+ return false;
+ }
void debug_sync(const char*);
void debug_crash(const char*);
int bf_rollback();
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index a6b0991e82b..1dfeb782bbe 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1261,6 +1261,51 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr)
key_arr->keys_len= 0;
}
+void
+wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* keys)
+{
+ if (!WSREP(thd) || !WSREP_CLIENT(thd)) return;
+ TABLE_LIST *table;
+
+ thd->mdl_context.release_transactional_locks();
+ uint counter;
+ MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
+
+ if (thd->open_temporary_tables(tables) ||
+ open_tables(thd, &tables, &counter, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL))
+ {
+ WSREP_DEBUG("unable to open table for FK checks for %s", thd->query());
+ }
+
+ for (table= tables; table; table= table->next_local)
+ {
+ if (!is_temporary_table(table) && table->table)
+ {
+ FOREIGN_KEY_INFO *f_key_info;
+ List<FOREIGN_KEY_INFO> f_key_list;
+
+ table->table->file->get_foreign_key_list(thd, &f_key_list);
+ List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
+ while ((f_key_info=it++))
+ {
+ WSREP_DEBUG("appended fkey %s", f_key_info->referenced_table->str);
+ keys->push_back(wsrep_prepare_key_for_toi(f_key_info->referenced_db->str,
+ f_key_info->referenced_table->str,
+ wsrep::key::shared));
+ }
+ }
+ }
+
+ /* close the table and release MDL locks */
+ close_thread_tables(thd);
+ thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
+ for (table= tables; table; table= table->next_local)
+ {
+ table->table= NULL;
+ table->mdl_request.ticket= NULL;
+ }
+}
+
/*!
* @param db Database string
* @param table Table string
@@ -1511,10 +1556,11 @@ wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
return ret;
}
-wsrep::key_array wsrep_prepare_keys_for_toi(const char* db,
- const char* table,
- const TABLE_LIST* table_list,
- const Alter_info* alter_info)
+wsrep::key_array wsrep_prepare_keys_for_toi(const char *db,
+ const char *table,
+ const TABLE_LIST *table_list,
+ const Alter_info *alter_info,
+ const wsrep::key_array *fk_tables)
{
wsrep::key_array ret;
if (db || table)
@@ -1534,8 +1580,13 @@ wsrep::key_array wsrep_prepare_keys_for_toi(const char* db,
ret.insert(ret.end(), fk.begin(), fk.end());
}
}
+ if (fk_tables && !fk_tables->empty())
+ {
+ ret.insert(ret.end(), fk_tables->begin(), fk_tables->end());
+ }
return ret;
}
+
/*
* Construct Query_log_Event from thd query and serialize it
* into buffer.
@@ -2069,9 +2120,10 @@ fail:
-1: TOI replication failed
*/
static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
- const TABLE_LIST* table_list,
- const Alter_info* alter_info,
- const HA_CREATE_INFO* create_info)
+ const TABLE_LIST *table_list,
+ const Alter_info *alter_info,
+ const wsrep::key_array *fk_tables,
+ const HA_CREATE_INFO *create_info)
{
DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_TOI);
@@ -2102,7 +2154,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
struct wsrep_buf buff= { buf, buf_len };
wsrep::key_array key_array=
- wsrep_prepare_keys_for_toi(db, table, table_list, alter_info);
+ wsrep_prepare_keys_for_toi(db, table, table_list, alter_info, fk_tables);
if (thd->has_read_only_protection())
{
@@ -2250,8 +2302,9 @@ static void wsrep_RSU_end(THD *thd)
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list,
- const Alter_info* alter_info,
- const HA_CREATE_INFO* create_info)
+ const Alter_info *alter_info,
+ const wsrep::key_array *fk_tables,
+ const HA_CREATE_INFO *create_info)
{
/*
No isolation for applier or replaying threads.
@@ -2305,7 +2358,8 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
{
switch (wsrep_OSU_method_get(thd)) {
case WSREP_OSU_TOI:
- ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info, create_info);
+ ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info, fk_tables,
+ create_info);
break;
case WSREP_OSU_RSU:
ret= wsrep_RSU_begin(thd, db_, table_);
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 4461d73a928..eb32636d67f 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -215,6 +215,7 @@ wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout);
extern void wsrep_last_committed_id (wsrep_gtid_t* gtid);
extern int wsrep_check_opts();
extern void wsrep_prepend_PATH (const char* path);
+void wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* table, wsrep::key_array* keys);
/* Other global variables */
extern wsrep_seqno_t wsrep_locked_seqno;
@@ -362,8 +363,9 @@ struct HA_CREATE_INFO;
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list,
- const Alter_info* alter_info= NULL,
- const HA_CREATE_INFO* create_info= NULL);
+ const Alter_info* alter_info= nullptr,
+ const wsrep::key_array *fk_tables= nullptr,
+ const HA_CREATE_INFO* create_info= nullptr);
bool wsrep_should_replicate_ddl(THD* thd, const enum legacy_db_type db_type);
bool wsrep_should_replicate_ddl_iterate(THD* thd, const TABLE_LIST* table_list);
@@ -607,6 +609,9 @@ void wsrep_deinit_server();
*/
enum wsrep::streaming_context::fragment_unit wsrep_fragment_unit(ulong unit);
+wsrep::key wsrep_prepare_key_for_toi(const char* db, const char* table,
+ enum wsrep::key::type type);
+
#else /* !WITH_WSREP */
/* These macros are needed to compile MariaDB without WSREP support
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 9a180614afd..3bbc499bab5 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -3483,7 +3483,7 @@ re_evict:
if (fix_block->page.ibuf_exist) {
fix_block->page.ibuf_exist = false;
ibuf_merge_or_delete_for_page(fix_block, page_id,
- zip_size, true);
+ zip_size);
}
if (rw_latch == RW_X_LATCH) {
@@ -3550,7 +3550,7 @@ buf_page_get_gen(
{
rw_lock_x_lock_inline(&block->lock, 0, file, line);
block->page.ibuf_exist= false;
- ibuf_merge_or_delete_for_page(block, page_id, block->zip_size(), true);
+ ibuf_merge_or_delete_for_page(block, page_id, block->zip_size());
if (rw_latch == RW_X_LATCH)
{
@@ -3823,7 +3823,7 @@ loop:
if (block->page.ibuf_exist)
{
if (!recv_recovery_is_on())
- ibuf_merge_or_delete_for_page(nullptr, page_id, zip_size, true);
+ ibuf_merge_or_delete_for_page(nullptr, page_id, zip_size);
block->page.ibuf_exist= false;
}
@@ -3885,7 +3885,7 @@ loop:
/* Delete possible entries for the page from the insert buffer:
such can exist if the page belonged to an index which was dropped */
if (!recv_recovery_is_on())
- ibuf_merge_or_delete_for_page(nullptr, page_id, zip_size, true);
+ ibuf_merge_or_delete_for_page(nullptr, page_id, zip_size);
static_assert(FIL_PAGE_PREV + 4 == FIL_PAGE_NEXT, "adjacent");
memset_aligned<8>(block->frame + FIL_PAGE_PREV, 0xff, 8);
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index ca4081e90e9..168636cc965 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -5268,87 +5268,3 @@ dict_tf_to_row_format_string(
ut_error;
return(0);
}
-
-/** Look for any dictionary objects that are found in the given tablespace.
-@param[in] space_id Tablespace ID to search for.
-@return true if tablespace is empty. */
-bool
-dict_space_is_empty(
- ulint space_id)
-{
- btr_pcur_t pcur;
- const rec_t* rec;
- mtr_t mtr;
- bool found = false;
-
- dict_sys_lock();
- mtr_start(&mtr);
-
- for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
- rec != NULL;
- rec = dict_getnext_system(&pcur, &mtr)) {
- const byte* field;
- ulint len;
- ulint space_id_for_table;
-
- field = rec_get_nth_field_old(
- rec, DICT_FLD__SYS_TABLES__SPACE, &len);
- ut_ad(len == 4);
- space_id_for_table = mach_read_from_4(field);
-
- if (space_id_for_table == space_id) {
- found = true;
- }
- }
-
- mtr_commit(&mtr);
- dict_sys_unlock();
-
- return(!found);
-}
-
-/** Find the space_id for the given name in sys_tablespaces.
-@param[in] name Tablespace name to search for.
-@return the tablespace ID. */
-ulint
-dict_space_get_id(
- const char* name)
-{
- btr_pcur_t pcur;
- const rec_t* rec;
- mtr_t mtr;
- ulint name_len = strlen(name);
- ulint id = ULINT_UNDEFINED;
-
- dict_sys_lock();
- mtr_start(&mtr);
-
- for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLESPACES);
- rec != NULL;
- rec = dict_getnext_system(&pcur, &mtr)) {
- const byte* field;
- ulint len;
-
- field = rec_get_nth_field_old(
- rec, DICT_FLD__SYS_TABLESPACES__NAME, &len);
- ut_ad(len > 0);
- ut_ad(len < OS_FILE_MAX_PATH);
-
- if (len == name_len && !memcmp(name, field, len)) {
- field = rec_get_nth_field_old(
- rec, DICT_FLD__SYS_TABLESPACES__SPACE, &len);
- ut_ad(len == 4);
- id = mach_read_from_4(field);
-
- /* This is normally called by dict_getnext_system()
- at the end of the index. */
- btr_pcur_close(&pcur);
- break;
- }
- }
-
- mtr_commit(&mtr);
- dict_sys_unlock();
-
- return(id);
-}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index ccd46dd88b6..6fd1e99023a 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -541,6 +541,7 @@ static PSI_mutex_info all_innodb_mutexes[] = {
PSI_KEY(ibuf_bitmap_mutex),
PSI_KEY(ibuf_mutex),
PSI_KEY(ibuf_pessimistic_insert_mutex),
+ PSI_KEY(index_online_log),
PSI_KEY(log_sys_mutex),
PSI_KEY(page_zip_stat_per_index_mutex),
PSI_KEY(purge_sys_pq_mutex),
@@ -587,7 +588,6 @@ static PSI_rwlock_info all_innodb_rwlocks[] = {
PSI_RWLOCK_KEY(trx_i_s_cache_lock),
PSI_RWLOCK_KEY(trx_purge_latch),
PSI_RWLOCK_KEY(index_tree_rw_lock),
- PSI_RWLOCK_KEY(index_online_log),
};
# endif /* UNIV_PFS_RWLOCK */
@@ -15264,24 +15264,6 @@ struct table_list_item {
const char* name;
};
-/** Structure to compare two st_tablename objects using their
-db and tablename. It is used in the ordering of cascade_fk_set.
-It returns true if the first argument precedes the second argument
-and false otherwise. */
-struct tablename_compare {
-
- bool operator()(const st_handler_tablename lhs,
- const st_handler_tablename rhs) const
- {
- int cmp = strcmp(lhs.db, rhs.db);
- if (cmp == 0) {
- cmp = strcmp(lhs.tablename, rhs.tablename);
- }
-
- return(cmp < 0);
- }
-};
-
/*****************************************************************//**
Checks if ALTER TABLE may change the storage engine of the table.
Changing storage engines is not allowed for tables for which there
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 2e06272e43a..c5c5e8cba31 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -51,12 +51,7 @@ struct ha_table_option_struct
uint encryption; /*!< DEFAULT, ON, OFF */
ulonglong encryption_key_id; /*!< encryption key id */
};
-/* JAN: TODO: MySQL 5.7 handler.h */
-struct st_handler_tablename
-{
- const char *db;
- const char *tablename;
-};
+
/** The class defining a handle to an Innodb table */
class ha_innobase final : public handler
{
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 91a450b0711..0d81f81135c 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -4170,19 +4170,11 @@ insert buffer. If the page is not read, but created in the buffer pool, this
function deletes its buffered entries from the insert buffer; there can
exist entries for such a page if the page belonged to an index which
subsequently was dropped.
-@param[in,out] block if page has been read from disk,
-pointer to the page x-latched, else NULL
-@param[in] page_id page id of the index page
-@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
-@param[in] update_ibuf_bitmap normally this is set, but
-if we have deleted or are deleting the tablespace, then we naturally do not
-want to update a non-existent bitmap page */
-void
-ibuf_merge_or_delete_for_page(
- buf_block_t* block,
- const page_id_t page_id,
- ulint zip_size,
- bool update_ibuf_bitmap)
+@param block X-latched page to try to apply changes to, or NULL to discard
+@param page_id page identifier
+@param zip_size ROW_FORMAT=COMPRESSED page size, or 0 */
+void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
+ ulint zip_size)
{
btr_pcur_t pcur;
#ifdef UNIV_IBUF_DEBUG
@@ -4211,47 +4203,33 @@ ibuf_merge_or_delete_for_page(
return;
}
- fil_space_t* space;
-
- if (update_ibuf_bitmap) {
- space = fil_space_t::get(page_id.space());
-
- if (UNIV_UNLIKELY(!space)) {
- /* Do not try to read the bitmap page from the
- non-existent tablespace, delete the ibuf records */
- block = NULL;
- update_ibuf_bitmap = false;
- } else {
- ulint bitmap_bits = 0;
+ fil_space_t* space = fil_space_t::get(page_id.space());
- ibuf_mtr_start(&mtr);
+ if (UNIV_UNLIKELY(!space)) {
+ block = NULL;
+ } else {
+ ulint bitmap_bits = 0;
- buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
- page_id, zip_size, &mtr);
+ ibuf_mtr_start(&mtr);
- if (bitmap_page
- && fil_page_get_type(bitmap_page->frame)
- != FIL_PAGE_TYPE_ALLOCATED) {
- bitmap_bits = ibuf_bitmap_page_get_bits(
- bitmap_page->frame, page_id, zip_size,
- IBUF_BITMAP_BUFFERED, &mtr);
- }
+ buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
+ page_id, zip_size, &mtr);
+
+ if (bitmap_page
+ && fil_page_get_type(bitmap_page->frame)
+ != FIL_PAGE_TYPE_ALLOCATED) {
+ bitmap_bits = ibuf_bitmap_page_get_bits(
+ bitmap_page->frame, page_id, zip_size,
+ IBUF_BITMAP_BUFFERED, &mtr);
+ }
- ibuf_mtr_commit(&mtr);
+ ibuf_mtr_commit(&mtr);
- if (!bitmap_bits) {
- /* No changes are buffered for this page. */
- space->release();
- return;
- }
+ if (!bitmap_bits) {
+ /* No changes are buffered for this page. */
+ space->release();
+ return;
}
- } else if (block != NULL
- && (ibuf_fixed_addr_page(page_id, physical_size)
- || fsp_descr_page(page_id, physical_size))) {
-
- return;
- } else {
- space = NULL;
}
mem_heap_t* heap = mem_heap_create(512);
@@ -4297,12 +4275,11 @@ loop:
ibuf.index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
&pcur, &mtr);
- if (block != NULL) {
+ if (block) {
ut_ad(rw_lock_own(&block->lock, RW_LOCK_X));
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
rw_lock_x_lock(&block->lock);
- mtr.set_named_space(space);
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
/* This is a user page (secondary index leaf page),
but we pretend that it is a change buffer page in
@@ -4311,7 +4288,9 @@ loop:
the block is io-fixed. Other threads must not try to
latch an io-fixed block. */
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
- } else if (update_ibuf_bitmap) {
+ }
+
+ if (space) {
mtr.set_named_space(space);
}
@@ -4467,7 +4446,7 @@ loop:
}
reset_bit:
- if (!update_ibuf_bitmap) {
+ if (!space) {
} else if (buf_block_t* bitmap = ibuf_bitmap_get_map_page(
page_id, zip_size, &mtr)) {
/* FIXME: update the bitmap byte only once! */
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 276252e625c..f7c4d5dca29 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -910,19 +910,6 @@ inline ulint dict_tf_get_zip_size(ulint flags)
: 0;
}
-/** Determine the extent size (in pages) for the given table
-@param[in] table the table whose extent size is being
- calculated.
-@return extent size in pages (256, 128 or 64) */
-inline ulint dict_table_extent_size(const dict_table_t* table)
-{
- if (ulint zip_size = table->space->zip_size()) {
- return (1U << 20) / zip_size;
- }
-
- return FSP_EXTENT_SIZE;
-}
-
/********************************************************************//**
Checks if a column is in the ordering columns of the clustered index of a
table. Column prefixes are treated like whole columns.
@@ -1803,20 +1790,6 @@ dict_table_decode_n_col(
ulint* n_col,
ulint* n_v_col);
-/** Look for any dictionary objects that are found in the given tablespace.
-@param[in] space_id Tablespace ID to search for.
-@return true if tablespace is empty. */
-bool
-dict_space_is_empty(
- ulint space_id);
-
-/** Find the space_id for the given name in sys_tablespaces.
-@param[in] name Tablespace name to search for.
-@return the tablespace ID. */
-ulint
-dict_space_get_id(
- const char* name);
-
/** Free the virtual column template
@param[in,out] vc_templ virtual column template */
UNIV_INLINE
diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h
index 061f1bc4e8e..cb418e57532 100644
--- a/storage/innobase/include/ibuf0ibuf.h
+++ b/storage/innobase/include/ibuf0ibuf.h
@@ -329,19 +329,11 @@ insert buffer. If the page is not read, but created in the buffer pool, this
function deletes its buffered entries from the insert buffer; there can
exist entries for such a page if the page belonged to an index which
subsequently was dropped.
-@param[in,out] block if page has been read from disk,
-pointer to the page x-latched, else NULL
-@param[in] page_id page id of the index page
-@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
-@param[in] update_ibuf_bitmap normally this is set, but
-if we have deleted or are deleting the tablespace, then we naturally do not
-want to update a non-existent bitmap page */
-void
-ibuf_merge_or_delete_for_page(
- buf_block_t* block,
- const page_id_t page_id,
- ulint zip_size,
- bool update_ibuf_bitmap);
+@param block X-latched page to try to apply changes to, or NULL to discard
+@param page_id page identifier
+@param zip_size ROW_FORMAT=COMPRESSED page size, or 0 */
+void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
+ ulint zip_size);
/** Delete all change buffer entries for a tablespace,
in DISCARD TABLESPACE, IMPORT TABLESPACE, or crash recovery.
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 2294025a1aa..2aa0ed1e0e3 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -985,20 +985,6 @@ public:
/*------------------------------*/
char* detailed_error; /*!< detailed error message for last
error, or empty. */
- /* Lock wait statistics */
- ulint n_rec_lock_waits;
- /*!< Number of record lock waits,
- might not be exactly correct. */
- ulint n_table_lock_waits;
- /*!< Number of table lock waits,
- might not be exactly correct. */
- ulint total_rec_lock_wait_time;
- /*!< Total rec lock wait time up
- to this moment. */
- ulint total_table_lock_wait_time;
- /*!< Total table lock wait time
- up to this moment. */
-
rw_trx_hash_element_t *rw_trx_hash_element;
LF_PINS *rw_trx_hash_pins;
ulint magic_n;
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 24134479d8e..ee7f09ec17f 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -4259,72 +4259,152 @@ os_file_set_umask(ulint umask)
}
#ifdef _WIN32
-static int win32_get_block_size(HANDLE volume_handle, const char *volume_name)
+
+/* Checks whether physical drive is on SSD.*/
+static bool is_drive_on_ssd(DWORD nr)
{
- STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR disk_alignment;
- STORAGE_PROPERTY_QUERY storage_query;
- DWORD tmp;
-
- memset(&storage_query, 0, sizeof(storage_query));
- storage_query.PropertyId = StorageAccessAlignmentProperty;
- storage_query.QueryType = PropertyStandardQuery;
-
- if (os_win32_device_io_control(volume_handle,
- IOCTL_STORAGE_QUERY_PROPERTY,
- &storage_query,
- sizeof storage_query,
- &disk_alignment,
- sizeof disk_alignment,
- &tmp) && tmp == sizeof disk_alignment) {
- return disk_alignment.BytesPerPhysicalSector;
- }
+ char physical_drive_path[32];
+ snprintf(physical_drive_path, sizeof(physical_drive_path),
+ "\\\\.\\PhysicalDrive%lu", nr);
+
+ HANDLE h= CreateFile(physical_drive_path, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+ if (h == INVALID_HANDLE_VALUE)
+ return false;
- switch (GetLastError()) {
- case ERROR_INVALID_FUNCTION:
- case ERROR_NOT_SUPPORTED:
- break;
- default:
- os_file_handle_error_no_exit(
- volume_name,
- "DeviceIoControl(IOCTL_STORAGE_QUERY_PROPERTY / StorageAccessAlignmentProperty)",
- FALSE);
- }
- return 512;
+ DEVICE_SEEK_PENALTY_DESCRIPTOR seek_penalty;
+ STORAGE_PROPERTY_QUERY storage_query{};
+ storage_query.PropertyId= StorageDeviceSeekPenaltyProperty;
+ storage_query.QueryType= PropertyStandardQuery;
+
+ bool on_ssd= false;
+ DWORD bytes_written;
+ if (DeviceIoControl(h, IOCTL_STORAGE_QUERY_PROPERTY, &storage_query,
+ sizeof storage_query, &seek_penalty, sizeof seek_penalty,
+ &bytes_written, nullptr))
+ {
+ on_ssd= seek_penalty.IncursSeekPenalty;
+ }
+ else
+ {
+ on_ssd= false;
+ }
+ CloseHandle(h);
+ return on_ssd;
}
-static bool win32_is_ssd(HANDLE volume_handle)
+/*
+ Checks whether volume is on SSD, by checking all physical drives
+ in that volume.
+*/
+static bool is_volume_on_ssd(const char *volume_mount_point)
{
- DWORD tmp;
- DEVICE_SEEK_PENALTY_DESCRIPTOR seek_penalty;
- STORAGE_PROPERTY_QUERY storage_query;
- memset(&storage_query, 0, sizeof(storage_query));
-
- storage_query.PropertyId = StorageDeviceSeekPenaltyProperty;
- storage_query.QueryType = PropertyStandardQuery;
-
- if (os_win32_device_io_control(volume_handle,
- IOCTL_STORAGE_QUERY_PROPERTY,
- &storage_query,
- sizeof storage_query,
- &seek_penalty,
- sizeof seek_penalty,
- &tmp) && tmp == sizeof(seek_penalty)){
- return !seek_penalty.IncursSeekPenalty;
+ char volume_name[MAX_PATH];
+
+ if (!GetVolumeNameForVolumeMountPoint(volume_mount_point, volume_name,
+ array_elements(volume_name)))
+ {
+ /* This can fail, e.g if file is on network share */
+ return false;
}
- DEVICE_TRIM_DESCRIPTOR trim;
- storage_query.PropertyId = StorageDeviceTrimProperty;
- if (os_win32_device_io_control(volume_handle,
- IOCTL_STORAGE_QUERY_PROPERTY,
- &storage_query,
- sizeof storage_query,
- &trim,
- sizeof trim,
- &tmp) && tmp == sizeof trim) {
- return trim.TrimEnabled;
+ /* Chomp last backslash, this is needed to open volume.*/
+ size_t length= strlen(volume_name);
+ if (length && volume_name[length - 1] == '\\')
+ volume_name[length - 1]= 0;
+
+ /* Open volume handle */
+ HANDLE volume_handle= CreateFile(
+ volume_name, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+
+ if (volume_handle == INVALID_HANDLE_VALUE)
+ return false;
+
+ /*
+ Enumerate all volume extends, check whether all of them are on SSD
+ */
+
+ /* Anticipate common case where there is only one extent.*/
+ VOLUME_DISK_EXTENTS single_extent;
+
+ /* But also have a place to manage allocated data.*/
+ std::unique_ptr<BYTE[]> lifetime;
+
+ DWORD bytes_written;
+ VOLUME_DISK_EXTENTS *extents= nullptr;
+ if (DeviceIoControl(volume_handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
+ nullptr, 0, &single_extent, sizeof(single_extent),
+ &bytes_written, nullptr))
+ {
+ /* Worked on the first try. Use the preallocated buffer.*/
+ extents= &single_extent;
}
- return false;
+ else
+ {
+ VOLUME_DISK_EXTENTS *last_query= &single_extent;
+ while (GetLastError() == ERROR_MORE_DATA)
+ {
+ DWORD extentCount= last_query->NumberOfDiskExtents;
+ DWORD allocatedSize=
+ FIELD_OFFSET(VOLUME_DISK_EXTENTS, Extents[extentCount]);
+ lifetime.reset(new BYTE[allocatedSize]);
+ last_query= (VOLUME_DISK_EXTENTS *) lifetime.get();
+ if (DeviceIoControl(volume_handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
+ nullptr, 0, last_query, allocatedSize,
+ &bytes_written, nullptr))
+ {
+ extents= last_query;
+ break;
+ }
+ }
+ }
+ CloseHandle(volume_handle);
+ if (!extents)
+ return false;
+
+ for (DWORD i= 0; i < extents->NumberOfDiskExtents; i++)
+ if (!is_drive_on_ssd(extents->Extents[i].DiskNumber))
+ return false;
+
+ return true;
+}
+
+#include <unordered_map>
+static bool is_file_on_ssd(char *file_path)
+{
+ /* Cache of volume_path => volume_info, protected by rwlock.*/
+ static std::unordered_map<std::string, bool> cache;
+ static SRWLOCK lock= SRWLOCK_INIT;
+
+ /* Preset result, in case something fails, e.g we're on network drive.*/
+ char volume_path[MAX_PATH];
+ if (!GetVolumePathName(file_path, volume_path, array_elements(volume_path)))
+ return false;
+
+ /* Try cached volume info first.*/
+ std::string volume_path_str(volume_path);
+ bool found;
+ bool result;
+ AcquireSRWLockShared(&lock);
+ auto e= cache.find(volume_path_str);
+ if ((found= e != cache.end()))
+ result= e->second;
+ ReleaseSRWLockShared(&lock);
+
+ if (found)
+ return result;
+
+ result= is_volume_on_ssd(volume_path);
+
+ /* Update cache */
+ AcquireSRWLockExclusive(&lock);
+ cache[volume_path_str]= result;
+ ReleaseSRWLockExclusive(&lock);
+ return result;
}
+
#endif
/** Determine some file metadata when creating or reading the file.
@@ -4361,48 +4441,12 @@ void fil_node_t::find_metadata(os_file_t file
space->atomic_write_supported = space->purpose == FIL_TYPE_TEMPORARY
|| space->purpose == FIL_TYPE_IMPORT;
#ifdef _WIN32
- block_size = 512;
- on_ssd = false;
- // Open volume for this file, find out it "physical bytes per sector"
- char volume[MAX_PATH + 4];
- if (!GetVolumePathName(name, volume + 4, MAX_PATH)) {
- os_file_handle_error_no_exit(name,
- "GetVolumePathName()", FALSE);
- return;
- }
- // Special prefix required for volume names.
- memcpy(volume, "\\\\.\\", 4);
-
- size_t len = strlen(volume);
- if (volume[len - 1] == '\\') {
- // Trim trailing backslash from volume name.
- volume[len - 1] = 0;
- }
-
- HANDLE volume_handle = CreateFile(volume, FILE_READ_ATTRIBUTES,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- 0, OPEN_EXISTING, 0, 0);
-
- if (volume_handle != INVALID_HANDLE_VALUE) {
- block_size = win32_get_block_size(volume_handle, volume);
- on_ssd = win32_is_ssd(volume_handle);
- CloseHandle(volume_handle);
+ on_ssd = is_file_on_ssd(name);
+ FILE_STORAGE_INFO info;
+ if (GetFileInformationByHandleEx(
+ file, FileStorageInfo, &info, sizeof(info))) {
+ block_size = info.PhysicalBytesPerSectorForAtomicity;
} else {
- /*
- Report error, unless it is expected, e.g
- missing permissions, or error when trying to
- open volume for UNC share.
- */
- if (GetLastError() != ERROR_ACCESS_DENIED
- && GetDriveType(volume) == DRIVE_FIXED) {
- os_file_handle_error_no_exit(volume, "CreateFile()", FALSE);
- }
- }
-
- /* Currently we support file block size up to 4KiB */
- if (block_size > 4096) {
- block_size = 4096;
- } else if (block_size < 512) {
block_size = 512;
}
#else
diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc
index 1b1cabb6963..49b0a21330d 100644
--- a/storage/innobase/trx/trx0rec.cc
+++ b/storage/innobase/trx/trx0rec.cc
@@ -59,12 +59,12 @@ const dtuple_t trx_undo_metadata = {
static ulint trx_undo_left(const buf_block_t *undo_block, const byte *ptr)
{
ut_ad(ptr >= &undo_block->frame[TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE]);
- ut_ad(ptr <= &undo_block->frame[srv_page_size - 10 - FIL_PAGE_DATA_END]);
-
/* The 10 is supposed to be an extra safety margin (and needed for
compatibility with older versions) */
- return srv_page_size - ulint(ptr - undo_block->frame) -
+ lint left= srv_page_size - (ptr - undo_block->frame) -
(10 + FIL_PAGE_DATA_END);
+ ut_ad(left >= 0);
+ return left < 0 ? 0 : static_cast<ulint>(left);
}
/**********************************************************************//**
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 074667a22f9..bd54af76d9d 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -460,10 +460,6 @@ void trx_t::free()
MEM_NOACCESS(&xid, sizeof xid);
MEM_NOACCESS(&mod_tables, sizeof mod_tables);
MEM_NOACCESS(&detailed_error, sizeof detailed_error);
- MEM_NOACCESS(&n_rec_lock_waits, sizeof n_rec_lock_waits);
- MEM_NOACCESS(&n_table_lock_waits, sizeof n_table_lock_waits);
- MEM_NOACCESS(&total_rec_lock_wait_time, sizeof total_rec_lock_wait_time);
- MEM_NOACCESS(&total_table_lock_wait_time, sizeof total_table_lock_wait_time);
MEM_NOACCESS(&magic_n, sizeof magic_n);
trx_pools->mem_free(this);
}
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index 2b390c6c267..a0c755b3a7d 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -2360,6 +2360,14 @@ static int initialize_variables_for_repair(HA_CHECK *param,
{
MARIA_SHARE *share= info->s;
+ /*
+ We have to clear these variables first, as the cleanup-in-case-of-error
+ handling may touch these.
+ */
+ bzero((char*) sort_info, sizeof(*sort_info));
+ bzero((char*) sort_param, sizeof(*sort_param));
+ bzero(&info->rec_cache, sizeof(info->rec_cache));
+
if (share->data_file_type == NO_RECORD)
{
_ma_check_print_error(param,
@@ -2374,9 +2382,6 @@ static int initialize_variables_for_repair(HA_CHECK *param,
if (share->lock.update_status)
(*share->lock.update_status)(info->lock.status_param);
- bzero((char*) sort_info, sizeof(*sort_info));
- bzero((char*) sort_param, sizeof(*sort_param));
-
param->testflag|= T_REP; /* for easy checking */
if (share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
param->testflag|= T_CALC_CHECKSUM;
@@ -2404,7 +2409,6 @@ static int initialize_variables_for_repair(HA_CHECK *param,
set_data_file_type(sort_info, info->s);
sort_info->org_data_file_type= share->data_file_type;
- bzero(&info->rec_cache, sizeof(info->rec_cache));
info->rec_cache.file= info->dfile.file;
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
@@ -2891,9 +2895,13 @@ err:
_ma_reset_state(info);
end_io_cache(&param->read_cache);
- end_io_cache(&sort_info.new_info->rec_cache);
+ if (sort_info.new_info)
+ {
+ end_io_cache(&sort_info.new_info->rec_cache);
+ sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
+ }
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
+
sort_param.sort_info->info->in_check_table= 0;
/* this below could fail, shouldn't we detect error? */
if (got_error)
@@ -4110,10 +4118,13 @@ err:
maria_scan_end(sort_info.info);
_ma_reset_state(info);
- end_io_cache(&sort_info.new_info->rec_cache);
+ if (sort_info.new_info)
+ {
+ end_io_cache(&sort_info.new_info->rec_cache);
+ sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
+ }
end_io_cache(&param->read_cache);
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
if (got_error)
{
if (! param->error_printed)
@@ -4642,10 +4653,13 @@ err:
the share by remove_io_thread() or it was not yet started (if the
error happend before creating the thread).
*/
- end_io_cache(&sort_info.new_info->rec_cache);
+ if (sort_info.new_info)
+ {
+ end_io_cache(&sort_info.new_info->rec_cache);
+ sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
+ }
end_io_cache(&param->read_cache);
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
/*
Destroy the new data cache in case of non-quick repair. All slave
threads did either detach from the share by remove_io_thread()
diff --git a/storage/maria/ma_delete_table.c b/storage/maria/ma_delete_table.c
index 90e6b5250c1..fa93a7100b0 100644
--- a/storage/maria/ma_delete_table.c
+++ b/storage/maria/ma_delete_table.c
@@ -30,6 +30,7 @@ int maria_delete_table(const char *name)
{
MARIA_HA *info;
myf sync_dir;
+ int got_error= 0, error;
DBUG_ENTER("maria_delete_table");
#ifdef EXTRA_DEBUG
@@ -41,9 +42,13 @@ int maria_delete_table(const char *name)
Unfortunately it is necessary to open the table just to check this. We use
'open_for_repair' to be able to open even a crashed table.
*/
+ my_errno= 0;
if (!(info= maria_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR, 0)))
{
sync_dir= 0;
+ /* Ignore not found errors and wrong symlink errors */
+ if (my_errno != ENOENT && my_errno != HA_WRONG_CREATE_OPTION)
+ got_error= my_errno;;
}
else
{
@@ -78,7 +83,9 @@ int maria_delete_table(const char *name)
DBUG_RETURN(1);
}
- DBUG_RETURN(maria_delete_table_files(name, 0, sync_dir | MY_WME));
+ if (!(error= maria_delete_table_files(name, 0, sync_dir | MY_WME)))
+ error= got_error;
+ DBUG_RETURN(error);
}
/**
diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c
index f32fd6dd19d..28c24dc6ed1 100644
--- a/storage/maria/ma_open.c
+++ b/storage/maria/ma_open.c
@@ -1476,7 +1476,7 @@ static void setup_key_functions(register MARIA_KEYDEF *keyinfo)
/**
- @brief Function to save and store the header in the index file (.MYI)
+ @brief Function to save and store the header in the index file (.MAI)
Operates under MARIA_SHARE::intern_lock if requested.
Sets MARIA_SHARE::MARIA_STATE_INFO::is_of_horizon if transactional table.
diff --git a/wsrep-lib b/wsrep-lib
-Subproject 2da6e4894e1df5d1db51db2bbc49255e02251b9
+Subproject 41a6e9dad79c921134e44cf974b6b7ca3b84e53