Commit cbcb4eca authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.2 into 10.3

parents ade782c0 69d536a2
...@@ -1200,6 +1200,7 @@ write_slave_info(MYSQL *connection) ...@@ -1200,6 +1200,7 @@ write_slave_info(MYSQL *connection)
char *master = NULL; char *master = NULL;
char *filename = NULL; char *filename = NULL;
char *gtid_executed = NULL; char *gtid_executed = NULL;
char *using_gtid = NULL;
char *position = NULL; char *position = NULL;
char *gtid_slave_pos = NULL; char *gtid_slave_pos = NULL;
char *ptr; char *ptr;
...@@ -1210,6 +1211,7 @@ write_slave_info(MYSQL *connection) ...@@ -1210,6 +1211,7 @@ write_slave_info(MYSQL *connection)
{"Relay_Master_Log_File", &filename}, {"Relay_Master_Log_File", &filename},
{"Exec_Master_Log_Pos", &position}, {"Exec_Master_Log_Pos", &position},
{"Executed_Gtid_Set", &gtid_executed}, {"Executed_Gtid_Set", &gtid_executed},
{"Using_Gtid", &using_gtid},
{NULL, NULL} {NULL, NULL}
}; };
...@@ -1250,7 +1252,8 @@ write_slave_info(MYSQL *connection) ...@@ -1250,7 +1252,8 @@ write_slave_info(MYSQL *connection)
ut_a(asprintf(&mysql_slave_position, ut_a(asprintf(&mysql_slave_position,
"master host '%s', purge list '%s'", "master host '%s', purge list '%s'",
master, gtid_executed) != -1); 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 */ /* MariaDB >= 10.0 with GTID enabled */
result = backup_file_printf(XTRABACKUP_SLAVE_INFO, result = backup_file_printf(XTRABACKUP_SLAVE_INFO,
"SET GLOBAL gtid_slave_pos = '%s';\n" "SET GLOBAL gtid_slave_pos = '%s';\n"
......
...@@ -117,6 +117,8 @@ extern struct wsrep_service_st { ...@@ -117,6 +117,8 @@ extern struct wsrep_service_st {
void (*wsrep_unlock_rollback_func)(); void (*wsrep_unlock_rollback_func)();
void (*wsrep_set_data_home_dir_func)(const char *data_dir); void (*wsrep_set_data_home_dir_func)(const char *data_dir);
my_bool (*wsrep_thd_is_applier_func)(MYSQL_THD); 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; } *wsrep_service;
#ifdef MYSQL_DYNAMIC_PLUGIN #ifdef MYSQL_DYNAMIC_PLUGIN
...@@ -165,6 +167,7 @@ extern struct wsrep_service_st { ...@@ -165,6 +167,7 @@ extern struct wsrep_service_st {
#define wsrep_unlock_rollback() wsrep_service->wsrep_unlock_rollback_func() #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_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_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_debug get_wsrep_debug()
#define wsrep_log_conflicts get_wsrep_log_conflicts() #define wsrep_log_conflicts get_wsrep_log_conflicts()
...@@ -229,6 +232,8 @@ bool wsrep_thd_ignore_table(THD *thd); ...@@ -229,6 +232,8 @@ bool wsrep_thd_ignore_table(THD *thd);
void wsrep_unlock_rollback(); void wsrep_unlock_rollback();
void wsrep_set_data_home_dir(const char *data_dir); void wsrep_set_data_home_dir(const char *data_dir);
my_bool wsrep_thd_is_applier(MYSQL_THD thd); my_bool wsrep_thd_is_applier(MYSQL_THD thd);
void wsrep_report_bf_lock_wait(THD *thd,
unsigned long long trx_id);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -2,48 +2,45 @@ connection node_1; ...@@ -2,48 +2,45 @@ connection node_1;
connection node_2; connection node_2;
connection node_1; connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
CREATE PROCEDURE p1 () INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
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();;
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2a; connection node_2a;
Killing server ... 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; connection node_1;
Got one of the listed errors INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
connection node_2; INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
Got one of the listed errors INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
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);
connection node_2a; connection node_2a;
count_equal INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
1 INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0"); INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
VARIABLE_VALUE INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
2 INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
VARIABLE_VALUE = 2 INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
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);
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1a; connection node_1a;
SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; SELECT COUNT(*) FROM t1;
VARIABLE_VALUE COUNT(*)
2 132
SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; connection node_2a;
VARIABLE_VALUE = 2 SELECT COUNT(*) FROM t1;
1 COUNT(*)
DROP PROCEDURE p1; 132
connection node_1;
DROP TABLE t1; DROP TABLE t1;
CALL mtr.add_suppression("gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); 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"); CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0");
disconnect node_1a;
disconnect node_2a;
...@@ -4,11 +4,11 @@ connection node_1; ...@@ -4,11 +4,11 @@ connection node_1;
connection node_2; connection node_2;
connection node_3; connection node_3;
connection node_4; connection node_4;
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; SELECT VARIABLE_VALUE AS EXPECT_4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 4 EXPECT_4
1 4
connection node_1; connection node_1;
CREATE TABLE t1 (f1 INTEGER); CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=INNODB;
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
connection node_2; connection node_2;
INSERT INTO t1 VALUES (2); INSERT INTO t1 VALUES (2);
...@@ -20,60 +20,78 @@ connection node_3; ...@@ -20,60 +20,78 @@ connection node_3;
INSERT INTO t1 VALUES (13); INSERT INTO t1 VALUES (13);
Shutting down server ... Shutting down server ...
connection node_1; 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); INSERT INTO t1 VALUES (11);
connection node_2; connection node_2;
INSERT INTO t1 VALUES (12); INSERT INTO t1 VALUES (12);
connection node_4; connection node_4;
INSERT INTO t1 VALUES (14); INSERT INTO t1 VALUES (14);
connection node_3; 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); INSERT INTO t1 VALUES (131);
connection node_2; connection node_2;
INSERT INTO t1 VALUES (22); INSERT INTO t1 VALUES (22);
Shutting down server ... Shutting down server ...
connection node_1; 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); INSERT INTO t1 VALUES (21);
connection node_3; connection node_3;
INSERT INTO t1 VALUES (23); INSERT INTO t1 VALUES (23);
connection node_4; connection node_4;
INSERT INTO t1 VALUES (24); INSERT INTO t1 VALUES (24);
connection node_2; 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); INSERT INTO t1 VALUES (221);
connection node_4; connection node_4;
INSERT INTO t1 VALUES (34); INSERT INTO t1 VALUES (34);
Shutting down server ... Shutting down server ...
connection node_1; 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); INSERT INTO t1 VALUES (31);
connection node_2; connection node_2;
INSERT INTO t1 VALUES (32); INSERT INTO t1 VALUES (32);
connection node_3; connection node_3;
INSERT INTO t1 VALUES (33); INSERT INTO t1 VALUES (33);
connection node_4; 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); INSERT INTO t1 VALUES (341);
connection node_1; connection node_1;
SELECT COUNT(*) = 19 FROM t1; SELECT COUNT(*) AS EXPECT_19 FROM t1;
COUNT(*) = 19 EXPECT_19
1 19
connection node_2; connection node_2;
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 4 VARIABLE_VALUE = 4
1 1
SELECT COUNT(*) = 19 FROM t1; SELECT COUNT(*) AS EXPECT_19 FROM t1;
COUNT(*) = 19 EXPECT_19
1 19
connection node_3; connection node_3;
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 4 VARIABLE_VALUE = 4
1 1
SELECT COUNT(*) = 19 FROM t1; SELECT COUNT(*) AS EXPECT_19 FROM t1;
COUNT(*) = 19 EXPECT_19
1 19
connection node_4; connection node_4;
SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; SELECT VARIABLE_VALUE = 4 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE = 4 VARIABLE_VALUE = 4
1 1
SELECT COUNT(*) = 19 FROM t1; SELECT COUNT(*) AS EXPECT_19 FROM t1;
COUNT(*) = 19 EXPECT_19
1 19
connection node_1; connection node_1;
DROP TABLE t1; 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"); 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 ...@@ -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"); CALL mtr.add_suppression("Action message in non-primary configuration from member 0");
connection node_4; connection node_4;
CALL mtr.add_suppression("Action message in non-primary configuration from member 0"); CALL mtr.add_suppression("Action message in non-primary configuration from member 0");
disconnect node_2; connection node_1;
disconnect node_1; disconnect node_3;
disconnect node_4;
...@@ -2,93 +2,61 @@ ...@@ -2,93 +2,61 @@
# Test that autoincrement works correctly while the cluster membership # Test that autoincrement works correctly while the cluster membership
# is changing and SST takes place. # is changing and SST takes place.
# #
--source include/big_test.inc --source include/big_test.inc
--source include/galera_cluster.inc --source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_mariabackup.inc --source include/have_mariabackup.inc
--source include/force_restart.inc
--let $node_1=node_1 --let $node_1=node_1
--let $node_2=node_2 --let $node_2=node_2
--source include/auto_increment_offset_save.inc --source include/auto_increment_offset_save.inc
--connection node_1 --connection node_1
--let $connection_id = `SELECT CONNECTION_ID()`
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;
# Issue an endless stream of autoincrement inserts INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
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
# Kill and restart node #2 # Kill and restart node #2
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 --connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--connection node_2a --connection node_2a
--source include/kill_galera.inc --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 --connection node_1
# CR_SERVER_LOST INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
--error 2013,2006 INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
--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);
--connection node_2 --connection node_2a
# CR_SERVER_LOST --source include/start_mysqld.inc
--error 2013,2006 --source include/wait_until_connected_again.inc
--reap
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
# Confirm that the count is correct and that the cluster is intact 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 --connection node_1a
--let $count = `SELECT COUNT(*) FROM t1` SELECT COUNT(*) FROM t1;
--connection node_2a --connection node_2a
--disable_query_log SELECT COUNT(*) FROM t1;
--eval SELECT COUNT(*) = $count AS count_equal FROM t1
--enable_query_log
CALL mtr.add_suppression("WSREP: Action message in non-primary configuration from member 0"); --connection node_1
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;
DROP TABLE t1; DROP TABLE t1;
CALL mtr.add_suppression("gcs_caused\\(\\) returned -1 \\(Operation not permitted\\)"); 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 ...@@ -97,3 +65,6 @@ CALL mtr.add_suppression("WSREP: Action message in non-primary configuration fro
--let $node_1=node_1a --let $node_1=node_1a
--let $node_2=node_2a --let $node_2=node_2a
--source include/auto_increment_offset_restore.inc --source include/auto_increment_offset_restore.inc
--disconnect node_1a
--disconnect node_2a
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
--source include/big_test.inc --source include/big_test.inc
--source include/galera_cluster.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_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
--connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 --connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4
...@@ -22,10 +22,13 @@ ...@@ -22,10 +22,13 @@
--let $node_4=node_4 --let $node_4=node_4
--source include/auto_increment_offset_save.inc --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 --connection node_1
CREATE TABLE t1 (f1 INTEGER); CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=INNODB;
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
--connection node_2 --connection node_2
...@@ -46,9 +49,13 @@ INSERT INTO t1 VALUES (13); ...@@ -46,9 +49,13 @@ INSERT INTO t1 VALUES (13);
--echo Shutting down server ... --echo Shutting down server ...
--source include/shutdown_mysqld.inc --source include/shutdown_mysqld.inc
--sleep 5
--connection node_1 --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); INSERT INTO t1 VALUES (11);
--connection node_2 --connection node_2
...@@ -59,9 +66,12 @@ INSERT INTO t1 VALUES (14); ...@@ -59,9 +66,12 @@ INSERT INTO t1 VALUES (14);
--connection node_3 --connection node_3
--source include/start_mysqld.inc --source include/start_mysqld.inc
--sleep 5
--source include/wait_until_connected_again.inc --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); INSERT INTO t1 VALUES (131);
# #
...@@ -73,9 +83,12 @@ INSERT INTO t1 VALUES (22); ...@@ -73,9 +83,12 @@ INSERT INTO t1 VALUES (22);
--echo Shutting down server ... --echo Shutting down server ...
--source include/shutdown_mysqld.inc --source include/shutdown_mysqld.inc
--sleep 5
--connection node_1 --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); INSERT INTO t1 VALUES (21);
--connection node_3 --connection node_3
...@@ -86,9 +99,12 @@ INSERT INTO t1 VALUES (24); ...@@ -86,9 +99,12 @@ INSERT INTO t1 VALUES (24);
--connection node_2 --connection node_2
--source include/start_mysqld.inc --source include/start_mysqld.inc
--sleep 5
--source include/wait_until_connected_again.inc --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); INSERT INTO t1 VALUES (221);
# #
...@@ -100,9 +116,12 @@ INSERT INTO t1 VALUES (34); ...@@ -100,9 +116,12 @@ INSERT INTO t1 VALUES (34);
--echo Shutting down server ... --echo Shutting down server ...
--source include/shutdown_mysqld.inc --source include/shutdown_mysqld.inc
--sleep 5
--connection node_1 --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); INSERT INTO t1 VALUES (31);
--connection node_2 --connection node_2
...@@ -113,9 +132,12 @@ INSERT INTO t1 VALUES (33); ...@@ -113,9 +132,12 @@ INSERT INTO t1 VALUES (33);
--connection node_4 --connection node_4
--source include/start_mysqld.inc --source include/start_mysqld.inc
--sleep 5
--source include/wait_until_connected_again.inc --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); INSERT INTO t1 VALUES (341);
...@@ -124,22 +146,44 @@ INSERT INTO t1 VALUES (341); ...@@ -124,22 +146,44 @@ INSERT INTO t1 VALUES (341);
# #
--connection node_1 --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 --source include/wait_condition.inc
SELECT COUNT(*) = 19 FROM t1; SELECT COUNT(*) AS EXPECT_19 FROM t1;
--connection node_2 --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 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 --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 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 --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 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 --connection node_1
DROP TABLE t1; DROP TABLE t1;
...@@ -158,4 +202,6 @@ CALL mtr.add_suppression("Action message in non-primary configuration from membe ...@@ -158,4 +202,6 @@ CALL mtr.add_suppression("Action message in non-primary configuration from membe
# Restore original auto_increment_offset values. # Restore original auto_increment_offset values.
--source include/auto_increment_offset_restore.inc --source include/auto_increment_offset_restore.inc
--source include/galera_end.inc --connection node_1
--disconnect node_3
--disconnect node_4
...@@ -7,11 +7,11 @@ VARIABLE_VALUE = 3 ...@@ -7,11 +7,11 @@ VARIABLE_VALUE = 3
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
connection node_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); INSERT INTO t1 VALUES (1);
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
COUNT(*) = 1 EXPECT_1
1 1
DROP TABLE t1; DROP TABLE t1;
...@@ -7,16 +7,16 @@ VARIABLE_VALUE = 3 ...@@ -7,16 +7,16 @@ VARIABLE_VALUE = 3
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
connection node_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); INSERT INTO t1 VALUES (1);
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
COUNT(*) = 1 EXPECT_1
1 1
DROP TABLE t1; DROP TABLE t1;
connection node_1; connection node_1;
include/assert_grep.inc [Streaming the backup to joiner at \[::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 [async IST sender starting to serve tcp://\[::1\]:]
include/assert_grep.inc [IST receiver addr using 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\]]
...@@ -7,12 +7,12 @@ VARIABLE_VALUE = 3 ...@@ -7,12 +7,12 @@ VARIABLE_VALUE = 3
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
connection node_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); INSERT INTO t1 VALUES (1);
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
COUNT(*) = 1 EXPECT_1
1 1
DROP TABLE t1; DROP TABLE t1;
connection node_1; connection node_1;
...@@ -20,4 +20,4 @@ include/assert_grep.inc [Streaming the backup to joiner at \[::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\]:] include/assert_grep.inc [async IST sender starting to serve tcp://\[::1\]:]
connection node_2; connection node_2;
include/assert_grep.inc [IST receiver addr using 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\]]
...@@ -12,12 +12,12 @@ SET GLOBAL wsrep_sst_method = 'mysqldump'; ...@@ -12,12 +12,12 @@ SET GLOBAL wsrep_sst_method = 'mysqldump';
Shutting down server ... Shutting down server ...
connection node_1; connection node_1;
Cleaning var directory ... 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); INSERT INTO t1 VALUES (1);
connection node_2; connection node_2;
Starting server ... Starting server ...
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
COUNT(*) = 1 EXPECT_1
1 1
DROP TABLE t1; DROP TABLE t1;
SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses'; SELECT VARIABLE_VALUE LIKE '%[::1]%' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses';
......
...@@ -7,11 +7,11 @@ VARIABLE_VALUE = 3 ...@@ -7,11 +7,11 @@ VARIABLE_VALUE = 3
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
connection node_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); INSERT INTO t1 VALUES (1);
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
COUNT(*) = 1 EXPECT_1
1 1
DROP TABLE t1; DROP TABLE t1;
...@@ -7,11 +7,11 @@ VARIABLE_VALUE = 3 ...@@ -7,11 +7,11 @@ VARIABLE_VALUE = 3
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
connection node_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); INSERT INTO t1 VALUES (1);
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; SET GLOBAL wsrep_provider_options='gmcast.isolate=0';
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
COUNT(*) = 1 EXPECT_1
1 1
DROP TABLE t1; DROP TABLE t1;
...@@ -2,7 +2,8 @@ connection node_1; ...@@ -2,7 +2,8 @@ connection node_1;
connection node_2; connection node_2;
connection node_3; connection node_3;
connection node_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);
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'] 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"); ...@@ -48,6 +49,7 @@ CALL mtr.add_suppression("Failed to prepare for incremental state transfer");
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`f1` int(11) DEFAULT NULL `f1` int(11) NOT NULL,
PRIMARY KEY (`f1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
...@@ -2,7 +2,7 @@ connection node_1; ...@@ -2,7 +2,7 @@ connection node_1;
connection node_2; connection node_2;
connection node_3; connection node_3;
connection node_1; connection node_1;
CREATE TABLE t1 (f1 INTEGER); CREATE TABLE t1 (f1 INTEGER) ENGINE=INNODB;
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
connection node_2; connection node_2;
SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
......
...@@ -10,6 +10,7 @@ wsrep_node_address=[::1] ...@@ -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_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_sst_receive_address='[::1]:@mysqld.1.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.1.port' wsrep_node_incoming_address='[::1]:@mysqld.1.port'
bind-address=::
[mysqld.2] [mysqld.2]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port'
...@@ -17,6 +18,7 @@ wsrep_node_address=[::1] ...@@ -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_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_sst_receive_address='[::1]:@mysqld.2.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.2.port' wsrep_node_incoming_address='[::1]:@mysqld.2.port'
bind-address=::
[mysqld.3] [mysqld.3]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port'
...@@ -24,3 +26,4 @@ wsrep_node_address=[::1] ...@@ -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_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_sst_receive_address='[::1]:@mysqld.3.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.3.port' wsrep_node_incoming_address='[::1]:@mysqld.3.port'
bind-address=::
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
--source include/galera_cluster.inc --source include/galera_cluster.inc
--source include/check_ipv6.inc --source include/check_ipv6.inc
--source include/force_restart.inc
# Confirm that initial handshake happened over ipv6 # Confirm that initial handshake happened over ipv6
...@@ -21,7 +22,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc --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); INSERT INTO t1 VALUES (1);
--connection node_2 --connection node_2
...@@ -33,6 +34,6 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
--source include/wait_condition.inc --source include/wait_condition.inc
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
DROP TABLE t1; DROP TABLE t1;
...@@ -10,18 +10,21 @@ wsrep-cluster-address=gcomm:// ...@@ -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_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_sst_receive_address='[::1]:@mysqld.1.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.1.port' wsrep_node_incoming_address='[::1]:@mysqld.1.port'
bind-address=::
[mysqld.2] [mysqld.2]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' 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_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_sst_receive_address='[::1]:@mysqld.2.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.2.port' wsrep_node_incoming_address='[::1]:@mysqld.2.port'
bind-address=::
[mysqld.3] [mysqld.3]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' 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_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_sst_receive_address='[::1]:@mysqld.3.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.3.port' wsrep_node_incoming_address='[::1]:@mysqld.3.port'
bind-address=::
[SST] [SST]
transferfmt=@ENV.MTR_GALERA_TFMT transferfmt=@ENV.MTR_GALERA_TFMT
......
...@@ -18,7 +18,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc --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); INSERT INTO t1 VALUES (1);
--connection node_2 --connection node_2
...@@ -30,7 +30,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
--source include/wait_condition.inc --source include/wait_condition.inc
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
DROP TABLE t1; DROP TABLE t1;
...@@ -56,6 +56,8 @@ DROP TABLE t1; ...@@ -56,6 +56,8 @@ DROP TABLE t1;
--let $assert_select = IST receiver addr using tcp://\[::1\] --let $assert_select = IST receiver addr using tcp://\[::1\]
--source include/assert_grep.inc --source include/assert_grep.inc
--let $assert_text = Prepared IST receiver, listening at: tcp://\[::1\] # The receiver expects IST
--let $assert_select = Prepared IST receiver, listening at: tcp://\[::1\] --let $assert_count = 1
--let $assert_text = , listening at: tcp://\[::1\]
--let $assert_select = , listening at: tcp://\[::1\]
--source include/assert_grep.inc --source include/assert_grep.inc
...@@ -3,35 +3,37 @@ ...@@ -3,35 +3,37 @@
# decoy value - should not be read by mysqld or sst scripts # decoy value - should not be read by mysqld or sst scripts
[mysqld] [mysqld]
innodb-data-home-dir=/tmp innodb-data-home-dir=/tmp
bind-address=::
[galera]
innodb-data-home-dir= innodb-data-home-dir=
wsrep_sst_method=mariabackup wsrep_sst_method=mariabackup
wsrep_sst_auth="root:" wsrep_sst_auth="root:"
wsrep_node_address=::1 wsrep_node_address=::1
[galera.1] [mysqld.1]
wsrep-cluster-address=gcomm:// 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_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_sst_receive_address='[::1]:@mysqld.1.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.1.port' wsrep_node_incoming_address='[::1]:@mysqld.1.port'
wsrep_node_name=node_1 wsrep_node_name=node_1
bind-address=::
[galera.2] [mysqld.2]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' 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_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_sst_receive_address='[::1]:@mysqld.2.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.2.port' wsrep_node_incoming_address='[::1]:@mysqld.2.port'
wsrep_node_name=node_2 wsrep_node_name=node_2
wsrep_sst_donor=node_1 wsrep_sst_donor=node_1
bind-address=::
[galera.3] [mysqld.3]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' 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_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_sst_receive_address='[::1]:@mysqld.3.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.3.port' wsrep_node_incoming_address='[::1]:@mysqld.3.port'
wsrep_node_name=node_3 wsrep_node_name=node_3
wsrep_sst_donor=node_1 wsrep_sst_donor=node_1
bind-address=::
[SST] [SST]
transferfmt=@ENV.MTR_GALERA_TFMT transferfmt=@ENV.MTR_GALERA_TFMT
......
...@@ -18,7 +18,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc --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); INSERT INTO t1 VALUES (1);
--connection node_2 --connection node_2
...@@ -30,7 +30,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
--source include/wait_condition.inc --source include/wait_condition.inc
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
DROP TABLE t1; DROP TABLE t1;
...@@ -64,8 +64,8 @@ DROP TABLE t1; ...@@ -64,8 +64,8 @@ DROP TABLE t1;
--let $assert_select = IST receiver addr using tcp://\[::1\] --let $assert_select = IST receiver addr using tcp://\[::1\]
--source include/assert_grep.inc --source include/assert_grep.inc
# There will be only one Prepared IST and in Galera 3 segnos are not printed # The receiver expects IST
--let $assert_count= 1 --let $assert_count = 1
--let $assert_text = Prepared IST receiver, listening at: tcp://\[::1\] --let $assert_text = , listening at: tcp://\[::1\]
--let $assert_select = Prepared IST receiver, listening at: tcp://\[::1\] --let $assert_select = , listening at: tcp://\[::1\]
--source include/assert_grep.inc --source include/assert_grep.inc
...@@ -9,18 +9,21 @@ wsrep-cluster-address=gcomm:// ...@@ -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_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_sst_receive_address='[::1]:@mysqld.1.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.1.port' wsrep_node_incoming_address='[::1]:@mysqld.1.port'
bind-address=::
[mysqld.2] [mysqld.2]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' 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_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_sst_receive_address='[::1]:@mysqld.2.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.2.port' wsrep_node_incoming_address='[::1]:@mysqld.2.port'
bind-address=::
[mysqld.3] [mysqld.3]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' 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_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_sst_receive_address='[::1]:@mysqld.3.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.3.port' wsrep_node_incoming_address='[::1]:@mysqld.3.port'
bind-address=::
[SST] [SST]
sockopt=",pf=ip6" sockopt=",pf=ip6"
...@@ -54,7 +54,7 @@ SET GLOBAL wsrep_sst_method = 'mysqldump'; ...@@ -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/mysql
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data --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); INSERT INTO t1 VALUES (1);
--connection node_2 --connection node_2
...@@ -70,7 +70,7 @@ INSERT INTO t1 VALUES (1); ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
--source include/wait_condition.inc --source include/wait_condition.inc
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
DROP TABLE t1; DROP TABLE t1;
......
...@@ -9,18 +9,21 @@ wsrep-cluster-address=gcomm:// ...@@ -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_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_sst_receive_address='[::1]:@mysqld.1.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.1.port' wsrep_node_incoming_address='[::1]:@mysqld.1.port'
bind-address=::
[mysqld.2] [mysqld.2]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' 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_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_sst_receive_address='[::1]:@mysqld.2.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.2.port' wsrep_node_incoming_address='[::1]:@mysqld.2.port'
bind-address=::
[mysqld.3] [mysqld.3]
wsrep_cluster_address='gcomm://[::1]:@mysqld.1.#galera_port' 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_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_sst_receive_address='[::1]:@mysqld.3.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.3.port' wsrep_node_incoming_address='[::1]:@mysqld.3.port'
bind-address=::
[SST] [SST]
sockopt=",pf=ip6" sockopt=",pf=ip6"
...@@ -16,7 +16,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc --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); INSERT INTO t1 VALUES (1);
--connection node_2 --connection node_2
...@@ -28,6 +28,6 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
--source include/wait_condition.inc --source include/wait_condition.inc
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
DROP TABLE t1; DROP TABLE t1;
...@@ -4,28 +4,31 @@ ...@@ -4,28 +4,31 @@
[mysqld] [mysqld]
innodb-data-home-dir=/tmp innodb-data-home-dir=/tmp
[mariadb] [mysqld]
innodb-data-home-dir= innodb-data-home-dir=
wsrep_sst_method=rsync wsrep_sst_method=rsync
wsrep_node_address=::1 wsrep_node_address=::1
[mariadb.1] [mysqld.1]
wsrep-cluster-address=gcomm:// 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_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_sst_receive_address='[::1]:@mysqld.1.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.1.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_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_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_sst_receive_address='[::1]:@mysqld.2.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.2.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_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_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_sst_receive_address='[::1]:@mysqld.3.#sst_port'
wsrep_node_incoming_address='[::1]:@mysqld.3.port' wsrep_node_incoming_address='[::1]:@mysqld.3.port'
bind-address=::
[SST] [SST]
sockopt=",pf=ip6" sockopt=",pf=ip6"
...@@ -16,7 +16,7 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc --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); INSERT INTO t1 VALUES (1);
--connection node_2 --connection node_2
...@@ -28,6 +28,6 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; ...@@ -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'; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
--source include/wait_condition.inc --source include/wait_condition.inc
SELECT COUNT(*) = 1 FROM t1; SELECT COUNT(*) AS EXPECT_1 FROM t1;
DROP TABLE t1; DROP TABLE t1;
!include ../galera_3nodes.cnf
[mysqld.1]
wsrep_debug=1
[mysqld.2]
wsrep_debug=1
[mysqld.3]
wsrep_debug=1
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# Test the safe_to_bootstrap in grastate.dat # Test the safe_to_bootstrap in grastate.dat
# #
--source include/galera_cluster.inc --source include/galera_cluster.inc
--source include/force_restart.inc
--let $galera_connection_name = node_3 --let $galera_connection_name = node_3
--let $galera_server_number = 3 --let $galera_server_number = 3
...@@ -14,7 +15,11 @@ ...@@ -14,7 +15,11 @@
--source ../galera/include/auto_increment_offset_save.inc --source ../galera/include/auto_increment_offset_save.inc
--connection node_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);
--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 # At start, all grastate.dat files have safe_to_boostrap: 0
...@@ -151,10 +156,18 @@ SET SESSION wsrep_on = OFF; ...@@ -151,10 +156,18 @@ SET SESSION wsrep_on = OFF;
--source include/start_mysqld.inc --source include/start_mysqld.inc
--source include/wait_until_connected_again.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 --connection node_2
--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
--source include/start_mysqld.inc --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 --connection node_3
--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.3.expect --let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.3.expect
--source include/start_mysqld.inc --source include/start_mysqld.inc
......
...@@ -16,10 +16,13 @@ ...@@ -16,10 +16,13 @@
--source ../galera/include/auto_increment_offset_save.inc --source ../galera/include/auto_increment_offset_save.inc
--connection node_1 --connection node_1
CREATE TABLE t1 (f1 INTEGER); CREATE TABLE t1 (f1 INTEGER) ENGINE=INNODB;
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
--connection node_2 --connection node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM t1;
--source include/wait_condition.inc
SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
--connection node_1 --connection node_1
...@@ -28,15 +31,11 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; ...@@ -28,15 +31,11 @@ SET GLOBAL wsrep_provider_options='gmcast.isolate=1';
--connection node_2 --connection node_2
SET SESSION wsrep_sync_wait = 0; 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'; --let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
--source include/wait_condition.inc --source include/wait_condition.inc
SET SESSION wsrep_dirty_reads = 1; SET SESSION wsrep_dirty_reads = 1;
--let $wait_condition = SELECT COUNT(*) = 1 FROM t1;
--source include/wait_condition.inc
# Those statements should succeed # Those statements should succeed
--error 0 --error 0
......
...@@ -740,3 +740,32 @@ t1 CREATE TABLE `t1` ( ...@@ -740,3 +740,32 @@ t1 CREATE TABLE `t1` (
KEY `v4` (`v4`) KEY `v4` (`v4`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1; 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;
...@@ -605,3 +605,35 @@ ALTER TABLE t1 ADD CONSTRAINT fk FOREIGN KEY (v4) REFERENCES nosuch(col); ...@@ -605,3 +605,35 @@ ALTER TABLE t1 ADD CONSTRAINT fk FOREIGN KEY (v4) REFERENCES nosuch(col);
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
# Cleanup # Cleanup
DROP TABLE t1; 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;
...@@ -5,8 +5,7 @@ SET GLOBAL innodb_file_per_table=1; ...@@ -5,8 +5,7 @@ SET GLOBAL innodb_file_per_table=1;
# #
SET GLOBAL innodb_file_per_table=ON; SET GLOBAL innodb_file_per_table=ON;
create table t1 (a int not null, d varchar(15) not null, b create table t1 (a int not null, d varchar(15) not null, b
varchar(198) not null, c char(156), varchar(198) not null, c char(156)) engine=InnoDB
fulltext ftsic(c)) engine=InnoDB
row_format=redundant; row_format=redundant;
insert into t1 values(123, 'abcdef', 'jghikl', 'mnop'); insert into t1 values(123, 'abcdef', 'jghikl', 'mnop');
insert into t1 values(456, 'abcdef', 'jghikl', 'mnop'); insert into t1 values(456, 'abcdef', 'jghikl', 'mnop');
...@@ -72,7 +71,7 @@ DROP TABLE t1; ...@@ -72,7 +71,7 @@ DROP TABLE t1;
Warnings: Warnings:
Warning 1932 Table 'test.t1' doesn't exist in engine Warning 1932 Table 'test.t1' doesn't exist in engine
DROP TABLE t2,t3; 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_buffer_pool
ib_logfile0 ib_logfile0
ib_logfile1 ib_logfile1
......
...@@ -32,8 +32,7 @@ SET GLOBAL innodb_file_per_table=1; ...@@ -32,8 +32,7 @@ SET GLOBAL innodb_file_per_table=1;
SET GLOBAL innodb_file_per_table=ON; SET GLOBAL innodb_file_per_table=ON;
create table t1 (a int not null, d varchar(15) not null, b create table t1 (a int not null, d varchar(15) not null, b
varchar(198) not null, c char(156), varchar(198) not null, c char(156)) engine=InnoDB
fulltext ftsic(c)) engine=InnoDB
row_format=redundant; row_format=redundant;
insert into t1 values(123, 'abcdef', 'jghikl', 'mnop'); insert into t1 values(123, 'abcdef', 'jghikl', 'mnop');
......
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
--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
...@@ -186,7 +186,8 @@ static struct wsrep_service_st wsrep_handler = { ...@@ -186,7 +186,8 @@ static struct wsrep_service_st wsrep_handler = {
wsrep_trx_order_before, wsrep_trx_order_before,
wsrep_unlock_rollback, wsrep_unlock_rollback,
wsrep_set_data_home_dir, 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= static struct thd_specifics_service_st thd_specifics_handler=
......
/* Copyright (C) 2014 SkySQL Ab. /* Copyright (C) 2014, 2020, MariaDB
This program is free software; you can redistribute it and/or modify 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 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 *, ...) ...@@ -163,3 +163,7 @@ void wsrep_log(void (*)(const char *, ...), const char *, ...)
my_bool wsrep_thd_is_applier(MYSQL_THD thd) my_bool wsrep_thd_is_applier(MYSQL_THD thd)
{ return false; } { return false; }
void wsrep_report_bf_lock_wait(MYSQL_THD thd,
unsigned long long id)
{}
...@@ -875,3 +875,23 @@ bool wsrep_is_load_multi_commit(THD *thd) ...@@ -875,3 +875,23 @@ bool wsrep_is_load_multi_commit(THD *thd)
{ {
return thd->wsrep_split_flag; 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));
}
}
...@@ -45,6 +45,9 @@ extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync); ...@@ -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" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync);
extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); 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 */ #else /* WITH_WSREP */
#define wsrep_thd_is_BF(T, S) (0) #define wsrep_thd_is_BF(T, S) (0)
......
...@@ -148,9 +148,7 @@ fts_config_create_index_param_name( ...@@ -148,9 +148,7 @@ fts_config_create_index_param_name(
::strcpy(name, param); ::strcpy(name, param);
name[len] = '_'; name[len] = '_';
fts_write_object_id(index->id, name + len + 1, fts_write_object_id(index->id, name + len + 1);
DICT_TF2_FLAG_IS_SET(index->table,
DICT_TF2_FTS_AUX_HEX_NAME));
return(name); return(name);
} }
......
...@@ -1564,18 +1564,19 @@ fts_rename_aux_tables( ...@@ -1564,18 +1564,19 @@ fts_rename_aux_tables(
return(DB_SUCCESS); 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 on the given table. row_mysql_lock_data_dictionary must have been called
before this. 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 */ @return DB_SUCCESS or error code */
static MY_ATTRIBUTE((nonnull, warn_unused_result)) static dberr_t
dberr_t
fts_drop_common_tables( fts_drop_common_tables(
/*===================*/ trx_t* trx,
trx_t* trx, /*!< in: transaction */ fts_table_t* fts_table,
fts_table_t* fts_table) /*!< in: table with an FTS bool drop_orphan=false)
index */
{ {
ulint i; ulint i;
dberr_t error = DB_SUCCESS; dberr_t error = DB_SUCCESS;
...@@ -1593,6 +1594,16 @@ fts_drop_common_tables( ...@@ -1593,6 +1594,16 @@ fts_drop_common_tables(
if (err != DB_SUCCESS && err != DB_FAIL) { if (err != DB_SUCCESS && err != DB_FAIL) {
error = err; 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); return(error);
...@@ -2105,38 +2116,6 @@ fts_create_index_tables(trx_t* trx, const dict_index_t* index, table_id_t id) ...@@ -2105,38 +2116,6 @@ fts_create_index_tables(trx_t* trx, const dict_index_t* index, table_id_t id)
return(error); 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. Calculate the new state of a row given the existing state and a new event.
@return new state of row */ @return new state of row */
...@@ -5743,1313 +5722,261 @@ fts_savepoint_rollback( ...@@ -5743,1313 +5722,261 @@ fts_savepoint_rollback(
} }
} }
/** Check if a table is an FTS auxiliary table name. /*********************************************************************//**
@param[out] table FTS table info Compare two fts_aux_table_t parent_ids.
@param[in] name Table name @return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
@param[in] len Length of table name UNIV_INLINE
@return true if the name matches an auxiliary table name pattern */ int
static fts_check_aux_table_parent_id_cmp(
bool /*==============================*/
fts_is_aux_table_name( const void* p1, /*!< in: id1 */
fts_aux_table_t* table, const void* p2) /*!< in: id2 */
const char* name, {
ulint len) const fts_aux_table_t* fa1 = static_cast<const fts_aux_table_t*>(p1);
const fts_aux_table_t* fa2 = static_cast<const fts_aux_table_t*>(p2);
return static_cast<int>(fa1->parent_id - fa2->parent_id);
}
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* ptr;
char* end; const char* end= name + len;
char my_name[MAX_FULL_NAME_LEN + 1];
ut_ad(len <= MAX_FULL_NAME_LEN); ut_ad(len <= MAX_FULL_NAME_LEN);
ut_memcpy(my_name, name, len); ptr= static_cast<const char*>(memchr(name, '/', len));
my_name[len] = 0;
end = my_name + len;
ptr = static_cast<const char*>(memchr(my_name, '/', len)); if (ptr != NULL)
{
if (ptr != NULL) {
/* We will start the match after the '/' */ /* We will start the match after the '/' */
++ptr; ++ptr;
len = ulint(end - ptr); len = end - ptr;
} }
/* All auxiliary tables are prefixed with "FTS_" and the name /* All auxiliary tables are prefixed with "FTS_" and the name
length will be at the very least greater than 20 bytes. */ length will be at the very least greater than 20 bytes. */
if (ptr != NULL && len > 20 && strncmp(ptr, "FTS_", 4) == 0) { if (ptr && len > 20 && !memcmp(ptr, "FTS_", 4))
ulint i; {
/* Skip the prefix. */ /* Skip the prefix. */
ptr += 4; ptr+= 4;
len -= 4; len-= 4;
/* Try and read the table id. */
if (!fts_read_object_id(&table->parent_id, ptr)) {
return(false);
}
const char *table_id_ptr= ptr;
/* Skip the table id. */ /* Skip the table id. */
ptr = static_cast<const char*>(memchr(ptr, '_', len)); ptr= static_cast<const char*>(memchr(ptr, '_', len));
if (ptr == NULL) { if (!ptr)
return(false); return false;
}
/* Skip the underscore. */ /* Skip the underscore. */
++ptr; ++ptr;
ut_a(end > ptr); ut_ad(end > ptr);
len = ulint(end - ptr); len= end - ptr;
sscanf(table_id_ptr, UINT64PFx, table_id);
/* First search the common table suffix array. */ /* First search the common table suffix array. */
for (i = 0; fts_common_tables[i] != NULL; ++i) { for (ulint i = 0; fts_common_tables[i]; ++i)
{
if (strncmp(ptr, fts_common_tables[i], len) == 0) { if (!strncmp(ptr, fts_common_tables[i], len))
return(true); return true;
}
} }
/* Could be obsolete common tables. */ /* Could be obsolete common tables. */
if (strncmp(ptr, "ADDED", len) == 0 if ((len == 5 && !memcmp(ptr, "ADDED", len)) ||
|| strncmp(ptr, "STOPWORDS", len) == 0) { (len == 9 && !memcmp(ptr, "STOPWORDS", len)))
return(true); return true;
}
/* Try and read the index id. */
if (!fts_read_object_id(&table->index_id, ptr)) {
return(false);
}
/* Skip the table id. */ const char* index_id_ptr= ptr;
ptr = static_cast<const char*>(memchr(ptr, '_', len)); /* Skip the index id. */
ptr= static_cast<const char*>(memchr(ptr, '_', len));
if (!ptr)
return false;
if (ptr == NULL) { sscanf(index_id_ptr, UINT64PFx, index_id);
return(false);
}
/* Skip the underscore. */ /* Skip the underscore. */
++ptr; ++ptr;
ut_a(end > ptr); ut_a(end > ptr);
len = ulint(end - ptr); len= end - ptr;
/* Search the FT index specific array. */ if (len > 7)
for (i = 0; i < FTS_NUM_AUX_INDEX; ++i) { return false;
if (strncmp(ptr, fts_get_suffix(i), len) == 0) { /* Search the FT index specific array. */
return(true); for (ulint i = 0; i < FTS_NUM_AUX_INDEX; ++i)
} {
if (!memcmp(ptr, "INDEX_", len - 1))
return true;
} }
/* Other FT index specific table(s). */ /* Other FT index specific table(s). */
if (strncmp(ptr, "DOC_ID", len) == 0) { if (len == 6 && !memcmp(ptr, "DOC_ID", len))
return(true); 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); return false;
} }
/******************************************************************//** typedef std::pair<table_id_t,index_id_t> fts_aux_id;
Callback that sets a hex formatted FTS table's flags2 in typedef std::set<fts_aux_id> fts_space_set_t;
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);
}
/*****************************************************************//** /** Iterate over all the spaces in the space list and fetch the
Update the DICT_TF2_FTS_AUX_HEX_NAME flag in SYS_TABLES. fts parent table id and index id.
@return DB_SUCCESS or error code. */ @param[in,out] fts_space_set store the list of tablespace id and
static index id */
dberr_t static void fil_get_fts_spaces(fts_space_set_t& fts_space_set)
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; mutex_enter(&fil_system.mutex);
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( for (fil_space_t *space= UT_LIST_GET_FIRST(fil_system.space_list);
info, "my_func", fts_set_hex_format, &flags2); space;
space= UT_LIST_GET_NEXT(space_list, space))
{
index_id_t index_id= 0;
table_id_t table_id= 0;
if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) { if (space->purpose == FIL_TYPE_TABLESPACE
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); && fts_check_aux_table(space->name, &table_id, &index_id))
fts_space_set.insert(std::make_pair(table_id, index_id));
} }
dberr_t err = que_eval_sql(info, sql, !dict_locked, trx); mutex_exit(&fil_system.mutex);
ut_a(flags2 != ULINT32_UNDEFINED);
return(err);
} }
/*********************************************************************//** /** Check whether the parent table id and index id of fts auxilary
Rename an aux table to HEX format. It's called when "%016llu" is used tables with SYS_INDEXES. If it exists then we can safely ignore the
to format an object id in table name, which only happens in Windows. */ fts table from orphaned tables.
static MY_ATTRIBUTE((nonnull, warn_unused_result)) @param[in,out] fts_space_set fts space set contains set of auxiliary
dberr_t table ids */
fts_rename_one_aux_table_to_hex_format( static void fts_check_orphaned_tables(fts_space_set_t& fts_space_set)
/*===================================*/
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; btr_pcur_t pcur;
fts_table_t fts_table; mtr_t mtr;
char new_name[MAX_FULL_NAME_LEN]; trx_t* trx = trx_create();
dberr_t error; trx->op_info = "checking fts orphaned tables";
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) { row_mysql_lock_data_dictionary(trx);
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 */ mtr.start();
ptr = strchr(ptr, '_'); btr_pcur_open_at_index_side(
ut_a(ptr != NULL); true, dict_table_get_first_index(dict_sys->sys_indexes),
++ptr; BTR_SEARCH_LEAF, &pcur, true, 0, &mtr);
do
{
const rec_t *rec;
const byte *tbl_field;
const byte *index_field;
ulint len;
for (ulint i = 0; fts_index_selector[i].value; ++i) { btr_pcur_move_to_next_user_rec(&pcur, &mtr);
if (strcmp(ptr, fts_get_suffix(i)) == 0) { if (!btr_pcur_is_on_user_rec(&pcur))
fts_table.suffix = fts_get_suffix(i);
break; break;
}
}
}
ut_a(fts_table.suffix != NULL); rec= btr_pcur_get_rec(&pcur);
if (rec_get_deleted_flag(rec, 0))
continue;
fts_table.table_id = aux_table->parent_id; tbl_field= rec_get_nth_field_old(rec, 0, &len);
fts_table.index_id = aux_table->index_id; if (len != 8)
fts_table.table = parent_table; continue;
fts_get_table_name(&fts_table, new_name); index_field= rec_get_nth_field_old(rec, 1, &len);
ut_ad(strcmp(new_name, aux_table->name) != 0); if (len != 8)
continue;
if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) { table_id_t table_id = mach_read_from_8(tbl_field);
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX); index_id_t index_id = mach_read_from_8(index_field);
}
error = row_rename_table_for_mysql(aux_table->name, new_name, trx, fts_space_set_t::iterator it = fts_space_set.find(
false, false); fts_aux_id(table_id, index_id));
if (error != DB_SUCCESS) { if (it != fts_space_set.end())
ib::warn() << "Failed to rename aux table '" fts_space_set.erase(*it);
<< aux_table->name << "' to new format '" else
<< new_name << "'."; {
} else { it= fts_space_set.find(fts_aux_id(table_id, 0));
ib::info() << "Renamed aux table '" << aux_table->name if (it != fts_space_set.end())
<< "' to '" << new_name << "'."; fts_space_set.erase(*it);
} }
} while(!fts_space_set.empty());
return(error); btr_pcur_close(&pcur);
mtr.commit();
row_mysql_unlock_data_dictionary(trx);
trx->free();
} }
/**********************************************************************//** /** Drop all fts auxilary table for the respective fts_id
Rename all aux tables of a parent table to HEX format. Also set aux tables' @param[in] fts_id fts auxilary table ids */
flags2 and parent table's flags2 with DICT_TF2_FTS_AUX_HEX_NAME. static void fts_drop_all_aux_tables(trx_t *trx, fts_table_t *fts_table)
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; char fts_table_name[MAX_FULL_NAME_LEN];
ulint count; for (ulint i= 0;i < FTS_NUM_AUX_INDEX; i++)
{
ut_ad(!DICT_TF2_FLAG_IS_SET(parent_table, DICT_TF2_FTS_AUX_HEX_NAME)); fts_table->suffix= fts_get_suffix(i);
ut_ad(!ib_vector_is_empty(tables)); fts_get_table_name(fts_table, fts_table_name, true);
error = fts_update_hex_format_flag(trx, parent_table->id, true); /* Drop all fts aux and common table */
dberr_t err= fts_drop_table(trx, fts_table_name);
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 " if (err == DB_FAIL)
<< aux_table->name << ". Will revert" {
" all successful rename operations."; char *path= fil_make_filepath(NULL, fts_table_name, IBD, false);
fts_sql_rollback(trx); if (path != NULL)
break; {
os_file_delete_if_exists(innodb_data_file_key, path , NULL);
ut_free(path);
} }
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) { /** Drop all orphaned FTS auxiliary tables, those that don't have
ut_ad(count != ib_vector_size(tables)); a parent table or FTS index defined on them. */
void fts_drop_orphaned_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 fts_space_set_t fts_space_set;
the reverting. */ fil_get_fts_spaces(fts_space_set);
ut_ad(!trx_is_started(trx)); if (fts_space_set.empty())
return;
bool not_rename = false; fts_check_orphaned_tables(fts_space_set);
/* Try to revert those succesful rename operations if (fts_space_set.empty())
in order to revert the ibd file rename. */ return;
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*>( trx_t* trx= trx_create();
ib_vector_get(tables, i)); trx->op_info= "Drop orphaned aux FTS tables";
row_mysql_lock_data_dictionary(trx);
table = dict_table_open_on_id(aux_table->id, TRUE, 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); DICT_TABLE_OP_NORMAL);
ut_ad(table != NULL); if (!table)
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; 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); FTS_INIT_FTS_TABLE(&fts_table, NULL, FTS_COMMON_TABLE, table);
err = row_rename_table_for_mysql(table->name.m_name, fts_drop_common_tables(trx, &fts_table, true);
aux_table->name,
trx_bg, false, false);
trx_bg->dict_operation_lock_mode = 0; fts_table.type= FTS_INDEX_TABLE;
dict_table_close(table, TRUE, FALSE); fts_table.index_id= it->second;
fts_drop_all_aux_tables(trx, &fts_table);
if (err != DB_SUCCESS) { dict_table_close(table, true, false);
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();
} }
trx_commit_for_mysql(trx);
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 */
UNIV_INLINE
int
fts_check_aux_table_parent_id_cmp(
/*==============================*/
const void* p1, /*!< in: id1 */
const void* p2) /*!< in: id2 */
{
const fts_aux_table_t* fa1 = static_cast<const fts_aux_table_t*>(p1);
const fts_aux_table_t* fa2 = static_cast<const fts_aux_table_t*>(p2);
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)) {
ib::warn() << "Parent table of FTS auxiliary table "
<< aux_drop_table->name << " not found.";
dberr_t err = fts_drop_table(trx, aux_drop_table->name);
if (err == DB_FAIL) {
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 */
{
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;
}
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);
row_mysql_unlock_data_dictionary(trx); row_mysql_unlock_data_dictionary(trx);
trx->dict_operation_lock_mode= 0;
trx->free(); trx->free();
if (heap != NULL) {
mem_heap_free(heap);
}
} }
/**********************************************************************//** /**********************************************************************//**
......
...@@ -55,28 +55,23 @@ fts_get_table_id( ...@@ -55,28 +55,23 @@ fts_get_table_id(
long */ long */
{ {
int len; 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); ut_a(fts_table->table != NULL);
switch (fts_table->type) { switch (fts_table->type) {
case FTS_COMMON_TABLE: case FTS_COMMON_TABLE:
len = fts_write_object_id(fts_table->table_id, table_id, len = fts_write_object_id(fts_table->table_id, table_id);
hex_name);
break; break;
case FTS_INDEX_TABLE: case FTS_INDEX_TABLE:
len = fts_write_object_id(fts_table->table_id, table_id, len = fts_write_object_id(fts_table->table_id, table_id);
hex_name);
table_id[len] = '_'; table_id[len] = '_';
++len; ++len;
table_id += len; table_id += len;
len += fts_write_object_id(fts_table->index_id, table_id, len += fts_write_object_id(fts_table->index_id, table_id);
hex_name);
break; break;
default: default:
......
...@@ -736,12 +736,9 @@ fts_savepoint_rollback_last_stmt( ...@@ -736,12 +736,9 @@ fts_savepoint_rollback_last_stmt(
/*=============================*/ /*=============================*/
trx_t* trx); /*!< in: transaction */ 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. */ table or FTS index defined on them. */
void void fts_drop_orphaned_tables();
fts_drop_orphaned_tables(void);
/*==========================*/
/** Run SYNC on the table, i.e., write out data from the cache to the /** 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. FTS auxiliary INDEX table and clear the cache at the end.
...@@ -775,15 +772,6 @@ fts_init_doc_id( ...@@ -775,15 +772,6 @@ fts_init_doc_id(
/*============*/ /*============*/
const dict_table_t* table); /*!< in: table */ 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. */ compare two character string according to their charset. */
extern extern
...@@ -990,4 +978,14 @@ and there are no new fts index to add. ...@@ -990,4 +978,14 @@ and there are no new fts index to add.
@param[in] trx transaction to drop all fts tables */ @param[in] trx transaction to drop all fts tables */
void fts_clear_all(dict_table_t *table, trx_t *trx); 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 */ #endif /*!< fts0fts.h */
...@@ -461,11 +461,7 @@ int ...@@ -461,11 +461,7 @@ int
fts_write_object_id( fts_write_object_id(
/*================*/ /*================*/
ib_id_t id, /*!< in: a table/index id */ ib_id_t id, /*!< in: a table/index id */
char* str, /*!< in: buffer to write the id to */ 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));
/******************************************************************//** /******************************************************************//**
Read the table id from the string generated by fts_write_object_id(). Read the table id from the string generated by fts_write_object_id().
@return TRUE if parse successful */ @return TRUE if parse successful */
......
...@@ -32,10 +32,7 @@ int ...@@ -32,10 +32,7 @@ int
fts_write_object_id( fts_write_object_id(
/*================*/ /*================*/
ib_id_t id, /* in: a table/index id */ ib_id_t id, /* in: a table/index id */
char* str, /* in: buffer to write the id to */ 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 */
{ {
#ifdef _WIN32 #ifdef _WIN32
...@@ -60,11 +57,6 @@ fts_write_object_id( ...@@ -60,11 +57,6 @@ fts_write_object_id(
#endif /* _WIN32 */ #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)); return(sprintf(str, "%016llx", (ulonglong) id));
} }
......
...@@ -637,6 +637,57 @@ lock_rec_get_insert_intention( ...@@ -637,6 +637,57 @@ lock_rec_get_insert_intention(
return(lock->type_mode & LOCK_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. 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 */ @return TRUE if new lock has to wait for lock2 to be removed */
...@@ -743,75 +794,9 @@ lock_rec_has_to_wait( ...@@ -743,75 +794,9 @@ lock_rec_has_to_wait(
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF /* There should not be two conflicting locks that are
thread, we need to look at trx ordering and lock types */ brute force. If there is it is a bug. */
if (wsrep_thd_is_BF(trx->mysql_thd, FALSE) wsrep_assert_no_bf_bf_wait(NULL, lock2, trx);
&& 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;
}
}
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
return true; return true;
...@@ -1471,11 +1456,8 @@ lock_rec_create_low( ...@@ -1471,11 +1456,8 @@ lock_rec_create_low(
trx_mutex_exit(c_lock->trx); trx_mutex_exit(c_lock->trx);
if (UNIV_UNLIKELY(wsrep_debug)) { if (UNIV_UNLIKELY(wsrep_debug)) {
ib::info() << "WSREP: c_lock canceled " wsrep_report_bf_lock_wait(trx->mysql_thd, trx->id);
<< ib::hex(c_lock->trx->id) wsrep_report_bf_lock_wait(c_lock->trx->mysql_thd, c_lock->trx->id);
<< " SQL: "
<< wsrep_thd_query(
c_lock->trx->mysql_thd);
} }
/* have to bail out here to avoid lock_set_lock... */ /* have to bail out here to avoid lock_set_lock... */
...@@ -1554,6 +1536,7 @@ lock_rec_insert_by_trx_age( ...@@ -1554,6 +1536,7 @@ lock_rec_insert_by_trx_age(
hash_table_t* hash; hash_table_t* hash;
hash_cell_t* cell; hash_cell_t* cell;
ut_ad(!in_lock->trx->is_wsrep());
space = in_lock->un_member.rec_lock.space; space = in_lock->un_member.rec_lock.space;
page_no = in_lock->un_member.rec_lock.page_no; page_no = in_lock->un_member.rec_lock.page_no;
rec_fold = lock_rec_fold(space, page_no); rec_fold = lock_rec_fold(space, page_no);
...@@ -1821,27 +1804,19 @@ lock_rec_add_to_queue( ...@@ -1821,27 +1804,19 @@ lock_rec_add_to_queue(
= lock_rec_other_has_expl_req( = lock_rec_other_has_expl_req(
mode, block, false, heap_no, trx); mode, block, false, heap_no, trx);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (other_lock && trx->is_wsrep() && if (UNIV_UNLIKELY(other_lock && trx->is_wsrep())) {
!wsrep_thd_is_BF(trx->mysql_thd, FALSE) && /* Only BF transaction may be granted lock
!wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE)) { before other conflicting lock request. */
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)
ib::info() << "WSREP BF lock conflict for my lock:\n BF:" << && !wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE)) {
((wsrep_thd_is_BF(trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << /* If it is not BF, this case is a bug. */
wsrep_thd_exec_mode(trx->mysql_thd) << " conflict: " << wsrep_report_bf_lock_wait(trx->mysql_thd, trx->id);
wsrep_thd_conflict_state(trx->mysql_thd, false) << " seqno: " << wsrep_report_bf_lock_wait(other_lock->trx->mysql_thd, other_lock->trx->id);
wsrep_thd_trx_seqno(trx->mysql_thd) << " SQL: " << ut_error;
wsrep_thd_query(trx->mysql_thd); }
trx_t* otrx = other_lock->trx; } else
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);
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
ut_ad(!other_lock);
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
...@@ -2047,9 +2022,6 @@ lock_rec_has_to_wait_in_queue( ...@@ -2047,9 +2022,6 @@ lock_rec_has_to_wait_in_queue(
hash = lock_hash_get(wait_lock->type_mode); hash = lock_hash_get(wait_lock->type_mode);
for (lock = lock_rec_get_first_on_page_addr(hash, space, page_no); for (lock = lock_rec_get_first_on_page_addr(hash, space, page_no);
#ifdef WITH_WSREP
lock &&
#endif
lock != wait_lock; lock != wait_lock;
lock = lock_rec_get_next_on_page_const(lock)) { lock = lock_rec_get_next_on_page_const(lock)) {
const byte* p = (const byte*) &lock[1]; const byte* p = (const byte*) &lock[1];
...@@ -2057,24 +2029,6 @@ lock_rec_has_to_wait_in_queue( ...@@ -2057,24 +2029,6 @@ lock_rec_has_to_wait_in_queue(
if (heap_no < lock_rec_get_n_bits(lock) if (heap_no < lock_rec_get_n_bits(lock)
&& (p[bit_offset] & bit_mask) && (p[bit_offset] & bit_mask)
&& lock_has_to_wait(wait_lock, lock)) { && 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); return(lock);
} }
} }
...@@ -2190,6 +2144,7 @@ lock_grant_and_move_on_page(ulint rec_fold, ulint space, ulint page_no) ...@@ -2190,6 +2144,7 @@ lock_grant_and_move_on_page(ulint rec_fold, ulint space, ulint page_no)
lock = previous->hash; lock = previous->hash;
} }
ut_ad(!lock->trx->is_wsrep());
ut_ad(previous->hash == lock || previous == lock); ut_ad(previous->hash == lock || previous == lock);
/* Grant locks if there are no conflicting locks ahead. /* Grant locks if there are no conflicting locks ahead.
Move granted locks to the head of the list. */ Move granted locks to the head of the list. */
...@@ -2260,11 +2215,18 @@ static void lock_rec_dequeue_from_page(lock_t* in_lock) ...@@ -2260,11 +2215,18 @@ static void lock_rec_dequeue_from_page(lock_t* in_lock)
lock != NULL; lock != NULL;
lock = lock_rec_get_next_on_page(lock)) { lock = lock_rec_get_next_on_page(lock)) {
if (lock_get_wait(lock) if (!lock_get_wait(lock)) {
&& !lock_rec_has_to_wait_in_queue(lock)) { continue;
}
const lock_t* c = lock_rec_has_to_wait_in_queue(lock);
if (!c) {
/* Grant the lock */ /* Grant the lock */
ut_ad(lock->trx != in_lock->trx); ut_ad(lock->trx != in_lock->trx);
lock_grant(lock); lock_grant(lock);
#ifdef WITH_WSREP
} else {
wsrep_assert_no_bf_bf_wait(c, lock, c->trx);
#endif /* WITH_WSREP */
} }
} }
} else { } else {
...@@ -3528,11 +3490,8 @@ lock_table_create( ...@@ -3528,11 +3490,8 @@ lock_table_create(
ut_list_insert(table->locks, c_lock, lock, ut_list_insert(table->locks, c_lock, lock,
TableLockGetNode()); TableLockGetNode());
if (UNIV_UNLIKELY(wsrep_debug)) { if (UNIV_UNLIKELY(wsrep_debug)) {
ib::info() << "table lock BF conflict for " wsrep_report_bf_lock_wait(trx->mysql_thd, trx->id);
<< ib::hex(c_lock->trx->id) wsrep_report_bf_lock_wait(c_lock->trx->mysql_thd, c_lock->trx->id);
<< " SQL: "
<< wsrep_thd_query(
c_lock->trx->mysql_thd);
} }
} else { } else {
ut_list_append(table->locks, lock, TableLockGetNode()); ut_list_append(table->locks, lock, TableLockGetNode());
...@@ -3544,6 +3503,8 @@ lock_table_create( ...@@ -3544,6 +3503,8 @@ lock_table_create(
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (UNIV_UNLIKELY(wsrep_debug)) { 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); wsrep_print_wait_locks(c_lock);
} }
...@@ -3553,14 +3514,6 @@ lock_table_create( ...@@ -3553,14 +3514,6 @@ lock_table_create(
lock_cancel_waiting_and_release( lock_cancel_waiting_and_release(
c_lock->trx->lock.wait_lock); c_lock->trx->lock.wait_lock);
trx_mutex_enter(trx); 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); trx_mutex_exit(c_lock->trx);
...@@ -4119,6 +4072,7 @@ lock_grant_and_move_on_rec( ...@@ -4119,6 +4072,7 @@ lock_grant_and_move_on_rec(
} }
lock = previous->hash; lock = previous->hash;
} }
ut_ad(!lock->trx->is_wsrep());
/* Grant locks if there are no conflicting locks ahead. /* Grant locks if there are no conflicting locks ahead.
Move granted locks to the head of the list. */ Move granted locks to the head of the list. */
for (;lock != NULL;) { for (;lock != NULL;) {
...@@ -4218,12 +4172,18 @@ lock_rec_unlock( ...@@ -4218,12 +4172,18 @@ lock_rec_unlock(
for (lock = first_lock; lock != NULL; for (lock = first_lock; lock != NULL;
lock = lock_rec_get_next(heap_no, lock)) { lock = lock_rec_get_next(heap_no, lock)) {
if (lock_get_wait(lock) if (!lock_get_wait(lock)) {
&& !lock_rec_has_to_wait_in_queue(lock)) { continue;
}
const lock_t* c = lock_rec_has_to_wait_in_queue(lock);
if (!c) {
/* Grant the lock */ /* Grant the lock */
ut_ad(trx != lock->trx); ut_ad(trx != lock->trx);
lock_grant(lock); lock_grant(lock);
#ifdef WITH_WSREP
} else {
wsrep_assert_no_bf_bf_wait(c, lock, c->trx);
#endif /* WITH_WSREP */
} }
} }
} else { } else {
...@@ -4893,24 +4853,28 @@ lock_rec_queue_validate( ...@@ -4893,24 +4853,28 @@ lock_rec_queue_validate(
explicit granted lock. */ explicit granted lock. */
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (other_lock->trx->is_wsrep()) { /** Galera record locking rules:
if (!lock_get_wait(other_lock) ) { * If there is no other record lock to the same record, we may grant
ib::info() << "WSREP impl BF lock conflict for my impl lock:\n BF:" << the lock request.
((wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << * If there is other record lock but this requested record lock is
wsrep_thd_exec_mode(impl_trx->mysql_thd) << " conflict: " << compatible, we may grant the lock request.
wsrep_thd_conflict_state(impl_trx->mysql_thd, false) << " seqno: " << * If there is other record lock and it is not compatible with
wsrep_thd_trx_seqno(impl_trx->mysql_thd) << " SQL: " << requested lock, all normal transactions must wait.
wsrep_thd_query(impl_trx->mysql_thd); * BF (brute force) additional exceptions :
** If BF already holds record lock for requested record, we may
trx_t* otrx = other_lock->trx; grant new record lock even if there is conflicting record lock(s)
waiting on a queue.
ib::info() << "WSREP other lock:\n BF:" << ** If conflicting transaction holds requested record lock,
((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << we will cancel this record lock and select conflicting transaction
wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " << for BF abort or kill victim.
wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " << ** If conflicting transaction is waiting for requested record lock
wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " << we will cancel this wait and select conflicting transaction
wsrep_thd_query(otrx->mysql_thd); 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, if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
block, heap_no, block, heap_no,
...@@ -4919,10 +4883,12 @@ lock_rec_queue_validate( ...@@ -4919,10 +4883,12 @@ lock_rec_queue_validate(
} }
} else } else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
{
ut_ad(lock_get_wait(other_lock)); ut_ad(lock_get_wait(other_lock));
ut_ad(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, ut_ad(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
block, heap_no, impl_trx)); block, heap_no, impl_trx));
} }
}
mutex_exit(&impl_trx->mutex); mutex_exit(&impl_trx->mutex);
} }
...@@ -4953,13 +4919,20 @@ lock_rec_queue_validate( ...@@ -4953,13 +4919,20 @@ lock_rec_queue_validate(
mode, block, false, heap_no, mode, block, false, heap_no,
lock->trx); lock->trx);
#ifdef WITH_WSREP #ifdef WITH_WSREP
ut_a(!other_lock if (UNIV_UNLIKELY(other_lock && lock->trx->is_wsrep())) {
|| wsrep_thd_is_BF(lock->trx->mysql_thd, FALSE) /* Only BF transaction may be granted
|| wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE)); lock before other conflicting lock
request. */
#else if (!wsrep_thd_is_BF(lock->trx->mysql_thd, FALSE)
ut_a(!other_lock); && !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 */ #endif /* WITH_WSREP */
ut_ad(!other_lock);
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) { } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
ut_a(lock_rec_has_to_wait_in_queue(lock)); ut_a(lock_rec_has_to_wait_in_queue(lock));
......
...@@ -911,8 +911,6 @@ row_ins_foreign_fill_virtual( ...@@ -911,8 +911,6 @@ row_ins_foreign_fill_virtual(
&ext, cascade->heap); &ext, cascade->heap);
n_diff = update->n_fields; n_diff = update->n_fields;
update->n_fields += n_v_fld;
if (index->table->vc_templ == NULL) { if (index->table->vc_templ == NULL) {
/** This can occur when there is a cascading /** This can occur when there is a cascading
delete or update after restart. */ delete or update after restart. */
...@@ -945,7 +943,7 @@ row_ins_foreign_fill_virtual( ...@@ -945,7 +943,7 @@ row_ins_foreign_fill_virtual(
return DB_COMPUTE_VALUE_FAILED; 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*>( upd_field->old_v_val = static_cast<dfield_t*>(
mem_heap_alloc(cascade->heap, mem_heap_alloc(cascade->heap,
...@@ -955,29 +953,26 @@ row_ins_foreign_fill_virtual( ...@@ -955,29 +953,26 @@ row_ins_foreign_fill_virtual(
upd_field_set_v_field_no(upd_field, i, index); upd_field_set_v_field_no(upd_field, i, index);
if (node->is_delete bool set_null =
node->is_delete
? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
: (foreign->type & DICT_FOREIGN_ON_UPDATE_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( dfield_t* new_vfield = innobase_get_computed_value(
update->old_vrow, col, index, update->old_vrow, col, index,
&vc.heap, update->heap, NULL, thd, &vc.heap, update->heap, NULL, thd,
mysql_table, record, NULL, mysql_table, record, NULL,
node->update, foreign); set_null ? update : node->update, foreign);
if (new_vfield == NULL) { if (new_vfield == NULL) {
return DB_COMPUTE_VALUE_FAILED; return DB_COMPUTE_VALUE_FAILED;
} }
dfield_copy(&(upd_field->new_val), new_vfield); 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++; n_diff++;
} }
......
...@@ -3937,9 +3937,21 @@ row_drop_database_for_mysql( ...@@ -3937,9 +3937,21 @@ row_drop_database_for_mysql(
avoid accessing dropped fts aux tables in information avoid accessing dropped fts aux tables in information
scheam when parent table still exists. scheam when parent table still exists.
Note: Drop parent table will drop fts aux tables. */ Note: Drop parent table will drop fts aux tables. */
char* parent_table_name; char* parent_table_name = NULL;
parent_table_name = fts_get_parent_table_name( table_id_t table_id;
table_name, strlen(table_name)); 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) { if (parent_table_name != NULL) {
ut_free(table_name); ut_free(table_name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment