Commit c62e49d0 authored by Julius Goryavsky's avatar Julius Goryavsky

MDEV-16656: DROP DATABASE crashes the Galera Cluster

When converting table identifiers to a new format,
some tables can be renamed twice, which subsequently
leads to the appearance of "false" auxiliary tables
belonging to another main (parent) table (which does
not actually have auxiliary tables).

This is because the table number is repeatedly added
to the aux_tables_to_rename vector inside the function
fts_check_and_drop_orphaned_tables.

To correct this error, we must add a check for the
occurrence of the table number in the aux_tables_to_rename
vector before adding a new element.

https://jira.mariadb.org/browse/MDEV-16656
parent 82524239
CREATE DATABASE fts;
USE fts;
CREATE TABLE fts_t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
CREATE TABLE fts_t2 (f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
INSERT INTO fts_t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
INSERT INTO fts_t2 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
DROP TABLE ten;
UPDATE fts_t1 SET f2 = 'abcd';
UPDATE fts_t2 SET f2 = 'efjh';
USE fts;
DROP TABLE fts_t1;
DROP TABLE fts_t2;
SHOW TABLES;
Tables_in_fts
DROP DATABASE fts;
#
# This test tests a DROP empty database
#
--source include/galera_cluster.inc
--source include/have_innodb.inc
# Save original auto_increment_offset values.
--let $node_1=node_1
--let $node_2=node_2
--source include/auto_increment_offset_save.inc
CREATE DATABASE fts;
USE fts;
CREATE TABLE fts_t1 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
CREATE TABLE fts_t2 (f2 VARCHAR(100), FULLTEXT (f2)) ENGINE=InnoDB;
# Insert 1K rows
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
INSERT INTO fts_t1 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
INSERT INTO fts_t2 (f2) SELECT 'foobarbaz' FROM ten AS a1, ten AS a2, ten AS a3;
DROP TABLE ten;
UPDATE fts_t1 SET f2 = 'abcd';
UPDATE fts_t2 SET f2 = 'efjh';
--connection node_2
let $wsrep_cluster_address = `SELECT @@global.wsrep_node_incoming_address`;
--source include/restart_mysqld.inc
--connection node_1
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
--let $galera_connection_name = node_2a
--let $galera_server_number = 2
--source include/galera_connect.inc
--connection node_2a
--source include/wait_until_ready.inc
--connection node_1
--let $restart_parameters = --wsrep-cluster-address=gcomm://$wsrep_cluster_address
--source include/restart_mysqld.inc
--connection node_2a
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
--let $galera_connection_name = node_1a
--let $galera_server_number = 1
--source include/galera_connect.inc
--connection node_1a
--source include/wait_until_ready.inc
USE fts;
DROP TABLE fts_t1;
DROP TABLE fts_t2;
SHOW TABLES;
DROP DATABASE fts;
# Restore original auto_increment_offset values.
--let $node_1=node_1a
--let $node_2=node_2a
--source include/auto_increment_offset_restore.inc
--source include/galera_end.inc
......@@ -2762,7 +2762,7 @@ fts_cmp_set_sync_doc_id(
mutex_enter(&cache->doc_id_lock);
/* For each sync operation, we will add next_doc_id by 1,
so to mark a sync operation */
if (cache->next_doc_id < cache->synced_doc_id + 1) {
if (cache->next_doc_id <= cache->synced_doc_id) {
cache->next_doc_id = cache->synced_doc_id + 1;
}
mutex_exit(&cache->doc_id_lock);
......@@ -6665,7 +6665,6 @@ fts_rename_aux_tables_to_hex_format(
"All the fts index associated with the table are "
"marked as corrupted. Please rebuild the "
"index again.", parent_table->name);
fts_sql_rollback(trx_rename);
/* Corrupting the fts index related to parent table. */
trx_t* trx_corrupt;
......@@ -7042,7 +7041,27 @@ fts_check_and_drop_orphaned_tables(
/* If the aux table is in decimal format, we should
rename it, so push it to aux_tables_to_rename */
if (!drop && rename) {
ib_vector_push(aux_tables_to_rename, aux_table);
/* It is necessary to check that the table with
this name is missing in the vector - otherwise it
can be renamed twice: */
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)) {
......
......@@ -2761,7 +2761,7 @@ fts_cmp_set_sync_doc_id(
mutex_enter(&cache->doc_id_lock);
/* For each sync operation, we will add next_doc_id by 1,
so to mark a sync operation */
if (cache->next_doc_id < cache->synced_doc_id + 1) {
if (cache->next_doc_id <= cache->synced_doc_id) {
cache->next_doc_id = cache->synced_doc_id + 1;
}
mutex_exit(&cache->doc_id_lock);
......@@ -6664,7 +6664,6 @@ fts_rename_aux_tables_to_hex_format(
"All the fts index associated with the table are "
"marked as corrupted. Please rebuild the "
"index again.", parent_table->name);
fts_sql_rollback(trx_rename);
/* Corrupting the fts index related to parent table. */
trx_t* trx_corrupt;
......@@ -7041,7 +7040,27 @@ fts_check_and_drop_orphaned_tables(
/* If the aux table is in decimal format, we should
rename it, so push it to aux_tables_to_rename */
if (!drop && rename) {
ib_vector_push(aux_tables_to_rename, aux_table);
/* It is necessary to check that the table with
this name is missing in the vector - otherwise it
can be renamed twice: */
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)) {
......
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