diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-09-21 12:29:00 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-09-21 12:29:00 +0300 |
commit | 3a423088ac4f854448803d8af14e0d176b08f0af (patch) | |
tree | 2c1cb172aa2457993b98eeb4152298089b340d36 | |
parent | 29847a37363ad439639dd414ec9f76a6678130d9 (diff) | |
parent | fba6ffe433fdba7aa397f1de8eb4ee0a74f55800 (diff) | |
download | mariadb-git-3a423088ac4f854448803d8af14e0d176b08f0af.tar.gz |
Merge 10.3 into 10.4
56 files changed, 982 insertions, 1742 deletions
diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index e008b2352a7..4c0ef77760c 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -1092,6 +1092,7 @@ write_slave_info(MYSQL *connection) char *master = NULL; char *filename = NULL; char *gtid_executed = NULL; + char *using_gtid = NULL; char *position = NULL; char *gtid_slave_pos = NULL; char *ptr; @@ -1102,6 +1103,7 @@ write_slave_info(MYSQL *connection) {"Relay_Master_Log_File", &filename}, {"Exec_Master_Log_Pos", &position}, {"Executed_Gtid_Set", >id_executed}, + {"Using_Gtid", &using_gtid}, {NULL, NULL} }; @@ -1142,7 +1144,8 @@ write_slave_info(MYSQL *connection) ut_a(asprintf(&mysql_slave_position, "master host '%s', purge list '%s'", master, gtid_executed) != -1); - } else if (gtid_slave_pos && *gtid_slave_pos) { + } else if (gtid_slave_pos && *gtid_slave_pos && + !(using_gtid && !strncmp(using_gtid, "No", 2))) { /* MariaDB >= 10.0 with GTID enabled */ result = backup_file_printf(XTRABACKUP_SLAVE_INFO, "SET GLOBAL gtid_slave_pos = '%s';\n" diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h index 0a06445de00..a040e40ed3c 100644 --- a/include/mysql/service_wsrep.h +++ b/include/mysql/service_wsrep.h @@ -85,6 +85,8 @@ extern struct wsrep_service_st { void (*wsrep_commit_ordered_func)(MYSQL_THD thd); my_bool (*wsrep_thd_is_applying_func)(const MYSQL_THD thd); bool (*wsrep_thd_set_wsrep_aborter_func)(MYSQL_THD bf_thd, MYSQL_THD thd); + void (*wsrep_report_bf_lock_wait_func)(const MYSQL_THD thd, + unsigned long long trx_id); } *wsrep_service; #define MYSQL_SERVICE_WSREP_INCLUDED @@ -126,7 +128,7 @@ extern struct wsrep_service_st { #define wsrep_commit_ordered(T) wsrep_service->wsrep_commit_ordered_func(T) #define wsrep_thd_is_applying(T) wsrep_service->wsrep_thd_is_applying_func(T) #define wsrep_thd_set_wsrep_aborter(T) wsrep_service->wsrep_thd_set_wsrep_aborter_func(T1, T2) - +#define wsrep_report_bf_lock_wait(T,I) wsrep_service->wsrep_report_bf_lock_wait(T,I) #else #define MYSQL_SERVICE_WSREP_STATIC_INCLUDED @@ -221,6 +223,7 @@ extern "C" my_bool wsrep_get_debug(); extern "C" void wsrep_commit_ordered(MYSQL_THD thd); extern "C" my_bool wsrep_thd_is_applying(const MYSQL_THD thd); extern "C" bool wsrep_thd_set_wsrep_aborter(MYSQL_THD bf_thd, MYSQL_THD victim_thd); - +extern "C" void wsrep_report_bf_lock_wait(const THD *thd, + unsigned long long trx_id); #endif #endif /* MYSQL_SERVICE_WSREP_INCLUDED */ diff --git a/mysql-test/main/windows_debug.result b/mysql-test/main/windows_debug.result new file mode 100644 index 00000000000..e6816cdd99b --- /dev/null +++ b/mysql-test/main/windows_debug.result @@ -0,0 +1,4 @@ +# mdev-23741 sharing violation when renaming .frm file in ALTER +CREATE TABLE t(i int); +SET STATEMENT debug_dbug='+d,rename_sharing_violation' FOR ALTER TABLE t ADD PRIMARY KEY (i); +DROP TABLE t; diff --git a/mysql-test/main/windows_debug.test b/mysql-test/main/windows_debug.test new file mode 100644 index 00000000000..bb0880ddc55 --- /dev/null +++ b/mysql-test/main/windows_debug.test @@ -0,0 +1,11 @@ +# Windows-specific tests , debug mode + +--source include/have_debug.inc +--source include/windows.inc + +--echo # mdev-23741 sharing violation when renaming .frm file in ALTER +CREATE TABLE t(i int); +SET STATEMENT debug_dbug='+d,rename_sharing_violation' FOR ALTER TABLE t ADD PRIMARY KEY (i); +DROP TABLE t; + +#End of 10.3 tests diff --git a/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result b/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result index 7c98b3e85ed..0ba269558d5 100644 --- a/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result +++ b/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result @@ -4,48 +4,45 @@ connection node_1; connection node_2; connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; -CREATE PROCEDURE p1 () -BEGIN -DECLARE x INT DEFAULT 1; -DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; -WHILE 1 DO -INSERT INTO t1 VALUES (DEFAULT); -COMMIT; -END WHILE; -END| -CALL p1();; -connection node_2; -CALL p1();; +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2a; Killing server ... -INSERT INTO t1 VALUES (DEFAULT); -connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; -connection node_1a; -INSERT INTO t1 VALUES (DEFAULT); connection node_1; -Got one of the listed errors -connection node_2; -Got one of the listed errors -connection node_1a; +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); connection node_2a; -count_equal -1 -CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0"); -SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -VARIABLE_VALUE -2 -SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -VARIABLE_VALUE = 2 -1 +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1a; -SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -VARIABLE_VALUE -2 -SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -VARIABLE_VALUE = 2 -1 -DROP PROCEDURE p1; +SELECT COUNT(*) FROM t1; +COUNT(*) +132 +connection node_2a; +SELECT COUNT(*) FROM t1; +COUNT(*) +132 +connection node_1; DROP TABLE t1; CALL mtr.add_suppression("gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0"); +disconnect node_1a; +disconnect node_2a; diff --git a/mysql-test/suite/galera/r/galera_wan_restart_ist.result b/mysql-test/suite/galera/r/galera_wan_restart_ist.result index 7b87d534d92..46865a9c48c 100644 --- a/mysql-test/suite/galera/r/galera_wan_restart_ist.result +++ b/mysql-test/suite/galera/r/galera_wan_restart_ist.result @@ -6,11 +6,11 @@ connection node_1; connection node_2; connection node_3; connection node_4; -SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -VARIABLE_VALUE = 4 -1 +SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +EXPECT_4 +4 connection node_1; -CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=INNODB; INSERT INTO t1 VALUES (1); connection node_2; INSERT INTO t1 VALUES (2); @@ -22,60 +22,78 @@ connection node_3; INSERT INTO t1 VALUES (13); Shutting down server ... connection node_1; +SELECT VARIABLE_VALUE AS EXPECT_3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +EXPECT_3 +3 INSERT INTO t1 VALUES (11); connection node_2; INSERT INTO t1 VALUES (12); connection node_4; INSERT INTO t1 VALUES (14); connection node_3; +SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +EXPECT_4 +4 INSERT INTO t1 VALUES (131); connection node_2; INSERT INTO t1 VALUES (22); Shutting down server ... connection node_1; +SELECT VARIABLE_VALUE AS EXPECT_3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +EXPECT_3 +3 INSERT INTO t1 VALUES (21); connection node_3; INSERT INTO t1 VALUES (23); connection node_4; INSERT INTO t1 VALUES (24); connection node_2; +SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +EXPECT_4 +4 INSERT INTO t1 VALUES (221); connection node_4; INSERT INTO t1 VALUES (34); Shutting down server ... connection node_1; +SELECT VARIABLE_VALUE AS EXPECT_3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +EXPECT_3 +3 INSERT INTO t1 VALUES (31); connection node_2; INSERT INTO t1 VALUES (32); connection node_3; INSERT INTO t1 VALUES (33); connection node_4; +SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +EXPECT_4 +4 INSERT INTO t1 VALUES (341); connection node_1; -SELECT COUNT(*) = 19 FROM t1; -COUNT(*) = 19 -1 +SELECT COUNT(*) AS EXPECT_19 FROM t1; +EXPECT_19 +19 connection node_2; SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 4 1 -SELECT COUNT(*) = 19 FROM t1; -COUNT(*) = 19 -1 +SELECT COUNT(*) AS EXPECT_19 FROM t1; +EXPECT_19 +19 connection node_3; SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 4 1 -SELECT COUNT(*) = 19 FROM t1; -COUNT(*) = 19 -1 +SELECT COUNT(*) AS EXPECT_19 FROM t1; +EXPECT_19 +19 connection node_4; SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 4 1 -SELECT COUNT(*) = 19 FROM t1; -COUNT(*) = 19 -1 +SELECT COUNT(*) AS EXPECT_19 FROM t1; +EXPECT_19 +19 connection node_1; DROP TABLE t1; CALL mtr.add_suppression("There are no nodes in the same segment that will ever be able to become donors, yet there is a suitable donor outside"); @@ -86,5 +104,6 @@ CALL mtr.add_suppression("There are no nodes in the same segment that will ever CALL mtr.add_suppression("Action message in non-primary configuration from member 0"); connection node_4; CALL mtr.add_suppression("Action message in non-primary configuration from member 0"); -disconnect node_2; -disconnect node_1; +connection node_1; +disconnect node_3; +disconnect node_4; diff --git a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test index 72952d271d5..ff8bdc9c4cc 100644 --- a/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test +++ b/mysql-test/suite/galera/t/galera_autoinc_sst_mariabackup.test @@ -2,93 +2,62 @@ # Test that autoincrement works correctly while the cluster membership # is changing and SST takes place. # - --source include/big_test.inc --source include/galera_cluster.inc ---source include/have_innodb.inc --source include/have_mariabackup.inc +--source include/force_restart.inc --let $node_1=node_1 --let $node_2=node_2 --source include/auto_increment_offset_save.inc --connection node_1 ---let $connection_id = `SELECT CONNECTION_ID()` - CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; -# Issue an endless stream of autoincrement inserts - -DELIMITER |; -CREATE PROCEDURE p1 () -BEGIN - DECLARE x INT DEFAULT 1; - DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; - - WHILE 1 DO - INSERT INTO t1 VALUES (DEFAULT); - COMMIT; - END WHILE; -END| -DELIMITER ;| - ---send CALL p1(); ---sleep 1 - ---connection node_2 ---send CALL p1(); ---sleep 1 +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); # Kill and restart node #2 - --connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 --connection node_2a --source include/kill_galera.inc - --remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat ---source include/start_mysqld.inc - -INSERT INTO t1 VALUES (DEFAULT); - -# Terminate the stored procedure - ---connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 ---connection node_1a ---disable_query_log ---eval KILL CONNECTION $connection_id ---enable_query_log -INSERT INTO t1 VALUES (DEFAULT); --connection node_1 -# CR_SERVER_LOST ---error 2013,2006 ---reap - ---connection node_2 -# CR_SERVER_LOST ---error 2013,2006 ---reap +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); -# Confirm that the count is correct and that the cluster is intact +--connection node_2a +--source include/start_mysqld.inc +--source include/wait_until_connected_again.inc + +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 --connection node_1a ---let $count = `SELECT COUNT(*) FROM t1` +SELECT COUNT(*) FROM t1; --connection node_2a ---disable_query_log ---eval SELECT COUNT(*) = $count AS count_equal FROM t1 ---enable_query_log - -CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0"); - -SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; - ---connection node_1a -SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +SELECT COUNT(*) FROM t1; -DROP PROCEDURE p1; +--connection node_1 DROP TABLE t1; CALL mtr.add_suppression("gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); @@ -97,3 +66,6 @@ CALL mtr.add_suppression("WSREP: Action message in non-primary configuration fro --let $node_1=node_1a --let $node_2=node_2a --source include/auto_increment_offset_restore.inc + +--disconnect node_1a +--disconnect node_2a diff --git a/mysql-test/suite/galera/t/galera_wan_restart_ist.test b/mysql-test/suite/galera/t/galera_wan_restart_ist.test index 1cf5d4c7f74..8a011d60851 100644 --- a/mysql-test/suite/galera/t/galera_wan_restart_ist.test +++ b/mysql-test/suite/galera/t/galera_wan_restart_ist.test @@ -10,7 +10,7 @@ --source include/big_test.inc --source include/galera_cluster.inc ---source include/have_innodb.inc +--source include/force_restart.inc --connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 --connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 @@ -22,10 +22,13 @@ --let $node_4=node_4 --source include/auto_increment_offset_save.inc -SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc + +SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --connection node_1 -CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=INNODB; INSERT INTO t1 VALUES (1); --connection node_2 @@ -46,9 +49,13 @@ INSERT INTO t1 VALUES (13); --echo Shutting down server ... --source include/shutdown_mysqld.inc ---sleep 5 + --connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT VARIABLE_VALUE AS EXPECT_3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + INSERT INTO t1 VALUES (11); --connection node_2 @@ -59,9 +66,12 @@ INSERT INTO t1 VALUES (14); --connection node_3 --source include/start_mysqld.inc ---sleep 5 --source include/wait_until_connected_again.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + INSERT INTO t1 VALUES (131); # @@ -73,9 +83,12 @@ INSERT INTO t1 VALUES (22); --echo Shutting down server ... --source include/shutdown_mysqld.inc ---sleep 5 --connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT VARIABLE_VALUE AS EXPECT_3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + INSERT INTO t1 VALUES (21); --connection node_3 @@ -86,9 +99,12 @@ INSERT INTO t1 VALUES (24); --connection node_2 --source include/start_mysqld.inc ---sleep 5 --source include/wait_until_connected_again.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + INSERT INTO t1 VALUES (221); # @@ -100,9 +116,12 @@ INSERT INTO t1 VALUES (34); --echo Shutting down server ... --source include/shutdown_mysqld.inc ---sleep 5 --connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT VARIABLE_VALUE AS EXPECT_3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + INSERT INTO t1 VALUES (31); --connection node_2 @@ -113,9 +132,12 @@ INSERT INTO t1 VALUES (33); --connection node_4 --source include/start_mysqld.inc ---sleep 5 --source include/wait_until_connected_again.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; + INSERT INTO t1 VALUES (341); @@ -124,22 +146,44 @@ INSERT INTO t1 VALUES (341); # --connection node_1 ---let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 19 FROM t1 --source include/wait_condition.inc -SELECT COUNT(*) = 19 FROM t1; +SELECT COUNT(*) AS EXPECT_19 FROM t1; --connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -SELECT COUNT(*) = 19 FROM t1; + +--let $wait_condition = SELECT COUNT(*) = 19 FROM t1 +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_19 FROM t1; + --connection node_3 +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -SELECT COUNT(*) = 19 FROM t1; + +--let $wait_condition = SELECT COUNT(*) = 19 FROM t1 +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_19 FROM t1; --connection node_4 +--let $wait_condition = SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -SELECT COUNT(*) = 19 FROM t1; + +--let $wait_condition = SELECT COUNT(*) = 19 FROM t1 +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_19 FROM t1; + --connection node_1 DROP TABLE t1; @@ -158,4 +202,6 @@ CALL mtr.add_suppression("Action message in non-primary configuration from membe # Restore original auto_increment_offset values. --source include/auto_increment_offset_restore.inc ---source include/galera_end.inc +--connection node_1 +--disconnect node_3 +--disconnect node_4 diff --git a/mysql-test/suite/galera_3nodes/r/GAL-501.result b/mysql-test/suite/galera_3nodes/r/GAL-501.result index 063e88ec21a..850fb6f3f78 100644 --- a/mysql-test/suite/galera_3nodes/r/GAL-501.result +++ b/mysql-test/suite/galera_3nodes/r/GAL-501.result @@ -10,11 +10,11 @@ VARIABLE_VALUE = 3 connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; connection node_1; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 1 DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_ipv6_mariabackup.result b/mysql-test/suite/galera_3nodes/r/galera_ipv6_mariabackup.result index 248c89afe99..9a96addbf57 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_mariabackup.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_mariabackup.result @@ -9,12 +9,12 @@ VARIABLE_VALUE = 3 connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; connection node_1; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 1 DROP TABLE t1; connection node_1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_ipv6_mariabackup_section.result b/mysql-test/suite/galera_3nodes/r/galera_ipv6_mariabackup_section.result index d50a4339694..182fb1af51e 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_mariabackup_section.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_mariabackup_section.result @@ -9,12 +9,12 @@ VARIABLE_VALUE = 3 connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; connection node_1; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 1 DROP TABLE t1; connection node_1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_ipv6_mysqldump.result b/mysql-test/suite/galera_3nodes/r/galera_ipv6_mysqldump.result index bfc210db2ba..934218492d6 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_mysqldump.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_mysqldump.result @@ -14,12 +14,12 @@ SET GLOBAL wsrep_sst_method = 'mysqldump'; Shutting down server ... connection node_1; Cleaning var directory ... -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; Starting server ... -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 1 DROP TABLE t1; SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses'; diff --git a/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync.result b/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync.result index 3f810d3eb97..27cbd7dbe55 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync.result @@ -9,11 +9,11 @@ VARIABLE_VALUE = 3 connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; connection node_1; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 1 DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync_section.result b/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync_section.result index 3f810d3eb97..27cbd7dbe55 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync_section.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync_section.result @@ -9,11 +9,11 @@ VARIABLE_VALUE = 3 connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; connection node_1; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; -SELECT COUNT(*) = 1 FROM t1; -COUNT(*) = 1 +SELECT COUNT(*) AS EXPECT_1 FROM t1; +EXPECT_1 1 DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result b/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result index be6e1a88cdf..2138f48adda 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result +++ b/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result @@ -4,7 +4,8 @@ connection node_1; connection node_2; connection node_3; connection node_1; -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] @@ -62,6 +63,7 @@ CALL mtr.add_suppression("WSREP: gcs/src/gcs_core.cpp:core_handle_uuid_msg()"); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `f1` int(11) DEFAULT NULL + `f1` int(11) NOT NULL, + PRIMARY KEY (`f1`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result b/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result index cb327107e2a..776c54aebe1 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result +++ b/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result @@ -4,7 +4,7 @@ connection node_1; connection node_2; connection node_3; connection node_1; -CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t1 (f1 INTEGER) ENGINE=INNODB; INSERT INTO t1 VALUES (1); connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; diff --git a/mysql-test/suite/galera_3nodes/t/GAL-501.cnf b/mysql-test/suite/galera_3nodes/t/GAL-501.cnf index 7002cb5bdfd..3b18a86093c 100644 --- a/mysql-test/suite/galera_3nodes/t/GAL-501.cnf +++ b/mysql-test/suite/galera_3nodes/t/GAL-501.cnf @@ -10,6 +10,7 @@ wsrep_node_address=[::1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.1.#galera_port;ist.recv_addr=[::1]' wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.1.port' +bind-address=:: [mysqld.2] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' @@ -17,6 +18,7 @@ wsrep_node_address=[::1] wsrep_provider_options='base_port=@mysqld.2.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.2.#galera_port;ist.recv_addr=[::1]' wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.2.port' +bind-address=:: [mysqld.3] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' @@ -24,3 +26,4 @@ wsrep_node_address=[::1] wsrep_provider_options='base_port=@mysqld.3.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.3.#galera_port;ist.recv_addr=[::1]' wsrep_sst_receive_address='[::1]:@mysqld.3.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.3.port' +bind-address=:: diff --git a/mysql-test/suite/galera_3nodes/t/GAL-501.opt b/mysql-test/suite/galera_3nodes/t/GAL-501.opt deleted file mode 100644 index c2bb4d156af..00000000000 --- a/mysql-test/suite/galera_3nodes/t/GAL-501.opt +++ /dev/null @@ -1 +0,0 @@ ---bind-address=:: diff --git a/mysql-test/suite/galera_3nodes/t/GAL-501.test b/mysql-test/suite/galera_3nodes/t/GAL-501.test index c4b17cdb21e..af5b83ae261 100644 --- a/mysql-test/suite/galera_3nodes/t/GAL-501.test +++ b/mysql-test/suite/galera_3nodes/t/GAL-501.test @@ -6,6 +6,7 @@ --source include/galera_cluster.inc --source include/check_ipv6.inc +--source include/force_restart.inc --let $galera_connection_name = node_3 --let $galera_server_number = 3 @@ -27,7 +28,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); --connection node_2 @@ -39,6 +40,6 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; --source include/wait_condition.inc -SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) AS EXPECT_1 FROM t1; DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.cnf b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.cnf index 969f364a1ec..8432b1c368c 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.cnf @@ -11,6 +11,7 @@ wsrep_provider_options='base_host=[::1];base_port=@mysqld.1.#galera_port;gmcast. wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.1.port' wsrep_node_name=node_1 +bind-address=:: [mysqld.2] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' @@ -19,6 +20,7 @@ wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.2.port' wsrep_node_name=node_2 wsrep_sst_donor=node_1 +bind-address=:: [mysqld.3] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' @@ -27,6 +29,7 @@ wsrep_sst_receive_address='[::1]:@mysqld.3.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.3.port' wsrep_node_name=node_3 wsrep_sst_donor=node_1 +bind-address=:: [SST] transferfmt=@ENV.MTR_GALERA_TFMT diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.opt b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.opt deleted file mode 100644 index c2bb4d156af..00000000000 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.opt +++ /dev/null @@ -1 +0,0 @@ ---bind-address=:: diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test index 2050f78cda9..31613454348 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.test @@ -18,7 +18,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); --connection node_2 @@ -30,7 +30,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; --source include/wait_condition.inc -SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) AS EXPECT_1 FROM t1; DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.cnf b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.cnf index dc294854056..aa3da690416 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.cnf @@ -3,35 +3,37 @@ # decoy value - should not be read by mysqld or sst scripts [mysqld] innodb-data-home-dir=/tmp - -[galera] +bind-address=:: innodb-data-home-dir= wsrep_sst_method=mariabackup wsrep_sst_auth="root:" wsrep_node_address=::1 -[galera.1] +[mysqld.1] wsrep-cluster-address=gcomm:// wsrep_provider_options='base_host=[::1];base_port=@mysqld.1.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.1.#galera_port;ist.recv_addr=[::1]:@mysqld.1.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.1.port' wsrep_node_name=node_1 +bind-address=:: -[galera.2] +[mysqld.2] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='base_host=[::1];base_port=@mysqld.2.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.2.#galera_port;ist.recv_addr=[::1]:@mysqld.2.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.2.port' wsrep_node_name=node_2 wsrep_sst_donor=node_1 +bind-address=:: -[galera.3] +[mysqld.3] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='base_host=[::1];base_port=@mysqld.3.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.3.#galera_port;ist.recv_addr=[::1]:@mysqld.3.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.3.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.3.port' wsrep_node_name=node_3 wsrep_sst_donor=node_1 +bind-address=:: [SST] transferfmt=@ENV.MTR_GALERA_TFMT diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.opt b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.opt deleted file mode 100644 index c2bb4d156af..00000000000 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.opt +++ /dev/null @@ -1 +0,0 @@ ---bind-address=:: diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test index 559ebfd8db2..3b2ca0892f1 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup_section.test @@ -18,7 +18,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); --connection node_2 @@ -30,7 +30,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; --source include/wait_condition.inc -SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) AS EXPECT_1 FROM t1; DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf index 80dd0c41cc3..5e77a45210b 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.cnf @@ -9,18 +9,21 @@ wsrep-cluster-address=gcomm:// wsrep_provider_options='base_host=[::1];base_port=@mysqld.1.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.1.#galera_port;ist.recv_addr=[::1]:@mysqld.1.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.1.port' +bind-address=:: [mysqld.2] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='base_host=[::1];base_port=@mysqld.2.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.2.#galera_port;ist.recv_addr=[::1]:@mysqld.2.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.2.port' +bind-address=:: [mysqld.3] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='base_host=[::1];base_port=@mysqld.3.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.3.#galera_port;ist.recv_addr=[::1]:@mysqld.3.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.3.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.3.port' +bind-address=:: [SST] sockopt=",pf=ip6" diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.opt b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.opt deleted file mode 100644 index c2bb4d156af..00000000000 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.opt +++ /dev/null @@ -1 +0,0 @@ ---bind-address=:: diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test index ff93ed07763..f5dd1aeb06d 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mysqldump.test @@ -54,7 +54,7 @@ SET GLOBAL wsrep_sst_method = 'mysqldump'; --remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mysql --remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); --connection node_2 @@ -71,7 +71,7 @@ let $restart_noprint=2; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; --source include/wait_condition.inc -SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) AS EXPECT_1 FROM t1; DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.cnf b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.cnf index 80dd0c41cc3..5e77a45210b 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.cnf @@ -9,18 +9,21 @@ wsrep-cluster-address=gcomm:// wsrep_provider_options='base_host=[::1];base_port=@mysqld.1.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.1.#galera_port;ist.recv_addr=[::1]:@mysqld.1.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.1.port' +bind-address=:: [mysqld.2] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='base_host=[::1];base_port=@mysqld.2.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.2.#galera_port;ist.recv_addr=[::1]:@mysqld.2.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.2.port' +bind-address=:: [mysqld.3] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='base_host=[::1];base_port=@mysqld.3.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.3.#galera_port;ist.recv_addr=[::1]:@mysqld.3.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.3.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.3.port' +bind-address=:: [SST] sockopt=",pf=ip6" diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.opt b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.opt deleted file mode 100644 index c2bb4d156af..00000000000 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.opt +++ /dev/null @@ -1 +0,0 @@ ---bind-address=:: diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test index fff776d98b6..448611e34e0 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync.test @@ -16,7 +16,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); --connection node_2 @@ -28,6 +28,6 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; --source include/wait_condition.inc -SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) AS EXPECT_1 FROM t1; DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.cnf b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.cnf index 7cac8e1451e..809b83bb782 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.cnf @@ -4,28 +4,31 @@ [mysqld] innodb-data-home-dir=/tmp -[mariadb] +[mysqld] innodb-data-home-dir= wsrep_sst_method=rsync wsrep_node_address=::1 -[mariadb.1] +[mysqld.1] wsrep-cluster-address=gcomm:// wsrep_provider_options='base_host=[::1];base_port=@mysqld.1.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.1.#galera_port;ist.recv_addr=[::1]:@mysqld.1.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.1.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.1.port' +bind-address=:: -[mariadb.2] +[mysqld.2] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='base_host=[::1];base_port=@mysqld.2.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.2.#galera_port;ist.recv_addr=[::1]:@mysqld.2.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.2.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.2.port' +bind-address=:: -[mariadb.3] +[mysqld.3] wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_provider_options='base_host=[::1];base_port=@mysqld.3.#galera_port;gmcast.listen_addr=tcp://[::]:@mysqld.3.#galera_port;ist.recv_addr=[::1]:@mysqld.3.#ist_port' wsrep_sst_receive_address='[::1]:@mysqld.3.#sst_port' wsrep_node_incoming_address='[::1]:@mysqld.3.port' +bind-address=:: [SST] sockopt=",pf=ip6" diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.opt b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.opt deleted file mode 100644 index c2bb4d156af..00000000000 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.opt +++ /dev/null @@ -1 +0,0 @@ ---bind-address=:: diff --git a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.test b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.test index fff776d98b6..448611e34e0 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_rsync_section.test @@ -16,7 +16,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); --connection node_2 @@ -28,6 +28,6 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; --source include/wait_condition.inc -SELECT COUNT(*) = 1 FROM t1; +SELECT COUNT(*) AS EXPECT_1 FROM t1; DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.cnf b/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.cnf new file mode 100644 index 00000000000..880a413f4b6 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.cnf @@ -0,0 +1,10 @@ +!include ../galera_3nodes.cnf + +[mysqld.1] +wsrep_debug=1 + +[mysqld.2] +wsrep_debug=1 + +[mysqld.3] +wsrep_debug=1 diff --git a/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test b/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test index 8e13aed8f5f..65b4000cd1f 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test +++ b/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test @@ -2,6 +2,7 @@ # Test the safe_to_bootstrap in grastate.dat # --source include/galera_cluster.inc +--source include/force_restart.inc # # Create connection node_3 and save auto increment variables. @@ -17,8 +18,11 @@ --source ../galera/include/auto_increment_offset_save.inc --connection node_1 +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); -CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc # # At start, all grastate.dat files have safe_to_boostrap: 0 @@ -157,11 +161,19 @@ let $restart_noprint=2; --source include/start_mysqld.inc --source include/wait_until_connected_again.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + + --connection node_2 --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect let $restart_noprint=2; --source include/start_mysqld.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + + --connection node_3 --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.3.expect let $restart_noprint=2; diff --git a/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test b/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test index 8c1d6246d44..cbee81b7f94 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test +++ b/mysql-test/suite/galera_3nodes/t/galera_var_dirty_reads2.test @@ -16,10 +16,13 @@ --source ../galera/include/auto_increment_offset_save.inc --connection node_1 -CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t1 (f1 INTEGER) ENGINE=INNODB; INSERT INTO t1 VALUES (1); --connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM t1; +--source include/wait_condition.inc + SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; --connection node_1 @@ -28,15 +31,11 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; --connection node_2 SET SESSION wsrep_sync_wait = 0; - --let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; --source include/wait_condition.inc SET SESSION wsrep_dirty_reads = 1; ---let $wait_condition = SELECT COUNT(*) = 1 FROM t1; ---source include/wait_condition.inc - # Those statements should succeed --error 0 diff --git a/mysql-test/suite/gcol/r/innodb_virtual_fk.result b/mysql-test/suite/gcol/r/innodb_virtual_fk.result index d5b4755e3c5..a3cdacb67a2 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_fk.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_fk.result @@ -740,3 +740,32 @@ t1 CREATE TABLE `t1` ( KEY `v4` (`v4`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t1; +# +# MDEV-20396 Server crashes after DELETE with SEL NULL Foreign key and a +# virtual column in index +# +CREATE TABLE parent +( +ID int unsigned NOT NULL, +PRIMARY KEY (ID) +); +CREATE TABLE child +( +ID int unsigned NOT NULL, +ParentID int unsigned NULL, +Value int unsigned NOT NULL DEFAULT 0, +Flag int unsigned AS (Value) VIRTUAL, +PRIMARY KEY (ID), +KEY (ParentID, Flag), +FOREIGN KEY (ParentID) REFERENCES parent (ID) ON DELETE SET NULL +ON UPDATE CASCADE +); +INSERT INTO parent (ID) VALUES (100); +INSERT INTO child (ID,ParentID,Value) VALUES (123123,100,1); +DELETE FROM parent WHERE ID=100; +select * from child; +ID ParentID Value Flag +123123 NULL 1 1 +INSERT INTO parent (ID) VALUES (100); +UPDATE child SET ParentID=100 WHERE ID=123123; +DROP TABLE child, parent; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_fk.test b/mysql-test/suite/gcol/t/innodb_virtual_fk.test index c484bb5dc0c..226bacabaef 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_fk.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_fk.test @@ -605,3 +605,35 @@ ALTER TABLE t1 ADD CONSTRAINT fk FOREIGN KEY (v4) REFERENCES nosuch(col); SHOW CREATE TABLE t1; # Cleanup DROP TABLE t1; + +--echo # +--echo # MDEV-20396 Server crashes after DELETE with SEL NULL Foreign key and a +--echo # virtual column in index +--echo # +CREATE TABLE parent +( + ID int unsigned NOT NULL, + PRIMARY KEY (ID) +); + +CREATE TABLE child +( + ID int unsigned NOT NULL, + ParentID int unsigned NULL, + Value int unsigned NOT NULL DEFAULT 0, + Flag int unsigned AS (Value) VIRTUAL, + PRIMARY KEY (ID), + KEY (ParentID, Flag), + FOREIGN KEY (ParentID) REFERENCES parent (ID) ON DELETE SET NULL + ON UPDATE CASCADE +); + +INSERT INTO parent (ID) VALUES (100); +INSERT INTO child (ID,ParentID,Value) VALUES (123123,100,1); +DELETE FROM parent WHERE ID=100; +select * from child; +INSERT INTO parent (ID) VALUES (100); +UPDATE child SET ParentID=100 WHERE ID=123123; + +# Cleanup +DROP TABLE child, parent; diff --git a/mysql-test/suite/innodb/r/row_format_redundant.result b/mysql-test/suite/innodb/r/row_format_redundant.result index 03e516f4eb4..73f20653604 100644 --- a/mysql-test/suite/innodb/r/row_format_redundant.result +++ b/mysql-test/suite/innodb/r/row_format_redundant.result @@ -6,8 +6,7 @@ SET GLOBAL innodb_file_per_table=1; # SET GLOBAL innodb_file_per_table=ON; create table t1 (a int not null, d varchar(15) not null, b -varchar(198) not null, c char(156), -fulltext ftsic(c)) engine=InnoDB +varchar(198) not null, c char(156)) engine=InnoDB row_format=redundant; insert into t1 values(123, 'abcdef', 'jghikl', 'mnop'); insert into t1 values(456, 'abcdef', 'jghikl', 'mnop'); @@ -76,7 +75,7 @@ DROP TABLE t1; Warnings: Warning 1932 Table 'test.t1' doesn't exist in engine DROP TABLE t2,t3; -FOUND 50 /\[ERROR\] InnoDB: Table `test`\.`t1` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=511\b/ in mysqld.1.err +FOUND 6 /\[ERROR\] InnoDB: Table `test`\.`t1` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=1 SYS_TABLES\.MIX_LEN=511\b/ in mysqld.1.err # restart ib_buffer_pool ib_logfile0 diff --git a/mysql-test/suite/innodb/t/row_format_redundant.test b/mysql-test/suite/innodb/t/row_format_redundant.test index 6f38835d7e9..e8869b886c8 100644 --- a/mysql-test/suite/innodb/t/row_format_redundant.test +++ b/mysql-test/suite/innodb/t/row_format_redundant.test @@ -32,8 +32,7 @@ SET GLOBAL innodb_file_per_table=1; SET GLOBAL innodb_file_per_table=ON; create table t1 (a int not null, d varchar(15) not null, b -varchar(198) not null, c char(156), -fulltext ftsic(c)) engine=InnoDB +varchar(198) not null, c char(156)) engine=InnoDB row_format=redundant; insert into t1 values(123, 'abcdef', 'jghikl', 'mnop'); diff --git a/mysql-test/suite/mariabackup/rpl_slave_info.result b/mysql-test/suite/mariabackup/rpl_slave_info.result new file mode 100644 index 00000000000..13044fd6c39 --- /dev/null +++ b/mysql-test/suite/mariabackup/rpl_slave_info.result @@ -0,0 +1,37 @@ +include/master-slave.inc +[connection master] +connection slave; +############### +# If Using_Gtid != 'No', backup gtid_slave_pos +######################## +include/stop_slave.inc +change master to master_use_gtid=slave_pos; +include/start_slave.inc +connection master; +CREATE TABLE t(i INT); +connection slave; +"using_gtid: Slave_Pos" +FOUND 1 /gtid_slave_pos/ in xtrabackup_slave_info +NOT FOUND /MASTER_LOG_FILE/ in xtrabackup_slave_info +############### +# If Using_Gtid != 'No' and !gtid_slave_pos, backup master position +######################## +include/stop_slave.inc +SET GLOBAL gtid_slave_pos=""; +NOT FOUND /gtid_slave_pos/ in xtrabackup_slave_info +FOUND 1 /MASTER_LOG_FILE/ in xtrabackup_slave_info +############### +# If Using_Gtid == 'No', backup Exec_Master_Log_Pos +######################## +change master to master_use_gtid=no; +include/start_slave.inc +connection master; +INSERT INTO t VALUES(1); +connection slave; +"using_gtid: No" +NOT FOUND /gtid_slave_pos/ in xtrabackup_slave_info +FOUND 1 /MASTER_LOG_FILE/ in xtrabackup_slave_info +connection master; +DROP TABLE t; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/mariabackup/rpl_slave_info.test b/mysql-test/suite/mariabackup/rpl_slave_info.test new file mode 100644 index 00000000000..ca7682d8af9 --- /dev/null +++ b/mysql-test/suite/mariabackup/rpl_slave_info.test @@ -0,0 +1,84 @@ +--source include/master-slave.inc + +--connection slave + +--echo ############### +--echo # If Using_Gtid != 'No', backup gtid_slave_pos +--echo ######################## + +--source include/stop_slave.inc +change master to master_use_gtid=slave_pos; +--source include/start_slave.inc + +--connection master +CREATE TABLE t(i INT); +--sync_slave_with_master + +--let $using_gtid=query_get_value(SHOW SLAVE STATUS,Using_Gtid,1) +--echo "using_gtid: $using_gtid" + +--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2 --slave-info --backup --target-dir=$targetdir; +--enable_result_log + +--let SEARCH_FILE=$targetdir/xtrabackup_slave_info +--let SEARCH_PATTERN=gtid_slave_pos +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=MASTER_LOG_FILE +--source include/search_pattern_in_file.inc + +rmdir $targetdir; + +--echo ############### +--echo # If Using_Gtid != 'No' and !gtid_slave_pos, backup master position +--echo ######################## + +--source include/stop_slave.inc +SET GLOBAL gtid_slave_pos=""; + +--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2 --slave-info --backup --target-dir=$targetdir; +--enable_result_log + +--let SEARCH_FILE=$targetdir/xtrabackup_slave_info +--let SEARCH_PATTERN=gtid_slave_pos +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=MASTER_LOG_FILE +--source include/search_pattern_in_file.inc + +rmdir $targetdir; + +--echo ############### +--echo # If Using_Gtid == 'No', backup Exec_Master_Log_Pos +--echo ######################## + +change master to master_use_gtid=no; +--source include/start_slave.inc + +--connection master +INSERT INTO t VALUES(1); +--sync_slave_with_master + +--let $using_gtid=query_get_value(SHOW SLAVE STATUS,Using_Gtid,1) +--echo "using_gtid: $using_gtid" + +--let $targetdir=$MYSQLTEST_VARDIR/tmp/backup +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.2 --slave-info --backup --target-dir=$targetdir; +--enable_result_log + +--let SEARCH_FILE=$targetdir/xtrabackup_slave_info +--let SEARCH_PATTERN=gtid_slave_pos +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=MASTER_LOG_FILE +--source include/search_pattern_in_file.inc + +rmdir $targetdir; + +# Cleanup +--connection master +DROP TABLE t; +--sync_slave_with_master +--source include/rpl_end.inc diff --git a/mysys/my_rename.c b/mysys/my_rename.c index 9f0770e8140..7b31e83be20 100644 --- a/mysys/my_rename.c +++ b/mysys/my_rename.c @@ -19,8 +19,62 @@ #include "m_string.h" #undef my_rename - /* On unix rename deletes to file if it exists */ +#ifdef _WIN32 + +#define RENAME_MAX_RETRIES 50 + +/* + On Windows, bad 3rd party programs (backup or anitivirus, or something else) + can have file open with a sharing mode incompatible with renaming, i.e they + won't use FILE_SHARE_DELETE when opening file. + + The following function will do a couple of retries, in case MoveFileEx returns + ERROR_SHARING_VIOLATION. +*/ +static BOOL win_rename_with_retries(const char *from, const char *to) +{ +#ifndef DBUG_OFF + FILE *fp = NULL; + DBUG_EXECUTE_IF("rename_sharing_violation", + { + fp= fopen(from, "r"); + DBUG_ASSERT(fp); + } + ); +#endif + + for (int retry= RENAME_MAX_RETRIES; retry--;) + { + DWORD ret = MoveFileEx(from, to, + MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING); + + DBUG_ASSERT(fp == NULL || (ret == FALSE && GetLastError() == ERROR_SHARING_VIOLATION)); + + if (!ret && (GetLastError() == ERROR_SHARING_VIOLATION)) + { +#ifndef DBUG_OFF + /* + If error was injected in via DBUG_EXECUTE_IF, close the file + that is causing ERROR_SHARING_VIOLATION, so that retry succeeds. + */ + if (fp) + { + fclose(fp); + fp= NULL; + } +#endif + + Sleep(10); + } + else + return ret; + } + return FALSE; +} +#endif + + /* On unix rename deletes to file if it exists */ int my_rename(const char *from, const char *to, myf MyFlags) { int error = 0; @@ -28,8 +82,7 @@ int my_rename(const char *from, const char *to, myf MyFlags) DBUG_PRINT("my",("from %s to %s MyFlags %lu", from, to, MyFlags)); #if defined(__WIN__) - if (!MoveFileEx(from, to, MOVEFILE_COPY_ALLOWED | - MOVEFILE_REPLACE_EXISTING)) + if (!win_rename_with_retries(from, to)) { my_osmaperr(GetLastError()); #elif defined(HAVE_RENAME) diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc index 889f3630cc3..4fc927cfd86 100644 --- a/sql/service_wsrep.cc +++ b/sql/service_wsrep.cc @@ -337,3 +337,26 @@ extern "C" bool wsrep_thd_set_wsrep_aborter(THD *bf_thd, THD *victim_thd) victim_thd->wsrep_aborter = bf_thd->thread_id; return false; } + +extern "C" void wsrep_report_bf_lock_wait(const THD *thd, + unsigned long long trx_id) +{ + if (thd) + { + WSREP_ERROR("Thread %s trx_id: %llu thread: %ld " + "seqno: %lld client_state: %s client_mode: %s transaction_mode: %s " + "applier: %d toi: %d local: %d " + "query: %s", + wsrep_thd_is_BF(thd, false) ? "BF" : "normal", + trx_id, + thd_get_thread_id(thd), + wsrep_thd_trx_seqno(thd), + wsrep_thd_client_state_str(thd), + wsrep_thd_client_mode_str(thd), + wsrep_thd_transaction_state_str(thd), + wsrep_thd_is_applying(thd), + wsrep_thd_is_toi(thd), + wsrep_thd_is_local(thd), + wsrep_thd_query(thd)); + } +} diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic index 42fc0600807..69e57de5c8b 100644 --- a/sql/sql_plugin_services.ic +++ b/sql/sql_plugin_services.ic @@ -174,7 +174,8 @@ static struct wsrep_service_st wsrep_handler = { wsrep_get_debug, wsrep_commit_ordered, wsrep_thd_is_applying, - wsrep_thd_set_wsrep_aborter + wsrep_thd_set_wsrep_aborter, + wsrep_report_bf_lock_wait }; static struct thd_specifics_service_st thd_specifics_handler= diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index 11fd90091f6..c4dbd8c450f 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -145,3 +145,7 @@ my_bool wsrep_thd_is_applying(const THD*) bool wsrep_thd_set_wsrep_aborter(THD*, THD*) { return 0;} + +void wsrep_report_bf_lock_wait(const THD*, + unsigned long long) +{} diff --git a/storage/innobase/fts/fts0config.cc b/storage/innobase/fts/fts0config.cc index 8ae10c2465d..9e2b40911ae 100644 --- a/storage/innobase/fts/fts0config.cc +++ b/storage/innobase/fts/fts0config.cc @@ -148,9 +148,7 @@ fts_config_create_index_param_name( ::strcpy(name, param); name[len] = '_'; - fts_write_object_id(index->id, name + len + 1, - DICT_TF2_FLAG_IS_SET(index->table, - DICT_TF2_FTS_AUX_HEX_NAME)); + fts_write_object_id(index->id, name + len + 1); return(name); } diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 82c0abb809f..74edb8a6db4 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1564,18 +1564,19 @@ fts_rename_aux_tables( return(DB_SUCCESS); } -/****************************************************************//** -Drops the common ancillary tables needed for supporting an FTS index +/** Drops the common ancillary tables needed for supporting an FTS index on the given table. row_mysql_lock_data_dictionary must have been called before this. +@param[in] trx transaction to drop fts common table +@param[in] fts_table table with an FTS index +@param[in] drop_orphan True if the function is used to drop + orphaned table @return DB_SUCCESS or error code */ -static MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t +static dberr_t fts_drop_common_tables( -/*===================*/ - trx_t* trx, /*!< in: transaction */ - fts_table_t* fts_table) /*!< in: table with an FTS - index */ + trx_t* trx, + fts_table_t* fts_table, + bool drop_orphan=false) { ulint i; dberr_t error = DB_SUCCESS; @@ -1593,6 +1594,16 @@ fts_drop_common_tables( if (err != DB_SUCCESS && err != DB_FAIL) { error = err; } + + if (drop_orphan && err == DB_FAIL) { + char* path = fil_make_filepath( + NULL, table_name, IBD, false); + if (path != NULL) { + os_file_delete_if_exists( + innodb_data_file_key, path, NULL); + ut_free(path); + } + } } return(error); @@ -2105,38 +2116,6 @@ fts_create_index_tables(trx_t* trx, const dict_index_t* index, table_id_t id) return(error); } -#if 0 -/******************************************************************//** -Return string representation of state. */ -static -const char* -fts_get_state_str( -/*==============*/ - /* out: string representation of state */ - fts_row_state state) /*!< in: state */ -{ - switch (state) { - case FTS_INSERT: - return("INSERT"); - - case FTS_MODIFY: - return("MODIFY"); - - case FTS_DELETE: - return("DELETE"); - - case FTS_NOTHING: - return("NOTHING"); - - case FTS_INVALID: - return("INVALID"); - - default: - return("UNKNOWN"); - } -} -#endif - /******************************************************************//** Calculate the new state of a row given the existing state and a new event. @return new state of row */ @@ -5692,523 +5671,6 @@ fts_savepoint_rollback( } } -/** Check if a table is an FTS auxiliary table name. -@param[out] table FTS table info -@param[in] name Table name -@param[in] len Length of table name -@return true if the name matches an auxiliary table name pattern */ -static -bool -fts_is_aux_table_name( - fts_aux_table_t* table, - const char* name, - ulint len) -{ - const char* ptr; - char* end; - char my_name[MAX_FULL_NAME_LEN + 1]; - - ut_ad(len <= MAX_FULL_NAME_LEN); - ut_memcpy(my_name, name, len); - my_name[len] = 0; - end = my_name + len; - - ptr = static_cast<const char*>(memchr(my_name, '/', len)); - - if (ptr != NULL) { - /* We will start the match after the '/' */ - ++ptr; - len = ulint(end - ptr); - } - - /* All auxiliary tables are prefixed with "FTS_" and the name - length will be at the very least greater than 20 bytes. */ - if (ptr != NULL && len > 20 && strncmp(ptr, "FTS_", 4) == 0) { - ulint i; - - /* Skip the prefix. */ - ptr += 4; - len -= 4; - - /* Try and read the table id. */ - if (!fts_read_object_id(&table->parent_id, ptr)) { - return(false); - } - - /* Skip the table id. */ - ptr = static_cast<const char*>(memchr(ptr, '_', len)); - - if (ptr == NULL) { - return(false); - } - - /* Skip the underscore. */ - ++ptr; - ut_a(end > ptr); - len = ulint(end - ptr); - - /* First search the common table suffix array. */ - for (i = 0; fts_common_tables[i] != NULL; ++i) { - - if (strncmp(ptr, fts_common_tables[i], len) == 0) { - return(true); - } - } - - /* Could be obsolete common tables. */ - if (strncmp(ptr, "ADDED", len) == 0 - || strncmp(ptr, "STOPWORDS", len) == 0) { - return(true); - } - - /* Try and read the index id. */ - if (!fts_read_object_id(&table->index_id, ptr)) { - return(false); - } - - /* Skip the table id. */ - ptr = static_cast<const char*>(memchr(ptr, '_', len)); - - if (ptr == NULL) { - return(false); - } - - /* Skip the underscore. */ - ++ptr; - ut_a(end > ptr); - len = ulint(end - ptr); - - /* Search the FT index specific array. */ - for (i = 0; i < FTS_NUM_AUX_INDEX; ++i) { - - if (strncmp(ptr, fts_get_suffix(i), len) == 0) { - return(true); - } - } - - /* Other FT index specific table(s). */ - if (strncmp(ptr, "DOC_ID", len) == 0) { - return(true); - } - } - - return(false); -} - -/**********************************************************************//** -Callback function to read a single table ID column. -@return Always return TRUE */ -static -ibool -fts_read_tables( -/*============*/ - void* row, /*!< in: sel_node_t* */ - void* user_arg) /*!< in: pointer to ib_vector_t */ -{ - int i; - fts_aux_table_t*table; - mem_heap_t* heap; - ibool done = FALSE; - ib_vector_t* tables = static_cast<ib_vector_t*>(user_arg); - sel_node_t* sel_node = static_cast<sel_node_t*>(row); - que_node_t* exp = sel_node->select_list; - - /* Must be a heap allocated vector. */ - ut_a(tables->allocator->arg != NULL); - - /* We will use this heap for allocating strings. */ - heap = static_cast<mem_heap_t*>(tables->allocator->arg); - table = static_cast<fts_aux_table_t*>(ib_vector_push(tables, NULL)); - - memset(table, 0x0, sizeof(*table)); - - /* Iterate over the columns and read the values. */ - for (i = 0; exp && !done; exp = que_node_get_next(exp), ++i) { - - dfield_t* dfield = que_node_get_val(exp); - void* data = dfield_get_data(dfield); - ulint len = dfield_get_len(dfield); - - ut_a(len != UNIV_SQL_NULL); - - /* Note: The column numbers below must match the SELECT */ - switch (i) { - case 0: /* NAME */ - - if (!fts_is_aux_table_name( - table, static_cast<const char*>(data), len)) { - ib_vector_pop(tables); - done = TRUE; - break; - } - - table->name = static_cast<char*>( - mem_heap_alloc(heap, len + 1)); - memcpy(table->name, data, len); - table->name[len] = 0; - break; - - case 1: /* ID */ - ut_a(len == 8); - table->id = mach_read_from_8( - static_cast<const byte*>(data)); - break; - - default: - ut_error; - } - } - - return(TRUE); -} - -/******************************************************************//** -Callback that sets a hex formatted FTS table's flags2 in -SYS_TABLES. The flags is stored in MIX_LEN column. -@return FALSE if all OK */ -static -ibool -fts_set_hex_format( -/*===============*/ - void* row, /*!< in: sel_node_t* */ - void* user_arg) /*!< in: bool set/unset flag */ -{ - sel_node_t* node = static_cast<sel_node_t*>(row); - dfield_t* dfield = que_node_get_val(node->select_list); - - ut_ad(dtype_get_mtype(dfield_get_type(dfield)) == DATA_INT); - ut_ad(dfield_get_len(dfield) == sizeof(ib_uint32_t)); - /* There should be at most one matching record. So the value - must be the default value. */ - ut_ad(mach_read_from_4(static_cast<byte*>(user_arg)) - == ULINT32_UNDEFINED); - - ulint flags2 = mach_read_from_4( - static_cast<byte*>(dfield_get_data(dfield))); - - flags2 |= DICT_TF2_FTS_AUX_HEX_NAME; - - mach_write_to_4(static_cast<byte*>(user_arg), flags2); - - return(FALSE); -} - -/*****************************************************************//** -Update the DICT_TF2_FTS_AUX_HEX_NAME flag in SYS_TABLES. -@return DB_SUCCESS or error code. */ -static -dberr_t -fts_update_hex_format_flag( -/*=======================*/ - trx_t* trx, /*!< in/out: transaction that - covers the update */ - table_id_t table_id, /*!< in: Table for which we want - to set the root table->flags2 */ - bool dict_locked) /*!< in: set to true if the - caller already owns the - dict_sys_t::mutex. */ -{ - pars_info_t* info; - ib_uint32_t flags2; - - static const char sql[] = - "PROCEDURE UPDATE_HEX_FORMAT_FLAG() IS\n" - "DECLARE FUNCTION my_func;\n" - "DECLARE CURSOR c IS\n" - " SELECT MIX_LEN" - " FROM SYS_TABLES" - " WHERE ID = :table_id FOR UPDATE;" - "\n" - "BEGIN\n" - "OPEN c;\n" - "WHILE 1 = 1 LOOP\n" - " FETCH c INTO my_func();\n" - " IF c % NOTFOUND THEN\n" - " EXIT;\n" - " END IF;\n" - "END LOOP;\n" - "UPDATE SYS_TABLES" - " SET MIX_LEN = :flags2" - " WHERE ID = :table_id;\n" - "CLOSE c;\n" - "END;\n"; - - flags2 = ULINT32_UNDEFINED; - - info = pars_info_create(); - - pars_info_add_ull_literal(info, "table_id", table_id); - pars_info_bind_int4_literal(info, "flags2", &flags2); - - pars_info_bind_function( - info, "my_func", fts_set_hex_format, &flags2); - - if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) { - trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); - } - - dberr_t err = que_eval_sql(info, sql, !dict_locked, trx); - - ut_a(flags2 != ULINT32_UNDEFINED); - - return(err); -} - -/*********************************************************************//** -Rename an aux table to HEX format. It's called when "%016llu" is used -to format an object id in table name, which only happens in Windows. */ -static MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t -fts_rename_one_aux_table_to_hex_format( -/*===================================*/ - trx_t* trx, /*!< in: transaction */ - const fts_aux_table_t* aux_table, /*!< in: table info */ - const dict_table_t* parent_table) /*!< in: parent table name */ -{ - const char* ptr; - fts_table_t fts_table; - char new_name[MAX_FULL_NAME_LEN]; - dberr_t error; - - ptr = strchr(aux_table->name, '/'); - ut_a(ptr != NULL); - ++ptr; - /* Skip "FTS_", table id and underscore */ - for (ulint i = 0; i < 2; ++i) { - ptr = strchr(ptr, '_'); - ut_a(ptr != NULL); - ++ptr; - } - - fts_table.suffix = NULL; - if (aux_table->index_id == 0) { - fts_table.type = FTS_COMMON_TABLE; - - for (ulint i = 0; fts_common_tables[i] != NULL; ++i) { - if (strcmp(ptr, fts_common_tables[i]) == 0) { - fts_table.suffix = fts_common_tables[i]; - break; - } - } - } else { - fts_table.type = FTS_INDEX_TABLE; - - /* Skip index id and underscore */ - ptr = strchr(ptr, '_'); - ut_a(ptr != NULL); - ++ptr; - - for (ulint i = 0; fts_index_selector[i].value; ++i) { - if (strcmp(ptr, fts_get_suffix(i)) == 0) { - fts_table.suffix = fts_get_suffix(i); - break; - } - } - } - - ut_a(fts_table.suffix != NULL); - - fts_table.table_id = aux_table->parent_id; - fts_table.index_id = aux_table->index_id; - fts_table.table = parent_table; - - fts_get_table_name(&fts_table, new_name); - ut_ad(strcmp(new_name, aux_table->name) != 0); - - if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) { - trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); - } - - error = row_rename_table_for_mysql(aux_table->name, new_name, trx, - false, false); - - if (error != DB_SUCCESS) { - ib::warn() << "Failed to rename aux table '" - << aux_table->name << "' to new format '" - << new_name << "'."; - } else { - ib::info() << "Renamed aux table '" << aux_table->name - << "' to '" << new_name << "'."; - } - - return(error); -} - -/**********************************************************************//** -Rename all aux tables of a parent table to HEX format. Also set aux tables' -flags2 and parent table's flags2 with DICT_TF2_FTS_AUX_HEX_NAME. -It's called when "%016llu" is used to format an object id in table name, -which only happens in Windows. -Note the ids in tables are correct but the names are old ambiguous ones. - -This function should make sure that either all the parent table and aux tables -are set DICT_TF2_FTS_AUX_HEX_NAME with flags2 or none of them are set */ -static MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t -fts_rename_aux_tables_to_hex_format_low( -/*====================================*/ - trx_t* trx, /*!< in: transaction */ - dict_table_t* parent_table, /*!< in: parent table */ - ib_vector_t* tables) /*!< in: aux tables to rename. */ -{ - dberr_t error; - ulint count; - - ut_ad(!DICT_TF2_FLAG_IS_SET(parent_table, DICT_TF2_FTS_AUX_HEX_NAME)); - ut_ad(!ib_vector_is_empty(tables)); - - error = fts_update_hex_format_flag(trx, parent_table->id, true); - - if (error != DB_SUCCESS) { - ib::warn() << "Setting parent table " << parent_table->name - << " to hex format failed."; - fts_sql_rollback(trx); - return(error); - } - - DICT_TF2_FLAG_SET(parent_table, DICT_TF2_FTS_AUX_HEX_NAME); - - for (count = 0; count < ib_vector_size(tables); ++count) { - dict_table_t* table; - fts_aux_table_t* aux_table; - - aux_table = static_cast<fts_aux_table_t*>( - ib_vector_get(tables, count)); - - table = dict_table_open_on_id(aux_table->id, TRUE, - DICT_TABLE_OP_NORMAL); - - ut_ad(table != NULL); - ut_ad(!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_AUX_HEX_NAME)); - - /* Set HEX_NAME flag here to make sure we can get correct - new table name in following function */ - DICT_TF2_FLAG_SET(table, DICT_TF2_FTS_AUX_HEX_NAME); - error = fts_rename_one_aux_table_to_hex_format(trx, - aux_table, parent_table); - /* We will rollback the trx if the error != DB_SUCCESS, - so setting the flag here is the same with setting it in - row_rename_table_for_mysql */ - DBUG_EXECUTE_IF("rename_aux_table_fail", error = DB_ERROR;); - - if (error != DB_SUCCESS) { - dict_table_close(table, TRUE, FALSE); - - ib::warn() << "Failed to rename one aux table " - << aux_table->name << ". Will revert" - " all successful rename operations."; - - fts_sql_rollback(trx); - break; - } - - error = fts_update_hex_format_flag(trx, aux_table->id, true); - dict_table_close(table, TRUE, FALSE); - - if (error != DB_SUCCESS) { - ib::warn() << "Setting aux table " << aux_table->name - << " to hex format failed."; - - fts_sql_rollback(trx); - break; - } - } - - if (error != DB_SUCCESS) { - ut_ad(count != ib_vector_size(tables)); - - /* If rename fails, thr trx would be rolled back, we can't - use it any more, we'll start a new background trx to do - the reverting. */ - - ut_ad(!trx_is_started(trx)); - - bool not_rename = false; - - /* Try to revert those succesful rename operations - in order to revert the ibd file rename. */ - for (ulint i = 0; i <= count; ++i) { - dict_table_t* table; - fts_aux_table_t* aux_table; - trx_t* trx_bg; - dberr_t err; - - aux_table = static_cast<fts_aux_table_t*>( - ib_vector_get(tables, i)); - - table = dict_table_open_on_id(aux_table->id, TRUE, - DICT_TABLE_OP_NORMAL); - ut_ad(table != NULL); - - if (not_rename) { - DICT_TF2_FLAG_UNSET(table, - DICT_TF2_FTS_AUX_HEX_NAME); - } - - if (!DICT_TF2_FLAG_IS_SET(table, - DICT_TF2_FTS_AUX_HEX_NAME)) { - dict_table_close(table, TRUE, FALSE); - continue; - } - - trx_bg = trx_create(); - trx_bg->op_info = "Revert half done rename"; - trx_bg->dict_operation_lock_mode = RW_X_LATCH; - trx_start_for_ddl(trx_bg, TRX_DICT_OP_TABLE); - - DICT_TF2_FLAG_UNSET(table, DICT_TF2_FTS_AUX_HEX_NAME); - err = row_rename_table_for_mysql(table->name.m_name, - aux_table->name, - trx_bg, false, false); - - trx_bg->dict_operation_lock_mode = 0; - dict_table_close(table, TRUE, FALSE); - - if (err != DB_SUCCESS) { - ib::warn() << "Failed to revert table " - << table->name << ". Please revert" - " manually."; - fts_sql_rollback(trx_bg); - /* Continue to clear aux tables' flags2 */ - not_rename = true; - } else { - fts_sql_commit(trx_bg); - } - trx_bg->free(); - } - - DICT_TF2_FLAG_UNSET(parent_table, DICT_TF2_FTS_AUX_HEX_NAME); - } - - return(error); -} - -/**********************************************************************//** -Convert an id, which is actually a decimal number but was regard as a HEX -from a string, to its real value. */ -static -ib_id_t -fts_fake_hex_to_dec( -/*================*/ - ib_id_t id) /*!< in: number to convert */ -{ - ib_id_t dec_id = 0; - char tmp_id[FTS_AUX_MIN_TABLE_ID_LENGTH]; - -#ifdef UNIV_DEBUG - int ret = -#endif /* UNIV_DEBUG */ - sprintf(tmp_id, UINT64PFx, id); - ut_ad(ret == 16); -#ifdef UNIV_DEBUG - ret = -#endif /* UNIV_DEBUG */ - sscanf(tmp_id, "%016" UINT64scan, &dec_id); - ut_ad(ret == 1); - - return dec_id; -} - /*********************************************************************//** Compare two fts_aux_table_t parent_ids. @return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ @@ -6225,780 +5687,245 @@ fts_check_aux_table_parent_id_cmp( return static_cast<int>(fa1->parent_id - fa2->parent_id); } -/** Mark all the fts index associated with the parent table as corrupted. -@param[in] trx transaction -@param[in, out] parent_table fts index associated with this parent table - will be marked as corrupted. */ -static -void -fts_parent_all_index_set_corrupt( - trx_t* trx, - dict_table_t* parent_table) -{ - fts_t* fts = parent_table->fts; - - if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) { - trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); - } - - for (ulint j = 0; j < ib_vector_size(fts->indexes); j++) { - dict_index_t* index = static_cast<dict_index_t*>( - ib_vector_getp_const(fts->indexes, j)); - dict_set_corrupted(index, - trx, "DROP ORPHANED TABLE"); - } -} - -/** Mark the fts index which index id matches the id as corrupted. -@param[in] trx transaction -@param[in] id index id to search -@param[in, out] parent_table parent table to check with all - the index. */ -static -void -fts_set_index_corrupt( - trx_t* trx, - index_id_t id, - dict_table_t* table) -{ - fts_t* fts = table->fts; - - if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) { - trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); - } - - for (ulint j = 0; j < ib_vector_size(fts->indexes); j++) { - dict_index_t* index = static_cast<dict_index_t*>( - ib_vector_getp_const(fts->indexes, j)); - if (index->id == id) { - dict_set_corrupted(index, trx, - "DROP ORPHANED TABLE"); - break; - } - } -} - -/** Check the index for the aux table is corrupted. -@param[in] aux_table auxiliary table -@retval nonzero if index is corrupted, zero for valid index */ -static -ulint -fts_check_corrupt_index( - fts_aux_table_t* aux_table) -{ - dict_table_t* table; - dict_index_t* index; - table = dict_table_open_on_id( - aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL); - - if (table == NULL) { - return(0); - } - - for (index = UT_LIST_GET_FIRST(table->indexes); - index; - index = UT_LIST_GET_NEXT(indexes, index)) { - if (index->id == aux_table->index_id) { - ut_ad(index->type & DICT_FTS); - dict_table_close(table, true, false); - return index->is_corrupted(); - } - } - - dict_table_close(table, true, false); - return(0); -} - -/* Get parent table name if it's a fts aux table -@param[in] aux_table_name aux table name -@param[in] aux_table_len aux table length -@return parent table name, or NULL */ -char* -fts_get_parent_table_name( - const char* aux_table_name, - ulint aux_table_len) -{ - fts_aux_table_t aux_table; - char* parent_table_name = NULL; - - if (fts_is_aux_table_name(&aux_table, aux_table_name, aux_table_len)) { - dict_table_t* parent_table; - - parent_table = dict_table_open_on_id( - aux_table.parent_id, TRUE, DICT_TABLE_OP_NORMAL); - - if (parent_table != NULL) { - parent_table_name = mem_strdupl( - parent_table->name.m_name, - strlen(parent_table->name.m_name)); - - dict_table_close(parent_table, TRUE, FALSE); - } - } - - return(parent_table_name); -} - -/** Check the validity of the parent table. -@param[in] aux_table auxiliary table -@return true if it is a valid table or false if it is not */ -static -bool -fts_valid_parent_table( - const fts_aux_table_t* aux_table) -{ - dict_table_t* parent_table; - bool valid = false; - - parent_table = dict_table_open_on_id( - aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL); - - if (parent_table != NULL && parent_table->fts != NULL) { - if (aux_table->index_id == 0) { - valid = true; - } else { - index_id_t id = aux_table->index_id; - dict_index_t* index; - - /* Search for the FT index in the table's list. */ - for (index = UT_LIST_GET_FIRST(parent_table->indexes); - index; - index = UT_LIST_GET_NEXT(indexes, index)) { - if (index->id == id) { - valid = true; - break; - } - - } - } - } - - if (parent_table) { - dict_table_close(parent_table, TRUE, FALSE); - } - - return(valid); -} - -/** Try to rename all aux tables of the specified parent table. -@param[in] aux_tables aux_tables to be renamed -@param[in] parent_table parent table of all aux - tables stored in tables. */ -static -void -fts_rename_aux_tables_to_hex_format( - ib_vector_t* aux_tables, - dict_table_t* parent_table) -{ - dberr_t err; - trx_t* trx_rename = trx_create(); - trx_rename->op_info = "Rename aux tables to hex format"; - trx_rename->dict_operation_lock_mode = RW_X_LATCH; - trx_start_for_ddl(trx_rename, TRX_DICT_OP_TABLE); - - err = fts_rename_aux_tables_to_hex_format_low(trx_rename, - parent_table, aux_tables); - - trx_rename->dict_operation_lock_mode = 0; - - if (err != DB_SUCCESS) { - - ib::warn() << "Rollback operations on all aux tables of " - "table "<< parent_table->name << ". All the fts index " - "associated with the table are marked as corrupted. " - "Please rebuild the index again."; - - /* Corrupting the fts index related to parent table. */ - trx_t* trx_corrupt; - trx_corrupt = trx_create(); - trx_corrupt->dict_operation_lock_mode = RW_X_LATCH; - trx_start_for_ddl(trx_corrupt, TRX_DICT_OP_TABLE); - fts_parent_all_index_set_corrupt(trx_corrupt, parent_table); - trx_corrupt->dict_operation_lock_mode = 0; - fts_sql_commit(trx_corrupt); - trx_corrupt->free(); - } else { - fts_sql_commit(trx_rename); - } - - trx_rename->free(); - ib_vector_reset(aux_tables); -} - -/** Set the hex format flag for the parent table. -@param[in, out] parent_table parent table -@param[in] trx transaction */ -static -void -fts_set_parent_hex_format_flag( - dict_table_t* parent_table, - trx_t* trx) -{ - if (!DICT_TF2_FLAG_IS_SET(parent_table, - DICT_TF2_FTS_AUX_HEX_NAME)) { - DBUG_EXECUTE_IF("parent_table_flag_fail", DBUG_SUICIDE();); - - dberr_t err = fts_update_hex_format_flag( - trx, parent_table->id, true); - - if (err != DB_SUCCESS) { - ib::fatal() << "Setting parent table " - << parent_table->name - << "to hex format failed. Please try " - << "to restart the server again, if it " - << "doesn't work, the system tables " - << "might be corrupted."; - } else { - DICT_TF2_FLAG_SET( - parent_table, DICT_TF2_FTS_AUX_HEX_NAME); - } - } -} - -/** Drop the obsolete auxilary table. -@param[in] tables tables to be dropped. */ -static -void -fts_drop_obsolete_aux_table_from_vector( - ib_vector_t* tables) -{ - dberr_t err; - - for (ulint count = 0; count < ib_vector_size(tables); - ++count) { - - fts_aux_table_t* aux_drop_table; - aux_drop_table = static_cast<fts_aux_table_t*>( - ib_vector_get(tables, count)); - trx_t* trx_drop = trx_create(); - trx_drop->op_info = "Drop obsolete aux tables"; - trx_drop->dict_operation_lock_mode = RW_X_LATCH; - trx_start_for_ddl(trx_drop, TRX_DICT_OP_TABLE); - - err = row_drop_table_for_mysql( - aux_drop_table->name, trx_drop, - SQLCOM_DROP_TABLE, true); - - trx_drop->dict_operation_lock_mode = 0; - - if (err != DB_SUCCESS) { - /* We don't need to worry about the - failure, since server would try to - drop it on next restart, even if - the table was broken. */ - ib::warn() << "Failed to drop obsolete aux table " - << aux_drop_table->name << ", which is " - << "harmless. will try to drop it on next " - << "restart."; - - fts_sql_rollback(trx_drop); - } else { - ib::info() << "Dropped obsolete aux" - " table '" << aux_drop_table->name - << "'."; - - fts_sql_commit(trx_drop); - } - - trx_drop->free(); - } -} - -/** Drop all the auxiliary table present in the vector. -@param[in] trx transaction -@param[in] tables tables to be dropped */ -static -void -fts_drop_aux_table_from_vector( - trx_t* trx, - ib_vector_t* tables) -{ - for (ulint count = 0; count < ib_vector_size(tables); - ++count) { - fts_aux_table_t* aux_drop_table; - aux_drop_table = static_cast<fts_aux_table_t*>( - ib_vector_get(tables, count)); - - /* Check for the validity of the parent table */ - if (!fts_valid_parent_table(aux_drop_table)) { +bool fts_check_aux_table(const char *name, + table_id_t *table_id, + index_id_t *index_id) +{ + ulint len= strlen(name); + const char* ptr; + const char* end= name + len; - ib::warn() << "Parent table of FTS auxiliary table " - << aux_drop_table->name << " not found."; + ut_ad(len <= MAX_FULL_NAME_LEN); + ptr= static_cast<const char*>(memchr(name, '/', len)); + + if (ptr != NULL) + { + /* We will start the match after the '/' */ + ++ptr; + len = end - ptr; + } + + /* All auxiliary tables are prefixed with "FTS_" and the name + length will be at the very least greater than 20 bytes. */ + if (ptr && len > 20 && !memcmp(ptr, "FTS_", 4)) + { + /* Skip the prefix. */ + ptr+= 4; + len-= 4; + + const char *table_id_ptr= ptr; + /* Skip the table id. */ + ptr= static_cast<const char*>(memchr(ptr, '_', len)); + + if (!ptr) + return false; + + /* Skip the underscore. */ + ++ptr; + ut_ad(end > ptr); + len= end - ptr; + + sscanf(table_id_ptr, UINT64PFx, table_id); + /* First search the common table suffix array. */ + for (ulint i = 0; fts_common_tables[i]; ++i) + { + if (!strncmp(ptr, fts_common_tables[i], len)) + return true; + } + + /* Could be obsolete common tables. */ + if ((len == 5 && !memcmp(ptr, "ADDED", len)) || + (len == 9 && !memcmp(ptr, "STOPWORDS", len))) + return true; + + const char* index_id_ptr= ptr; + /* Skip the index id. */ + ptr= static_cast<const char*>(memchr(ptr, '_', len)); + if (!ptr) + return false; + + sscanf(index_id_ptr, UINT64PFx, index_id); + + /* Skip the underscore. */ + ++ptr; + ut_a(end > ptr); + len= end - ptr; + + if (len > 7) + return false; + + /* Search the FT index specific array. */ + for (ulint i = 0; i < FTS_NUM_AUX_INDEX; ++i) + { + if (!memcmp(ptr, "INDEX_", len - 1)) + return true; + } + + /* Other FT index specific table(s). */ + if (len == 6 && !memcmp(ptr, "DOC_ID", len)) + return true; + } + + return false; +} + +typedef std::pair<table_id_t,index_id_t> fts_aux_id; +typedef std::set<fts_aux_id> fts_space_set_t; + +/** Iterate over all the spaces in the space list and fetch the +fts parent table id and index id. +@param[in,out] fts_space_set store the list of tablespace id and + index id */ +static void fil_get_fts_spaces(fts_space_set_t& fts_space_set) +{ + mutex_enter(&fil_system.mutex); + + for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list); + space; + space= UT_LIST_GET_NEXT(space_list, space)) + { + index_id_t index_id= 0; + table_id_t table_id= 0; + + if (space->purpose == FIL_TYPE_TABLESPACE + && fts_check_aux_table(space->name, &table_id, &index_id)) + fts_space_set.insert(std::make_pair(table_id, index_id)); + } + + mutex_exit(&fil_system.mutex); +} + +/** Check whether the parent table id and index id of fts auxilary +tables with SYS_INDEXES. If it exists then we can safely ignore the +fts table from orphaned tables. +@param[in,out] fts_space_set fts space set contains set of auxiliary + table ids */ +static void fts_check_orphaned_tables(fts_space_set_t& fts_space_set) +{ + btr_pcur_t pcur; + mtr_t mtr; + trx_t* trx = trx_create(); + trx->op_info = "checking fts orphaned tables"; + + row_mysql_lock_data_dictionary(trx); + + mtr.start(); + btr_pcur_open_at_index_side( + true, dict_table_get_first_index(dict_sys.sys_indexes), + BTR_SEARCH_LEAF, &pcur, true, 0, &mtr); + + do + { + const rec_t *rec; + const byte *tbl_field; + const byte *index_field; + ulint len; + + btr_pcur_move_to_next_user_rec(&pcur, &mtr); + if (!btr_pcur_is_on_user_rec(&pcur)) + break; + + rec= btr_pcur_get_rec(&pcur); + if (rec_get_deleted_flag(rec, 0)) + continue; + + tbl_field= rec_get_nth_field_old(rec, 0, &len); + if (len != 8) + continue; + + index_field= rec_get_nth_field_old(rec, 1, &len); + if (len != 8) + continue; + + table_id_t table_id = mach_read_from_8(tbl_field); + index_id_t index_id = mach_read_from_8(index_field); + + fts_space_set_t::iterator it = fts_space_set.find( + fts_aux_id(table_id, index_id)); - dberr_t err = fts_drop_table(trx, aux_drop_table->name); - if (err == DB_FAIL) { + if (it != fts_space_set.end()) + fts_space_set.erase(*it); + else + { + it= fts_space_set.find(fts_aux_id(table_id, 0)); + if (it != fts_space_set.end()) + fts_space_set.erase(*it); + } + } while(!fts_space_set.empty()); + + btr_pcur_close(&pcur); + mtr.commit(); + row_mysql_unlock_data_dictionary(trx); + trx->free(); +} - char* path = fil_make_filepath( - NULL, aux_drop_table->name, IBD, false); - - if (path != NULL) { - os_file_delete_if_exists( - innodb_data_file_key, - path , NULL); - ut_free(path); - } - } - } - } -} - -/**********************************************************************//** -Check and drop all orphaned FTS auxiliary tables, those that don't have -a parent table or FTS index defined on them. -@return DB_SUCCESS or error code */ -static MY_ATTRIBUTE((nonnull)) -void -fts_check_and_drop_orphaned_tables( -/*===============================*/ - trx_t* trx, /*!< in: transaction */ - ib_vector_t* tables) /*!< in: tables to check */ +/** Drop all fts auxilary table for the respective fts_id +@param[in] fts_id fts auxilary table ids */ +static void fts_drop_all_aux_tables(trx_t *trx, fts_table_t *fts_table) { - mem_heap_t* heap; - ib_vector_t* aux_tables_to_rename; - ib_vector_t* invalid_aux_tables; - ib_vector_t* valid_aux_tables; - ib_vector_t* drop_aux_tables; - ib_vector_t* obsolete_aux_tables; - ib_alloc_t* heap_alloc; - - heap = mem_heap_create(1024); - heap_alloc = ib_heap_allocator_create(heap); - - /* We store all aux tables belonging to the same parent table here, - and rename all these tables in a batch mode. */ - aux_tables_to_rename = ib_vector_create(heap_alloc, - sizeof(fts_aux_table_t), 128); - - /* We store all fake auxiliary table and orphaned table here. */ - invalid_aux_tables = ib_vector_create(heap_alloc, - sizeof(fts_aux_table_t), 128); - - /* We store all valid aux tables. We use this to filter the - fake auxiliary table from invalid auxiliary tables. */ - valid_aux_tables = ib_vector_create(heap_alloc, - sizeof(fts_aux_table_t), 128); - - /* We store all auxiliary tables to be dropped. */ - drop_aux_tables = ib_vector_create(heap_alloc, - sizeof(fts_aux_table_t), 128); - - /* We store all obsolete auxiliary tables to be dropped. */ - obsolete_aux_tables = ib_vector_create(heap_alloc, - sizeof(fts_aux_table_t), 128); - - /* Sort by parent_id first, in case rename will fail */ - ib_vector_sort(tables, fts_check_aux_table_parent_id_cmp); - - for (ulint i = 0; i < ib_vector_size(tables); ++i) { - dict_table_t* parent_table; - fts_aux_table_t* aux_table; - bool drop = false; - dict_table_t* table; - fts_aux_table_t* next_aux_table = NULL; - ib_id_t orig_parent_id = 0; - ib_id_t orig_index_id = 0; - bool rename = false; - - aux_table = static_cast<fts_aux_table_t*>( - ib_vector_get(tables, i)); - - table = dict_table_open_on_id( - aux_table->id, TRUE, DICT_TABLE_OP_NORMAL); - orig_parent_id = aux_table->parent_id; - orig_index_id = aux_table->index_id; - - if (table == NULL - || strcmp(table->name.m_name, aux_table->name)) { - - bool fake_aux = false; - - if (table != NULL) { - dict_table_close(table, TRUE, FALSE); - } - - if (i + 1 < ib_vector_size(tables)) { - next_aux_table = static_cast<fts_aux_table_t*>( - ib_vector_get(tables, i + 1)); - } - - /* To know whether aux table is fake fts or - orphan fts table. */ - for (ulint count = 0; - count < ib_vector_size(valid_aux_tables); - count++) { - fts_aux_table_t* valid_aux; - valid_aux = static_cast<fts_aux_table_t*>( - ib_vector_get(valid_aux_tables, count)); - if (strcmp(valid_aux->name, - aux_table->name) == 0) { - fake_aux = true; - break; - } - } - - /* All aux tables of parent table, whose id is - last_parent_id, have been checked, try to rename - them if necessary. */ - if ((next_aux_table == NULL - || orig_parent_id != next_aux_table->parent_id) - && (!ib_vector_is_empty(aux_tables_to_rename))) { - - ib_id_t parent_id = fts_fake_hex_to_dec( - aux_table->parent_id); - - parent_table = dict_table_open_on_id( - parent_id, TRUE, - DICT_TABLE_OP_NORMAL); - - fts_rename_aux_tables_to_hex_format( - aux_tables_to_rename, parent_table); - - dict_table_close(parent_table, TRUE, - FALSE); - } - - /* If the aux table is fake aux table. Skip it. */ - if (!fake_aux) { - ib_vector_push(invalid_aux_tables, aux_table); - } - - continue; - } else if (!DICT_TF2_FLAG_IS_SET(table, - DICT_TF2_FTS_AUX_HEX_NAME)) { - - aux_table->parent_id = fts_fake_hex_to_dec( - aux_table->parent_id); - - if (aux_table->index_id != 0) { - aux_table->index_id = fts_fake_hex_to_dec( - aux_table->index_id); - } - - ut_ad(aux_table->id > aux_table->parent_id); - - /* Check whether parent table id and index id - are stored as decimal format. */ - if (fts_valid_parent_table(aux_table)) { - - parent_table = dict_table_open_on_id( - aux_table->parent_id, true, - DICT_TABLE_OP_NORMAL); - - ut_ad(parent_table != NULL); - ut_ad(parent_table->fts != NULL); - - if (!DICT_TF2_FLAG_IS_SET( - parent_table, - DICT_TF2_FTS_AUX_HEX_NAME)) { - rename = true; - } + char fts_table_name[MAX_FULL_NAME_LEN]; + for (ulint i= 0;i < FTS_NUM_AUX_INDEX; i++) + { + fts_table->suffix= fts_get_suffix(i); + fts_get_table_name(fts_table, fts_table_name, true); + + /* Drop all fts aux and common table */ + dberr_t err= fts_drop_table(trx, fts_table_name); + + if (err == DB_FAIL) + { + char *path= fil_make_filepath(NULL, fts_table_name, IBD, false); + + if (path != NULL) + { + os_file_delete_if_exists(innodb_data_file_key, path , NULL); + ut_free(path); + } + } + } +} + +/** Drop all orphaned FTS auxiliary tables, those that don't have +a parent table or FTS index defined on them. */ +void fts_drop_orphaned_tables() +{ + fts_space_set_t fts_space_set; + fil_get_fts_spaces(fts_space_set); - dict_table_close(parent_table, TRUE, FALSE); - } - - if (!rename) { - /* Reassign the original value of - aux table if it is not in decimal format */ - aux_table->parent_id = orig_parent_id; - aux_table->index_id = orig_index_id; - } - } - - if (table != NULL) { - dict_table_close(table, TRUE, FALSE); - } - - if (!rename) { - /* Check the validity of the parent table. */ - if (!fts_valid_parent_table(aux_table)) { - drop = true; - } - } - - /* Filter out the fake aux table by comparing with the - current valid auxiliary table name. */ - for (ulint count = 0; - count < ib_vector_size(invalid_aux_tables); count++) { - fts_aux_table_t* invalid_aux; - invalid_aux = static_cast<fts_aux_table_t*>( - ib_vector_get(invalid_aux_tables, count)); - if (strcmp(invalid_aux->name, aux_table->name) == 0) { - ib_vector_remove( - invalid_aux_tables, - *reinterpret_cast<void**>(invalid_aux)); - break; - } - } - - ib_vector_push(valid_aux_tables, aux_table); - - /* If the index associated with aux table is corrupted, - skip it. */ - if (fts_check_corrupt_index(aux_table) > 0) { - - if (i + 1 < ib_vector_size(tables)) { - next_aux_table = static_cast<fts_aux_table_t*>( - ib_vector_get(tables, i + 1)); - } - - if (next_aux_table == NULL - || orig_parent_id != next_aux_table->parent_id) { - - parent_table = dict_table_open_on_id( - aux_table->parent_id, TRUE, - DICT_TABLE_OP_NORMAL); - - if (!ib_vector_is_empty(aux_tables_to_rename)) { - fts_rename_aux_tables_to_hex_format( - aux_tables_to_rename, parent_table); - } else { - fts_set_parent_hex_format_flag( - parent_table, trx); - } - - dict_table_close(parent_table, TRUE, FALSE); - } - - continue; - } - - parent_table = dict_table_open_on_id( - aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL); - - if (drop) { - ib_vector_push(drop_aux_tables, aux_table); - } else { - if (FTS_IS_OBSOLETE_AUX_TABLE(aux_table->name)) { - ib_vector_push(obsolete_aux_tables, aux_table); - continue; - } - } - - /* If the aux table is in decimal format, we should - rename it, so push it to aux_tables_to_rename */ - if (!drop && rename) { - bool rename_table = true; - for (ulint count = 0; - count < ib_vector_size(aux_tables_to_rename); - count++) { - fts_aux_table_t* rename_aux = - static_cast<fts_aux_table_t*>( - ib_vector_get(aux_tables_to_rename, - count)); - if (strcmp(rename_aux->name, - aux_table->name) == 0) { - rename_table = false; - break; - } - } - - if (rename_table) { - ib_vector_push(aux_tables_to_rename, - aux_table); - } - } - - if (i + 1 < ib_vector_size(tables)) { - next_aux_table = static_cast<fts_aux_table_t*>( - ib_vector_get(tables, i + 1)); - } - - if ((next_aux_table == NULL - || orig_parent_id != next_aux_table->parent_id) - && !ib_vector_is_empty(aux_tables_to_rename)) { - - ut_ad(rename); - ut_ad(!DICT_TF2_FLAG_IS_SET( - parent_table, DICT_TF2_FTS_AUX_HEX_NAME)); - - fts_rename_aux_tables_to_hex_format( - aux_tables_to_rename,parent_table); - } - - /* The IDs are already in correct hex format. */ - if (!drop && !rename) { - dict_table_t* table; - - table = dict_table_open_on_id( - aux_table->id, TRUE, DICT_TABLE_OP_NORMAL); - - if (table != NULL - && strcmp(table->name.m_name, aux_table->name)) { - dict_table_close(table, TRUE, FALSE); - table = NULL; - } - - if (table != NULL - && !DICT_TF2_FLAG_IS_SET( - table, - DICT_TF2_FTS_AUX_HEX_NAME)) { - - DBUG_EXECUTE_IF("aux_table_flag_fail", - ib::warn() << "Setting aux table " - << table->name << " to hex " - "format failed."; - fts_set_index_corrupt( - trx, aux_table->index_id, - parent_table); - goto table_exit;); - - dberr_t err = fts_update_hex_format_flag( - trx, table->id, true); - - if (err != DB_SUCCESS) { - ib::warn() << "Setting aux table " - << table->name << " to hex " - "format failed."; - - fts_set_index_corrupt( - trx, aux_table->index_id, - parent_table); - } else { - DICT_TF2_FLAG_SET(table, - DICT_TF2_FTS_AUX_HEX_NAME); - } - } -#ifndef DBUG_OFF -table_exit: -#endif /* !DBUG_OFF */ - - if (table != NULL) { - dict_table_close(table, TRUE, FALSE); - } - - ut_ad(parent_table != NULL); - - fts_set_parent_hex_format_flag( - parent_table, trx); - } - - if (parent_table != NULL) { - dict_table_close(parent_table, TRUE, FALSE); - } - } - - fts_drop_aux_table_from_vector(trx, invalid_aux_tables); - fts_drop_aux_table_from_vector(trx, drop_aux_tables); - fts_sql_commit(trx); - - fts_drop_obsolete_aux_table_from_vector(obsolete_aux_tables); - - /* Free the memory allocated at the beginning */ - if (heap != NULL) { - mem_heap_free(heap); - } -} - -/**********************************************************************//** -Drop all orphaned FTS auxiliary tables, those that don't have a parent -table or FTS index defined on them. */ -void -fts_drop_orphaned_tables(void) -/*==========================*/ -{ - trx_t* trx; - pars_info_t* info; - mem_heap_t* heap; - que_t* graph; - ib_vector_t* tables; - ib_alloc_t* heap_alloc; - - heap = mem_heap_create(1024); - heap_alloc = ib_heap_allocator_create(heap); - - /* We store the table ids of all the FTS indexes that were found. */ - tables = ib_vector_create(heap_alloc, sizeof(fts_aux_table_t), 128); - - /* Get the list of all known .ibd files and check for orphaned - FTS auxiliary files in that list. We need to remove them because - users can't map them back to table names and this will create - unnecessary clutter. */ - - mutex_enter(&fil_system.mutex); - - for (fil_space_t* space = UT_LIST_GET_FIRST(fil_system.space_list); - space != NULL; - space = UT_LIST_GET_NEXT(space_list, space)) { - - if (space->purpose != FIL_TYPE_TABLESPACE) { - continue; - } - - fts_aux_table_t fts_aux_table; - memset(&fts_aux_table, 0x0, sizeof fts_aux_table); - - size_t len = strlen(space->name); - - if (!fts_is_aux_table_name(&fts_aux_table, space->name, len)) { - continue; - } - - fts_aux_table.id = space->id; - fts_aux_table.name = mem_heap_strdupl(heap, space->name, len); - ib_vector_push(tables, &fts_aux_table); - } - - mutex_exit(&fil_system.mutex); - - trx = trx_create(); - trx->op_info = "dropping orphaned FTS tables"; - row_mysql_lock_data_dictionary(trx); - - info = pars_info_create(); - - pars_info_bind_function(info, "my_func", fts_read_tables, tables); - - graph = fts_parse_sql_no_dict_lock( - info, - "DECLARE FUNCTION my_func;\n" - "DECLARE CURSOR c IS" - " SELECT NAME, ID" - " FROM SYS_TABLES;\n" - "BEGIN\n" - "\n" - "OPEN c;\n" - "WHILE 1 = 1 LOOP\n" - " FETCH c INTO my_func();\n" - " IF c % NOTFOUND THEN\n" - " EXIT;\n" - " END IF;\n" - "END LOOP;\n" - "CLOSE c;"); - - for (;;) { - dberr_t error = fts_eval_sql(trx, graph); - - if (UNIV_LIKELY(error == DB_SUCCESS)) { - fts_check_and_drop_orphaned_tables(trx, tables); - break; /* Exit the loop. */ - } else { - ib_vector_reset(tables); - - fts_sql_rollback(trx); - - if (error == DB_LOCK_WAIT_TIMEOUT) { - ib::warn() << "lock wait timeout reading" - " SYS_TABLES. Retrying!"; - - trx->error_state = DB_SUCCESS; - } else { - ib::error() << "(" << error - << ") while reading SYS_TABLES."; - - break; /* Exit the loop. */ - } - } - } - - que_graph_free(graph); + if (fts_space_set.empty()) + return; - row_mysql_unlock_data_dictionary(trx); + fts_check_orphaned_tables(fts_space_set); - trx->free(); + if (fts_space_set.empty()) + return; - if (heap != NULL) { - mem_heap_free(heap); - } + trx_t* trx= trx_create(); + trx->op_info= "Drop orphaned aux FTS tables"; + row_mysql_lock_data_dictionary(trx); + + for (fts_space_set_t::iterator it = fts_space_set.begin(); + it != fts_space_set.end(); it++) + { + fts_table_t fts_table; + dict_table_t *table= dict_table_open_on_id(it->first, TRUE, + DICT_TABLE_OP_NORMAL); + if (!table) + continue; + + FTS_INIT_FTS_TABLE(&fts_table, NULL, FTS_COMMON_TABLE, table); + fts_drop_common_tables(trx, &fts_table, true); + + fts_table.type= FTS_INDEX_TABLE; + fts_table.index_id= it->second; + fts_drop_all_aux_tables(trx, &fts_table); + + dict_table_close(table, true, false); + } + trx_commit_for_mysql(trx); + row_mysql_unlock_data_dictionary(trx); + trx->dict_operation_lock_mode= 0; + trx->free(); } /**********************************************************************//** diff --git a/storage/innobase/fts/fts0sql.cc b/storage/innobase/fts/fts0sql.cc index 6873df102bf..edd3a13819e 100644 --- a/storage/innobase/fts/fts0sql.cc +++ b/storage/innobase/fts/fts0sql.cc @@ -55,28 +55,23 @@ fts_get_table_id( long */ { int len; - bool hex_name = DICT_TF2_FLAG_IS_SET(fts_table->table, - DICT_TF2_FTS_AUX_HEX_NAME); ut_a(fts_table->table != NULL); switch (fts_table->type) { case FTS_COMMON_TABLE: - len = fts_write_object_id(fts_table->table_id, table_id, - hex_name); + len = fts_write_object_id(fts_table->table_id, table_id); break; case FTS_INDEX_TABLE: - len = fts_write_object_id(fts_table->table_id, table_id, - hex_name); + len = fts_write_object_id(fts_table->table_id, table_id); table_id[len] = '_'; ++len; table_id += len; - len += fts_write_object_id(fts_table->index_id, table_id, - hex_name); + len += fts_write_object_id(fts_table->index_id, table_id); break; default: diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index 950d978e073..62a1641d496 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -734,12 +734,9 @@ fts_savepoint_rollback_last_stmt( /*=============================*/ trx_t* trx); /*!< in: transaction */ -/***********************************************************************//** -Drop all orphaned FTS auxiliary tables, those that don't have a parent +/** Drop all orphaned FTS auxiliary tables, those that don't have a parent table or FTS index defined on them. */ -void -fts_drop_orphaned_tables(void); -/*==========================*/ +void fts_drop_orphaned_tables(); /** Run SYNC on the table, i.e., write out data from the cache to the FTS auxiliary INDEX table and clear the cache at the end. @@ -773,15 +770,6 @@ fts_init_doc_id( /*============*/ const dict_table_t* table); /*!< in: table */ -/* Get parent table name if it's a fts aux table -@param[in] aux_table_name aux table name -@param[in] aux_table_len aux table length -@return parent table name, or NULL */ -char* -fts_get_parent_table_name( - const char* aux_table_name, - ulint aux_table_len); - /******************************************************************//** compare two character string according to their charset. */ extern @@ -988,4 +976,14 @@ and there are no new fts index to add. @param[in] trx transaction to drop all fts tables */ void fts_clear_all(dict_table_t *table, trx_t *trx); +/** Check whether the given name is fts auxiliary table +and fetch the parent table id and index id +@param[in] name table name +@param[in,out] table_id parent table id +@param[in,out] index_id index id +@return true if it is auxilary table */ +bool fts_check_aux_table(const char *name, + table_id_t *table_id, + index_id_t *index_id); + #endif /*!< fts0fts.h */ diff --git a/storage/innobase/include/fts0priv.h b/storage/innobase/include/fts0priv.h index e0b0d27bebf..6f00504525f 100644 --- a/storage/innobase/include/fts0priv.h +++ b/storage/innobase/include/fts0priv.h @@ -461,11 +461,7 @@ int fts_write_object_id( /*================*/ ib_id_t id, /*!< in: a table/index id */ - char* str, /*!< in: buffer to write the id to */ - bool hex_format MY_ATTRIBUTE((unused))) - /*!< in: true for fixed hex format, - false for old ambiguous format */ - MY_ATTRIBUTE((nonnull)); + char* str); /*!< in: buffer to write the id to */ /******************************************************************//** Read the table id from the string generated by fts_write_object_id(). @return TRUE if parse successful */ diff --git a/storage/innobase/include/fts0priv.ic b/storage/innobase/include/fts0priv.ic index ed737e520d6..da14cfcb013 100644 --- a/storage/innobase/include/fts0priv.ic +++ b/storage/innobase/include/fts0priv.ic @@ -32,10 +32,7 @@ int fts_write_object_id( /*================*/ ib_id_t id, /* in: a table/index id */ - char* str, /* in: buffer to write the id to */ - bool hex_format MY_ATTRIBUTE((unused))) - /* in: true for fixed hex format, - false for old ambiguous format */ + char* str) /* in: buffer to write the id to */ { #ifdef _WIN32 @@ -60,11 +57,6 @@ fts_write_object_id( #endif /* _WIN32 */ - /* As above, but this is only for those tables failing to rename. */ - if (!hex_format) { - return(sprintf(str, "%016llu", (ulonglong) id)); - } - return(sprintf(str, "%016llx", (ulonglong) id)); } diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index c6de0e606b9..3d18e2e2473 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -637,6 +637,57 @@ lock_rec_get_insert_intention( return(lock->type_mode & LOCK_INSERT_INTENTION); } +#ifdef WITH_WSREP +/** Check if both conflicting lock and other record lock are brute force +(BF). This case is a bug so report lock information and wsrep state. +@param[in] lock_rec1 conflicting waiting record lock or NULL +@param[in] lock_rec2 other waiting record lock +@param[in] trx1 lock_rec1 can be NULL, trx +*/ +static void wsrep_assert_no_bf_bf_wait( + const lock_t* lock_rec1, + const lock_t* lock_rec2, + const trx_t* trx1) +{ + ut_ad(!lock_rec1 || lock_get_type_low(lock_rec1) == LOCK_REC); + ut_ad(lock_get_type_low(lock_rec2) == LOCK_REC); + + if (!trx1->is_wsrep() || !lock_rec2->trx->is_wsrep()) + return; + if (UNIV_LIKELY(!wsrep_thd_is_BF(trx1->mysql_thd, FALSE))) + return; + if (UNIV_LIKELY(!wsrep_thd_is_BF(lock_rec2->trx->mysql_thd, FALSE))) + return; + + mtr_t mtr; + + if (lock_rec1) { + ib::error() << "Waiting lock on table: " + << lock_rec1->index->table->name + << " index: " + << lock_rec1->index->name() + << " that has conflicting lock "; + lock_rec_print(stderr, lock_rec1, mtr); + } + + ib::error() << "Conflicting lock on table: " + << lock_rec2->index->table->name + << " index: " + << lock_rec2->index->name() + << " that has lock "; + lock_rec_print(stderr, lock_rec2, mtr); + + ib::error() << "WSREP state: "; + + wsrep_report_bf_lock_wait(trx1->mysql_thd, + trx1->id); + wsrep_report_bf_lock_wait(lock_rec2->trx->mysql_thd, + lock_rec2->trx->id); + /* BF-BF wait is a bug */ + ut_error; +} +#endif /* WITH_WSREP */ + /*********************************************************************//** Checks if a lock request for a new lock has to wait for request lock2. @return TRUE if new lock has to wait for lock2 to be removed */ @@ -743,72 +794,9 @@ lock_rec_has_to_wait( } #ifdef WITH_WSREP - /* if BF thread is locking and has conflict with another BF - thread, we need to look at trx ordering and lock types */ - if (wsrep_thd_is_BF(trx->mysql_thd, FALSE) - && wsrep_thd_is_BF(lock2->trx->mysql_thd, FALSE)) { - mtr_t mtr; - - if (UNIV_UNLIKELY(wsrep_debug)) { - ib::info() << "BF-BF lock conflict, locking: " - << for_locking; - lock_rec_print(stderr, lock2, mtr); - ib::info() - << " SQL1: " << wsrep_thd_query(trx->mysql_thd) - << " SQL2: " - << wsrep_thd_query(lock2->trx->mysql_thd); - } - - if ((type_mode & LOCK_MODE_MASK) == LOCK_X - && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) { - if (for_locking || UNIV_UNLIKELY(wsrep_debug)) { - /* exclusive lock conflicts are not - accepted */ - ib::info() - << "BF-BF X lock conflict,mode: " - << type_mode - << " supremum: " << lock_is_on_supremum - << "conflicts states: my " - << wsrep_thd_transaction_state_str( - trx->mysql_thd) - << " locked " - << wsrep_thd_transaction_state_str( - lock2->trx->mysql_thd); - lock_rec_print(stderr, lock2, mtr); - ib::info() << " SQL1: " - << wsrep_thd_query(trx->mysql_thd) - << " SQL2: " - << wsrep_thd_query( - lock2->trx->mysql_thd); - - if (for_locking) { - return false; - } - } - } else { - /* if lock2->index->n_uniq <= - lock2->index->n_user_defined_cols - operation is on uniq index - */ - if (wsrep_debug) { - ib::info() - << "BF conflict, modes: " << type_mode - << ":" << lock2->type_mode - << " idx: " << lock2->index->name() - << " table: " - << lock2->index->table->name - << " n_uniq: " << lock2->index->n_uniq - << " n_user: " - << lock2->index->n_user_defined_cols - << " SQL1: " - << wsrep_thd_query(trx->mysql_thd) - << " SQL2: " - << wsrep_thd_query( - lock2->trx->mysql_thd); - } - return false; - } - } + /* There should not be two conflicting locks that are + brute force. If there is it is a bug. */ + wsrep_assert_no_bf_bf_wait(NULL, lock2, trx); #endif /* WITH_WSREP */ return true; @@ -1467,11 +1455,8 @@ lock_rec_create_low( trx_mutex_exit(c_lock->trx); if (UNIV_UNLIKELY(wsrep_debug)) { - ib::info() << "WSREP: c_lock canceled " - << ib::hex(c_lock->trx->id) - << " SQL: " - << wsrep_thd_query( - c_lock->trx->mysql_thd); + wsrep_report_bf_lock_wait(trx->mysql_thd, trx->id); + wsrep_report_bf_lock_wait(c_lock->trx->mysql_thd, c_lock->trx->id); } /* have to bail out here to avoid lock_set_lock... */ @@ -1550,6 +1535,7 @@ lock_rec_insert_by_trx_age( hash_table_t* hash; hash_cell_t* cell; + ut_ad(!in_lock->trx->is_wsrep()); space = in_lock->un_member.rec_lock.space; page_no = in_lock->un_member.rec_lock.page_no; rec_fold = lock_rec_fold(space, page_no); @@ -1817,27 +1803,19 @@ lock_rec_add_to_queue( = lock_rec_other_has_expl_req( mode, block, false, heap_no, trx); #ifdef WITH_WSREP - if (other_lock && trx->is_wsrep() && - !wsrep_thd_is_BF(trx->mysql_thd, FALSE) && - !wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE)) { - - ib::info() << "WSREP BF lock conflict for my lock:\n BF:" << - ((wsrep_thd_is_BF(trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_client_state_str(trx->mysql_thd) << " conflict: " << - wsrep_thd_transaction_state_str(trx->mysql_thd) << " seqno: " << - wsrep_thd_trx_seqno(trx->mysql_thd) << " SQL: " << - wsrep_thd_query(trx->mysql_thd); - trx_t* otrx = other_lock->trx; - ib::info() << "WSREP other lock:\n BF:" << - ((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " << - wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " << - wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " << - wsrep_thd_query(otrx->mysql_thd); - } -#else - ut_a(!other_lock); + if (UNIV_LIKELY_NULL(other_lock) && trx->is_wsrep()) { + /* Only BF transaction may be granted lock + before other conflicting lock request. */ + if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE) + && !wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE)) { + /* If it is not BF, this case is a bug. */ + wsrep_report_bf_lock_wait(trx->mysql_thd, trx->id); + wsrep_report_bf_lock_wait(other_lock->trx->mysql_thd, other_lock->trx->id); + ut_error; + } + } else #endif /* WITH_WSREP */ + ut_ad(!other_lock); } #endif /* UNIV_DEBUG */ @@ -2043,9 +2021,6 @@ lock_rec_has_to_wait_in_queue( hash = lock_hash_get(wait_lock->type_mode); for (lock = lock_rec_get_first_on_page_addr(hash, space, page_no); -#ifdef WITH_WSREP - lock && -#endif lock != wait_lock; lock = lock_rec_get_next_on_page_const(lock)) { const byte* p = (const byte*) &lock[1]; @@ -2053,24 +2028,6 @@ lock_rec_has_to_wait_in_queue( if (heap_no < lock_rec_get_n_bits(lock) && (p[bit_offset] & bit_mask) && lock_has_to_wait(wait_lock, lock)) { -#ifdef WITH_WSREP - if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) && - wsrep_thd_is_BF(lock->trx->mysql_thd, FALSE)) { - - if (UNIV_UNLIKELY(wsrep_debug)) { - mtr_t mtr; - ib::info() << "WSREP: waiting BF trx: " << ib::hex(wait_lock->trx->id) - << " query: " << wsrep_thd_query(wait_lock->trx->mysql_thd); - lock_rec_print(stderr, wait_lock, mtr); - ib::info() << "WSREP: do not wait another BF trx: " << ib::hex(lock->trx->id) - << " query: " << wsrep_thd_query(lock->trx->mysql_thd); - lock_rec_print(stderr, lock, mtr); - } - /* don't wait for another BF lock */ - continue; - } -#endif /* WITH_WSREP */ - return(lock); } } @@ -2186,6 +2143,7 @@ lock_grant_and_move_on_page(ulint rec_fold, ulint space, ulint page_no) lock = previous->hash; } + ut_ad(!lock->trx->is_wsrep()); ut_ad(previous->hash == lock || previous == lock); /* Grant locks if there are no conflicting locks ahead. Move granted locks to the head of the list. */ @@ -2256,11 +2214,18 @@ static void lock_rec_dequeue_from_page(lock_t* in_lock) lock != NULL; lock = lock_rec_get_next_on_page(lock)) { - if (lock_get_wait(lock) - && !lock_rec_has_to_wait_in_queue(lock)) { + if (!lock_get_wait(lock)) { + continue; + } + const lock_t* c = lock_rec_has_to_wait_in_queue(lock); + if (!c) { /* Grant the lock */ ut_ad(lock->trx != in_lock->trx); lock_grant(lock); +#ifdef WITH_WSREP + } else { + wsrep_assert_no_bf_bf_wait(c, lock, c->trx); +#endif /* WITH_WSREP */ } } } else { @@ -3524,11 +3489,8 @@ lock_table_create( ut_list_insert(table->locks, c_lock, lock, TableLockGetNode()); if (UNIV_UNLIKELY(wsrep_debug)) { - ib::info() << "table lock BF conflict for " - << ib::hex(c_lock->trx->id) - << " SQL: " - << wsrep_thd_query( - c_lock->trx->mysql_thd); + wsrep_report_bf_lock_wait(trx->mysql_thd, trx->id); + wsrep_report_bf_lock_wait(c_lock->trx->mysql_thd, c_lock->trx->id); } } else { ut_list_append(table->locks, lock, TableLockGetNode()); @@ -3540,6 +3502,8 @@ lock_table_create( c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; if (UNIV_UNLIKELY(wsrep_debug)) { + wsrep_report_bf_lock_wait(trx->mysql_thd, trx->id); + wsrep_report_bf_lock_wait(c_lock->trx->mysql_thd, c_lock->trx->id); wsrep_print_wait_locks(c_lock); } @@ -3549,14 +3513,6 @@ lock_table_create( lock_cancel_waiting_and_release( c_lock->trx->lock.wait_lock); trx_mutex_enter(trx); - - if (UNIV_UNLIKELY(wsrep_debug)) { - ib::info() << "WSREP: c_lock canceled " - << ib::hex(c_lock->trx->id) - << " SQL: " - << wsrep_thd_query( - c_lock->trx->mysql_thd); - } } trx_mutex_exit(c_lock->trx); @@ -4115,6 +4071,7 @@ lock_grant_and_move_on_rec( } lock = previous->hash; } + ut_ad(!lock->trx->is_wsrep()); /* Grant locks if there are no conflicting locks ahead. Move granted locks to the head of the list. */ for (;lock != NULL;) { @@ -4214,12 +4171,18 @@ released: for (lock = first_lock; lock != NULL; lock = lock_rec_get_next(heap_no, lock)) { - if (lock_get_wait(lock) - && !lock_rec_has_to_wait_in_queue(lock)) { - + if (!lock_get_wait(lock)) { + continue; + } + const lock_t* c = lock_rec_has_to_wait_in_queue(lock); + if (!c) { /* Grant the lock */ ut_ad(trx != lock->trx); lock_grant(lock); +#ifdef WITH_WSREP + } else { + wsrep_assert_no_bf_bf_wait(c, lock, c->trx); +#endif /* WITH_WSREP */ } } } else { @@ -4889,24 +4852,28 @@ func_exit: explicit granted lock. */ #ifdef WITH_WSREP - if (other_lock->trx->is_wsrep()) { - if (!lock_get_wait(other_lock) ) { - ib::info() << "WSREP impl BF lock conflict for my impl lock:\n BF:" << - ((wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_client_state_str(impl_trx->mysql_thd) << " conflict: " << - wsrep_thd_transaction_state_str(impl_trx->mysql_thd) << " seqno: " << - wsrep_thd_trx_seqno(impl_trx->mysql_thd) << " SQL: " << - wsrep_thd_query(impl_trx->mysql_thd); - - trx_t* otrx = other_lock->trx; - - ib::info() << "WSREP other lock:\n BF:" << - ((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " << - wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " << - wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " << - wsrep_thd_query(otrx->mysql_thd); - } + /** Galera record locking rules: + * If there is no other record lock to the same record, we may grant + the lock request. + * If there is other record lock but this requested record lock is + compatible, we may grant the lock request. + * If there is other record lock and it is not compatible with + requested lock, all normal transactions must wait. + * BF (brute force) additional exceptions : + ** If BF already holds record lock for requested record, we may + grant new record lock even if there is conflicting record lock(s) + waiting on a queue. + ** If conflicting transaction holds requested record lock, + we will cancel this record lock and select conflicting transaction + for BF abort or kill victim. + ** If conflicting transaction is waiting for requested record lock + we will cancel this wait and select conflicting transaction + for BF abort or kill victim. + ** There should not be two BF transactions waiting for same record lock + */ + if (other_lock->trx->is_wsrep() && !lock_get_wait(other_lock)) { + wsrep_report_bf_lock_wait(impl_trx->mysql_thd, impl_trx->id); + wsrep_report_bf_lock_wait(other_lock->trx->mysql_thd, other_lock->trx->id); if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, block, heap_no, @@ -4915,9 +4882,11 @@ func_exit: } } else #endif /* WITH_WSREP */ - ut_ad(lock_get_wait(other_lock)); - ut_ad(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, - block, heap_no, impl_trx)); + { + ut_ad(lock_get_wait(other_lock)); + ut_ad(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, + block, heap_no, impl_trx)); + } } mutex_exit(&impl_trx->mutex); @@ -4949,13 +4918,20 @@ func_exit: mode, block, false, heap_no, lock->trx); #ifdef WITH_WSREP - ut_a(!other_lock - || wsrep_thd_is_BF(lock->trx->mysql_thd, FALSE) - || wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE)); - -#else - ut_a(!other_lock); + if (UNIV_UNLIKELY(other_lock && lock->trx->is_wsrep())) { + /* Only BF transaction may be granted + lock before other conflicting lock + request. */ + if (!wsrep_thd_is_BF(lock->trx->mysql_thd, FALSE) + && !wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE)) { + /* If no BF, this case is a bug. */ + wsrep_report_bf_lock_wait(lock->trx->mysql_thd, lock->trx->id); + wsrep_report_bf_lock_wait(other_lock->trx->mysql_thd, other_lock->trx->id); + ut_error; + } + } else #endif /* WITH_WSREP */ + ut_ad(!other_lock); } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) { ut_a(lock_rec_has_to_wait_in_queue(lock)); diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index a57156e3371..9c913b0c9f2 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -908,8 +908,6 @@ row_ins_foreign_fill_virtual( &ext, cascade->heap); n_diff = update->n_fields; - update->n_fields += n_v_fld; - if (index->table->vc_templ == NULL) { /** This can occur when there is a cascading delete or update after restart. */ @@ -942,7 +940,7 @@ row_ins_foreign_fill_virtual( return DB_COMPUTE_VALUE_FAILED; } - upd_field = upd_get_nth_field(update, n_diff); + upd_field = update->fields + n_diff; upd_field->old_v_val = static_cast<dfield_t*>( mem_heap_alloc(cascade->heap, @@ -952,30 +950,27 @@ row_ins_foreign_fill_virtual( upd_field_set_v_field_no(upd_field, i, index); - if (node->is_delete - ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) - : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) { - - dfield_set_null(&upd_field->new_val); - } - - if (!node->is_delete - && (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)) { - - dfield_t* new_vfield = innobase_get_computed_value( - update->old_vrow, col, index, - &vc.heap, update->heap, NULL, thd, - mysql_table, record, NULL, - node->update, foreign); + bool set_null = + node->is_delete + ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) + : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL); - if (new_vfield == NULL) { - return DB_COMPUTE_VALUE_FAILED; - } + dfield_t* new_vfield = innobase_get_computed_value( + update->old_vrow, col, index, + &vc.heap, update->heap, NULL, thd, + mysql_table, record, NULL, + set_null ? update : node->update, foreign); - dfield_copy(&(upd_field->new_val), new_vfield); + if (new_vfield == NULL) { + return DB_COMPUTE_VALUE_FAILED; } - n_diff++; + dfield_copy(&upd_field->new_val, new_vfield); + + if (!dfield_datas_are_binary_equal( + upd_field->old_v_val, + &upd_field->new_val, 0)) + n_diff++; } update->n_fields = n_diff; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 0ad6889e604..a4359b9f7ad 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3931,9 +3931,21 @@ loop: avoid accessing dropped fts aux tables in information scheam when parent table still exists. Note: Drop parent table will drop fts aux tables. */ - char* parent_table_name; - parent_table_name = fts_get_parent_table_name( - table_name, strlen(table_name)); + char* parent_table_name = NULL; + table_id_t table_id; + index_id_t index_id; + + if (fts_check_aux_table( + table_name, &table_id, &index_id)) { + dict_table_t* parent_table = dict_table_open_on_id( + table_id, TRUE, DICT_TABLE_OP_NORMAL); + if (parent_table != NULL) { + parent_table_name = mem_strdupl( + parent_table->name.m_name, + strlen(parent_table->name.m_name)); + dict_table_close(parent_table, TRUE, FALSE); + } + } if (parent_table_name != NULL) { ut_free(table_name); |