summaryrefslogtreecommitdiff
path: root/sql/sql_admin.cc
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-11-13 21:54:21 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-11-13 21:54:21 +0200
commitd7a582489900ea175d9659304c4fdc39b3880014 (patch)
tree06a2485b15b84fedf197c573276441ea8d8bccb0 /sql/sql_admin.cc
parent97569d3c37a66bc941b933ac7c2cefa5430a5175 (diff)
parentb2029c0300bf8c311ff5d9fdc4b73a9e48bf6930 (diff)
downloadmariadb-git-d7a582489900ea175d9659304c4fdc39b3880014.tar.gz
Merge 10.4 into 10.5
Diffstat (limited to 'sql/sql_admin.cc')
-rw-r--r--sql/sql_admin.cc108
1 files changed, 81 insertions, 27 deletions
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index dc9b971f2ed..2d6f891f56f 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2010, 2015, Oracle and/or its affiliates.
- Copyright (c) 2011, 2019, MariaDB
+ Copyright (c) 2011, 2020, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@
#include "strfunc.h"
#include "sql_admin.h"
#include "sql_statistics.h"
-
+#include "wsrep_mysqld.h"
/* Prepare, run and cleanup for mysql_recreate_table() */
static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
@@ -90,10 +90,10 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table,
static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
HA_CHECK_OPT *check_opt)
{
- int error= 0;
+ int error= 0, create_error= 0;
TABLE tmp_table, *table;
TABLE_LIST *pos_in_locked_tables= 0;
- TABLE_SHARE *share;
+ TABLE_SHARE *share= 0;
bool has_mdl_lock= FALSE;
char from[FN_REFLEN],tmp[FN_REFLEN+32];
const char **ext;
@@ -206,6 +206,17 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
HA_EXTRA_NOT_USED, NULL);
table_list->table= 0;
}
+ else
+ {
+ /*
+ Table open failed, maybe because we run out of memory.
+ Close all open tables and relaese all MDL locks
+ */
+ tdc_release_share(share);
+ share->tdc->flush(thd, true);
+ share= 0;
+ }
+
/*
After this point we have an exclusive metadata lock on our table
in both cases when table was successfully open in mysql_admin_table()
@@ -219,11 +230,8 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
goto end;
}
if (dd_recreate_table(thd, table_list->db.str, table_list->table_name.str))
- {
- error= send_check_errmsg(thd, table_list, "repair",
- "Failed generating table from .frm file");
- goto end;
- }
+ create_error= send_check_errmsg(thd, table_list, "repair",
+ "Failed generating table from .frm file");
/*
'FALSE' for 'using_transactions' means don't postpone
invalidation till the end of a transaction, but do it
@@ -236,6 +244,8 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
"Failed restoring .MYD file");
goto end;
}
+ if (create_error)
+ goto end;
if (thd->locked_tables_list.locked_tables())
{
@@ -263,7 +273,8 @@ end:
if (table == &tmp_table)
{
closefrm(table);
- tdc_release_share(table->s);
+ if (share)
+ tdc_release_share(share);
}
/* In case of a temporary table there will be no metadata lock. */
if (unlikely(error) && has_mdl_lock)
@@ -418,6 +429,50 @@ dbug_err:
return open_error;
}
+#ifdef WITH_WSREP
+ /*
+ OPTIMIZE, REPAIR and ALTER may take MDL locks not only for the affected table, but
+ also for the table referenced by foreign key constraint.
+ This wsrep_toi_replication() function handles TOI replication for OPTIMIZE and REPAIR
+ so that certification keys for potential FK parent tables are also appended in the
+ write set.
+ ALTER TABLE case is handled elsewhere.
+ */
+static bool wsrep_toi_replication(THD *thd, TABLE_LIST *tables)
+{
+ if (!WSREP(thd) || !WSREP_CLIENT(thd)) return false;
+
+ LEX *lex= thd->lex;
+ /* only handle OPTIMIZE and REPAIR here */
+ switch (lex->sql_command)
+ {
+ case SQLCOM_OPTIMIZE:
+ case SQLCOM_REPAIR:
+ break;
+ default:
+ return false;
+ }
+
+ close_thread_tables(thd);
+ wsrep::key_array keys;
+
+ wsrep_append_fk_parent_table(thd, tables, &keys);
+
+ /* now TOI replication, with no locks held */
+ if (keys.empty())
+ {
+ WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, tables);
+ } else {
+ WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, tables, &keys) {
+ return true;
+ }
+ }
+ return false;
+
+ wsrep_error_label:
+ return true;
+}
+#endif /* WITH_WSREP */
/*
RETURN VALUES
@@ -486,6 +541,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
close_thread_tables(thd);
for (table= tables; table; table= table->next_local)
table->table= NULL;
+#ifdef WITH_WSREP
+ if (wsrep_toi_replication(thd, tables))
+ {
+ WSREP_INFO("wsrep TOI replication of has failed, skipping OPTIMIZE");
+ goto err;
+ }
+#endif /* WITH_WSREP */
for (table= tables; table; table= table->next_local)
{
@@ -592,6 +654,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
#endif
DBUG_PRINT("admin", ("table: %p", table->table));
+ if (table->schema_table)
+ {
+ result_code= HA_ADMIN_NOT_IMPLEMENTED;
+ goto send_result;
+ }
+
if (prepare_func)
{
DBUG_PRINT("admin", ("calling prepare_func"));
@@ -650,12 +718,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
goto send_result;
}
- if (table->schema_table)
- {
- result_code= HA_ADMIN_NOT_IMPLEMENTED;
- goto send_result;
- }
-
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
/* purecov: begin inspected */
@@ -1338,10 +1400,10 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
-error:
#ifdef WITH_WSREP
-wsrep_error_label:
-#endif
+ wsrep_error_label:
+#endif /* WITH_WSREP */
+error:
DBUG_RETURN(res);
}
@@ -1380,7 +1442,6 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
- WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
res= (specialflag & SPECIAL_NO_NEW_FUNC) ?
mysql_recreate_table(thd, first_table, true) :
@@ -1399,9 +1460,6 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
m_lex->query_tables= first_table;
error:
-#ifdef WITH_WSREP
-wsrep_error_label:
-#endif
DBUG_RETURN(res);
}
@@ -1416,7 +1474,6 @@ bool Sql_cmd_repair_table::execute(THD *thd)
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
- WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "repair",
TL_WRITE, 1,
MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM),
@@ -1435,8 +1492,5 @@ bool Sql_cmd_repair_table::execute(THD *thd)
m_lex->query_tables= first_table;
error:
-#ifdef WITH_WSREP
-wsrep_error_label:
-#endif
DBUG_RETURN(res);
}