diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-09-21 11:04:04 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-09-21 11:04:04 +0300 |
commit | cbcb4ecabbb82a09794d825ca246d64e3d4b2c8c (patch) | |
tree | b8fab11441c9080cbd3574a26c3eee10df58aaed | |
parent | ade782c001affa69df80ed51e807e16198a9fe04 (diff) | |
parent | 69d536a22dc1988e89697c55549fc3c272fbbf2c (diff) | |
download | mariadb-git-cbcb4ecabbb82a09794d825ca246d64e3d4b2c8c.tar.gz |
Merge 10.2 into 10.3
54 files changed, 923 insertions, 1750 deletions
diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index b1a9ea7d835..b3c2834d7aa 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -1200,6 +1200,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; @@ -1210,6 +1211,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} }; @@ -1250,7 +1252,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 a08349cd3cf..e9c3b0fa86a 100644 --- a/include/mysql/service_wsrep.h +++ b/include/mysql/service_wsrep.h @@ -117,6 +117,8 @@ extern struct wsrep_service_st { void (*wsrep_unlock_rollback_func)(); void (*wsrep_set_data_home_dir_func)(const char *data_dir); my_bool (*wsrep_thd_is_applier_func)(MYSQL_THD); + void (*wsrep_report_bf_lock_wait_func)(MYSQL_THD thd, + unsigned long long trx_id); } *wsrep_service; #ifdef MYSQL_DYNAMIC_PLUGIN @@ -165,6 +167,7 @@ extern struct wsrep_service_st { #define wsrep_unlock_rollback() wsrep_service->wsrep_unlock_rollback_func() #define wsrep_set_data_home_dir(A) wsrep_service->wsrep_set_data_home_dir_func(A) #define wsrep_thd_is_applier(T) wsrep_service->wsrep_thd_is_applier_func(T) +#define wsrep_report_bf_lock_wait(T,I) wsrep_service->wsrep_report_bf_lock_wait_func(T,I) #define wsrep_debug get_wsrep_debug() #define wsrep_log_conflicts get_wsrep_log_conflicts() @@ -229,6 +232,8 @@ bool wsrep_thd_ignore_table(THD *thd); void wsrep_unlock_rollback(); void wsrep_set_data_home_dir(const char *data_dir); my_bool wsrep_thd_is_applier(MYSQL_THD thd); +void wsrep_report_bf_lock_wait(THD *thd, + unsigned long long trx_id); #endif #ifdef __cplusplus 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 91f45c93257..00ae490021b 100644 --- a/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result +++ b/mysql-test/suite/galera/r/galera_autoinc_sst_mariabackup.result @@ -2,48 +2,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 8a2a7d0818e..58ed9f057da 100644 --- a/mysql-test/suite/galera/r/galera_wan_restart_ist.result +++ b/mysql-test/suite/galera/r/galera_wan_restart_ist.result @@ -4,11 +4,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); @@ -20,60 +20,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"); @@ -84,5 +102,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 d4d8291ae7d..9c94d7f10d2 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,61 @@ # 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 ---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 +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_2 -# CR_SERVER_LOST ---error 2013,2006 ---reap - -# 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 +SELECT COUNT(*) FROM t1; -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'; - -DROP PROCEDURE p1; +--connection node_1 DROP TABLE t1; CALL mtr.add_suppression("gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); @@ -97,3 +65,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 bcf74142144..4ddf3b2bce6 100644 --- a/mysql-test/suite/galera_3nodes/r/GAL-501.result +++ b/mysql-test/suite/galera_3nodes/r/GAL-501.result @@ -7,11 +7,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 5665ed5f46a..21403542ebe 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_mariabackup.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_mariabackup.result @@ -7,16 +7,16 @@ 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; include/assert_grep.inc [Streaming the backup to joiner at \[::1\]] include/assert_grep.inc [async IST sender starting to serve tcp://\[::1\]:] include/assert_grep.inc [IST receiver addr using tcp://\[::1\]] -include/assert_grep.inc [Prepared IST receiver, listening at: tcp://\[::1\]] +include/assert_grep.inc [, listening at: tcp://\[::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 5a844537327..9a7a2eac18e 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 @@ -7,12 +7,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; @@ -20,4 +20,4 @@ include/assert_grep.inc [Streaming the backup to joiner at \[::1\]] include/assert_grep.inc [async IST sender starting to serve tcp://\[::1\]:] connection node_2; include/assert_grep.inc [IST receiver addr using tcp://\[::1\]] -include/assert_grep.inc [Prepared IST receiver, listening at: tcp://\[::1\]] +include/assert_grep.inc [, listening at: tcp://\[::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 3564dc8c5a1..512bb5c8c78 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_mysqldump.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_mysqldump.result @@ -12,12 +12,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 bcf74142144..4ddf3b2bce6 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ipv6_rsync.result @@ -7,11 +7,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 bcf74142144..4ddf3b2bce6 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 @@ -7,11 +7,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 45b4d63fb4f..8b3211b2b26 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 @@ -2,7 +2,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'] @@ -48,6 +49,7 @@ CALL mtr.add_suppression("Failed to prepare for incremental state transfer"); 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 77991a6d468..b4944fc87da 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 @@ -2,7 +2,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 a36f21630ac..39f514c07bc 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 # Confirm that initial handshake happened over ipv6 @@ -21,7 +22,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 @@ -33,6 +34,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 5ac00fa056b..3861b17557d 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ipv6_mariabackup.cnf @@ -10,18 +10,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] 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 ae489117942..dc3331d1be3 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; @@ -56,6 +56,8 @@ DROP TABLE t1; --let $assert_select = IST receiver addr using tcp://\[::1\] --source include/assert_grep.inc ---let $assert_text = Prepared IST receiver, listening at: tcp://\[::1\] ---let $assert_select = Prepared IST receiver, listening at: tcp://\[::1\] +# The receiver expects IST +--let $assert_count = 1 +--let $assert_text = , listening at: tcp://\[::1\] +--let $assert_select = , listening at: tcp://\[::1\] --source include/assert_grep.inc 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 2c5aae8534d..c88ff99790c 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; @@ -64,8 +64,8 @@ DROP TABLE t1; --let $assert_select = IST receiver addr using tcp://\[::1\] --source include/assert_grep.inc -# There will be only one Prepared IST and in Galera 3 segnos are not printed ---let $assert_count= 1 ---let $assert_text = Prepared IST receiver, listening at: tcp://\[::1\] ---let $assert_select = Prepared IST receiver, listening at: tcp://\[::1\] +# The receiver expects IST +--let $assert_count = 1 +--let $assert_text = , listening at: tcp://\[::1\] +--let $assert_select = , listening at: tcp://\[::1\] --source include/assert_grep.inc 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 c9e08f58950..4904a49c73b 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 @@ -70,7 +70,7 @@ INSERT INTO t1 VALUES (1); --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 b7b6c66e5ad..e0b2e26927c 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 --let $galera_connection_name = node_3 --let $galera_server_number = 3 @@ -14,7 +15,11 @@ --source ../galera/include/auto_increment_offset_save.inc --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); + +--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 @@ -151,10 +156,18 @@ SET SESSION wsrep_on = OFF; --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 --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 --source include/start_mysqld.inc 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 6476c4fe4fa..63eff486ba3 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 8852bfd8e6a..81347ac90d9 100644 --- a/mysql-test/suite/innodb/r/row_format_redundant.result +++ b/mysql-test/suite/innodb/r/row_format_redundant.result @@ -5,8 +5,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'); @@ -72,7 +71,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 ib_buffer_pool ib_logfile0 ib_logfile1 diff --git a/mysql-test/suite/innodb/t/row_format_redundant.test b/mysql-test/suite/innodb/t/row_format_redundant.test index fc72e5c2664..b23093009bb 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/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic index 7c394b57c3e..a97aaed831a 100644 --- a/sql/sql_plugin_services.ic +++ b/sql/sql_plugin_services.ic @@ -186,7 +186,8 @@ static struct wsrep_service_st wsrep_handler = { wsrep_trx_order_before, wsrep_unlock_rollback, wsrep_set_data_home_dir, - wsrep_thd_is_applier + wsrep_thd_is_applier, + 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 1af74035355..2f12b089939 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 SkySQL Ab. +/* Copyright (C) 2014, 2020, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -163,3 +163,7 @@ void wsrep_log(void (*)(const char *, ...), const char *, ...) my_bool wsrep_thd_is_applier(MYSQL_THD thd) { return false; } + +void wsrep_report_bf_lock_wait(MYSQL_THD thd, + unsigned long long id) +{} diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 9515fd550f2..d00183abc80 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -875,3 +875,23 @@ bool wsrep_is_load_multi_commit(THD *thd) { return thd->wsrep_split_flag; } + +void wsrep_report_bf_lock_wait(THD *thd, + unsigned long long trx_id) +{ + if (thd) + { + WSREP_ERROR("Thread %s trx_id: %llu thread: %ld " + "seqno: %lld query_state: %s conf_state: %s exec_mode: %s " + "applier: %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_query_state_str(thd), + wsrep_thd_conflict_state_str(thd), + wsrep_thd_exec_mode_str(thd), + thd->wsrep_applier, + wsrep_thd_query(thd)); + } +} diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 10efcbefbf6..46bc08a466a 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -45,6 +45,9 @@ extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync); extern "C" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync); extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); +extern void wsrep_report_bf_lock_wait(THD *thd, + unsigned long long trx_id); + #else /* WITH_WSREP */ #define wsrep_thd_is_BF(T, S) (0) diff --git a/storage/innobase/fts/fts0config.cc b/storage/innobase/fts/fts0config.cc index 51770eb6b69..9f8e07285bf 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 cfe97d8677f..0d62be67369 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 */ @@ -5743,523 +5722,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 */ @@ -6276,780 +5738,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 e3736f3277d..f799a46d088 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 354c36aba50..7e4832a7917 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -736,12 +736,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. @@ -775,15 +772,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 @@ -990,4 +978,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 3c6bc0e14d7..fc888a0c1e6 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 138104ee2c5..efdd38e01a4 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,75 +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 (wsrep_trx_order_before(trx->mysql_thd, - lock2->trx->mysql_thd) - && (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_conflict_state( - trx->mysql_thd, FALSE) - << " locked " - << wsrep_thd_conflict_state( - lock2->trx->mysql_thd, - FALSE); - 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; @@ -1471,11 +1456,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... */ @@ -1554,6 +1536,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); @@ -1821,27 +1804,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_exec_mode(trx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(trx->mysql_thd, false) << " 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_exec_mode(otrx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " << - wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " << - wsrep_thd_query(otrx->mysql_thd); - } -#else - ut_a(!other_lock); + if (UNIV_UNLIKELY(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 */ @@ -2047,9 +2022,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]; @@ -2057,24 +2029,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); } } @@ -2190,6 +2144,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. */ @@ -2260,11 +2215,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 { @@ -3528,11 +3490,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()); @@ -3544,6 +3503,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); } @@ -3553,14 +3514,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); @@ -4119,6 +4072,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;) { @@ -4218,12 +4172,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 { @@ -4893,24 +4853,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_exec_mode(impl_trx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(impl_trx->mysql_thd, false) << " 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_exec_mode(otrx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(otrx->mysql_thd, false) << " 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, @@ -4919,9 +4883,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); @@ -4953,13 +4919,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 f25e9648a32..4c355881ca1 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -911,8 +911,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. */ @@ -945,7 +943,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, @@ -955,30 +953,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 e50ffa7a41c..635210dd405 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3937,9 +3937,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); |