diff options
Diffstat (limited to 'sql/sql_admin.cc')
-rw-r--r-- | sql/sql_admin.cc | 119 |
1 files changed, 74 insertions, 45 deletions
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 213d77f8237..060dcc059b5 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -26,13 +26,15 @@ #include "sql_view.h" // view_checksum #include "sql_table.h" // mysql_recreate_table #include "debug_sync.h" // DEBUG_SYNC -#include "sql_acl.h" // *_ACL #include "sp.h" // Sroutine_hash_entry #include "sql_parse.h" // check_table_access #include "strfunc.h" #include "sql_admin.h" #include "sql_statistics.h" #include "wsrep_mysqld.h" + +const LEX_CSTRING msg_status= {STRING_WITH_LEN("status")}; + /* Prepare, run and cleanup for mysql_recreate_table() */ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list) @@ -122,9 +124,9 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, Let us try to open at least a .FRM for this table. */ - table_list->mdl_request.init(MDL_key::TABLE, - table_list->db.str, table_list->table_name.str, - MDL_EXCLUSIVE, MDL_TRANSACTION); + MDL_REQUEST_INIT(&table_list->mdl_request, MDL_key::TABLE, + table_list->db.str, table_list->table_name.str, + MDL_EXCLUSIVE, MDL_TRANSACTION); if (lock_table_names(thd, table_list, table_list->next_global, thd->variables.lock_wait_timeout, 0)) @@ -213,15 +215,9 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, Table open failed, maybe because we run out of memory. Close all open tables and relaese all MDL locks */ -#if MYSQL_VERSION < 100500 - tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED, - table->s->db.str, table->s->table_name.str, - TRUE); -#else tdc_release_share(share); share->tdc->flush(thd, true); share= 0; -#endif } /* @@ -437,6 +433,21 @@ dbug_err: } + +static void send_read_only_warning(THD *thd, const LEX_CSTRING *msg_status, + const LEX_CSTRING *table_name) +{ + Protocol *protocol= thd->protocol; + char buf[MYSQL_ERRMSG_SIZE]; + size_t length; + length= my_snprintf(buf, sizeof(buf), + ER_THD(thd, ER_OPEN_AS_READONLY), + table_name->str); + protocol->store(msg_status, system_charset_info); + protocol->store(buf, length, system_charset_info); +} + + /* RETURN VALUES FALSE Message sent to net (admin operation went ok) @@ -510,7 +521,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, for (table= tables; table; table= table->next_local) { - char table_name[SAFE_NAME_LEN*2+2]; + char table_name_buff[SAFE_NAME_LEN*2+2]; + LEX_CSTRING table_name= { table_name_buff, 0}; const char *db= table->db.str; bool fatal_error=0; bool open_error; @@ -520,7 +532,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, DBUG_PRINT("admin", ("table: '%s'.'%s'", db, table->table_name.str)); DEBUG_SYNC(thd, "admin_command_kill_before_modify"); - strxmov(table_name, db, ".", table->table_name.str, NullS); + table_name.length= strxmov(table_name_buff, db, ".", table->table_name.str, + NullS) - table_name_buff; thd->open_options|= extra_open_options; table->lock_type= lock_type; /* @@ -577,8 +590,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, close_thread_tables(thd); table->table= NULL; thd->release_transactional_locks(); - table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str, - MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION); + MDL_REQUEST_INIT(&table->mdl_request, MDL_key::TABLE, table->db.str, + table->table_name.str, MDL_SHARED_NO_READ_WRITE, + MDL_TRANSACTION); } #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -605,12 +619,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, size_t length; DBUG_PRINT("admin", ("sending non existent partition error")); protocol->prepare_for_resend(); - protocol->store(table_name, system_charset_info); + protocol->store(&table_name, system_charset_info); protocol->store(operator_name, system_charset_info); protocol->store(STRING_WITH_LEN("error"), system_charset_info); length= my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_DROP_PARTITION_NON_EXISTENT), - table_name); + table_name.str); protocol->store(buff, length, system_charset_info); if(protocol->write()) goto err; @@ -686,20 +700,17 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, goto send_result; } - if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify) + if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify && + operator_func != &handler::ha_analyze) { /* purecov: begin inspected */ - char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; - size_t length; enum_sql_command save_sql_command= lex->sql_command; + LEX_CSTRING error_clex_str= { STRING_WITH_LEN("error") }; DBUG_PRINT("admin", ("sending error message")); protocol->prepare_for_resend(); - protocol->store(table_name, system_charset_info); + protocol->store(&table_name, system_charset_info); protocol->store(operator_name, system_charset_info); - protocol->store(STRING_WITH_LEN("error"), system_charset_info); - length= my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_OPEN_AS_READONLY), - table_name); - protocol->store(buff, length, system_charset_info); + send_read_only_warning(thd, &error_clex_str, &table_name); trans_commit_stmt(thd); trans_commit(thd); close_thread_tables(thd); @@ -754,7 +765,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, /* purecov: begin inspected */ DBUG_PRINT("admin", ("sending crashed warning")); protocol->prepare_for_resend(); - protocol->store(table_name, system_charset_info); + protocol->store(&table_name, system_charset_info); protocol->store(operator_name, system_charset_info); protocol->store(STRING_WITH_LEN("warning"), system_charset_info); protocol->store(STRING_WITH_LEN("Table is marked as crashed"), @@ -825,6 +836,15 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (compl_result_code == HA_ADMIN_OK && collect_eis) { + if (result_code == HA_ERR_TABLE_READONLY) + { + protocol->prepare_for_resend(); + protocol->store(&table_name, system_charset_info); + protocol->store(operator_name, system_charset_info); + send_read_only_warning(thd, &msg_status, &table_name); + (void) protocol->write(); + result_code= HA_ADMIN_OK; + } /* Here we close and reopen table in read mode because operation of collecting statistics is long and it will be better do not block @@ -837,8 +857,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, close_thread_tables(thd); table->table= NULL; thd->release_transactional_locks(); - table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str, - MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION); + MDL_REQUEST_INIT(&table->mdl_request, MDL_key::TABLE, table->db.str, + table->table_name.str, MDL_SHARED_NO_READ_WRITE, + MDL_TRANSACTION); table->mdl_request.set_type(MDL_SHARED_READ); table->lock_type= TL_READ; @@ -931,9 +952,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, else { protocol->prepare_for_resend(); - protocol->store(table_name, system_charset_info); + protocol->store(&table_name, system_charset_info); protocol->store(operator_name, system_charset_info); - protocol->store(STRING_WITH_LEN("status"), system_charset_info); + protocol->store(&msg_status, system_charset_info); protocol->store(STRING_WITH_LEN("Engine-independent statistics collected"), system_charset_info); if (protocol->write()) @@ -960,7 +981,7 @@ send_result: while ((err= it++)) { protocol->prepare_for_resend(); - protocol->store(table_name, system_charset_info); + protocol->store(&table_name, system_charset_info); protocol->store((char*) operator_name, system_charset_info); protocol->store(warning_level_names[err->get_level()].str, warning_level_names[err->get_level()].length, @@ -972,7 +993,7 @@ send_result: thd->get_stmt_da()->clear_warning_info(thd->query_id); } protocol->prepare_for_resend(); - protocol->store(table_name, system_charset_info); + protocol->store(&table_name, system_charset_info); protocol->store(operator_name, system_charset_info); send_result_message: @@ -995,32 +1016,32 @@ send_result_message: char buf[MYSQL_ERRMSG_SIZE]; size_t length= my_snprintf(buf, sizeof(buf), ER_THD(thd, ER_BAD_TABLE_ERROR), - table_name); + table_name.str); protocol->store(STRING_WITH_LEN("note"), system_charset_info); protocol->store(buf, length, system_charset_info); } break; case HA_ADMIN_OK: - protocol->store(STRING_WITH_LEN("status"), system_charset_info); + protocol->store(&msg_status, system_charset_info); protocol->store(STRING_WITH_LEN("OK"), system_charset_info); break; case HA_ADMIN_FAILED: - protocol->store(STRING_WITH_LEN("status"), system_charset_info); + protocol->store(&msg_status, system_charset_info); protocol->store(STRING_WITH_LEN("Operation failed"), system_charset_info); break; case HA_ADMIN_REJECT: - protocol->store(STRING_WITH_LEN("status"), system_charset_info); + protocol->store(&msg_status, system_charset_info); protocol->store(STRING_WITH_LEN("Operation need committed state"), system_charset_info); open_for_modify= FALSE; break; case HA_ADMIN_ALREADY_DONE: - protocol->store(STRING_WITH_LEN("status"), system_charset_info); + protocol->store(&msg_status, system_charset_info); protocol->store(STRING_WITH_LEN("Table is already up to date"), system_charset_info); break; @@ -1062,9 +1083,7 @@ send_result_message: *save_next_global= table->next_global; table->next_local= table->next_global= 0; - tmp_disable_binlog(thd); // binlogging is done by caller if wanted result_code= admin_recreate_table(thd, table); - reenable_binlog(thd); trans_commit_stmt(thd); trans_commit(thd); close_thread_tables(thd); @@ -1102,7 +1121,7 @@ send_result_message: } /* Start a new row for the final status row */ protocol->prepare_for_resend(); - protocol->store(table_name, system_charset_info); + protocol->store(&table_name, system_charset_info); protocol->store(operator_name, system_charset_info); if (result_code) // either mysql_recreate_table or analyze failed { @@ -1123,7 +1142,7 @@ send_result_message: goto err; /* Start off another row for HA_ADMIN_FAILED */ protocol->prepare_for_resend(); - protocol->store(table_name, system_charset_info); + protocol->store(&table_name, system_charset_info); protocol->store(operator_name, system_charset_info); } thd->clear_error(); @@ -1167,7 +1186,11 @@ send_result_message: fatal_error=1; break; } - + case HA_ERR_TABLE_READONLY: + { + send_read_only_warning(thd, &msg_status, &table_name); + break; + } default: // Probably HA_ADMIN_INTERNAL_ERROR { char buf[MYSQL_ERRMSG_SIZE]; @@ -1186,9 +1209,16 @@ send_result_message: they must be marked as DDL so that they are not scheduled in parallel with conflicting DMLs resulting in deadlock. */ - thd->transaction.stmt.mark_executed_table_admin_cmd(); + thd->transaction->stmt.mark_executed_table_admin_cmd(); if (table->table && !table->view) { + /* + Don't skip flushing if we are collecting EITS statistics. + */ + const bool skip_flush= + (operator_func == &handler::ha_analyze) && + (table->table->file->ha_table_flags() & HA_ONLINE_ANALYZE) && + !collect_eis; if (table->table->s->tmp_table) { /* @@ -1198,10 +1228,9 @@ send_result_message: if (open_for_modify && !open_error) table->table->file->info(HA_STATUS_CONST); } - else if (open_for_modify || fatal_error) + else if ((!skip_flush && open_for_modify) || fatal_error) { - tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED, - table->db.str, table->table_name.str, FALSE); + table->table->s->tdc->flush_unused(true); /* May be something modified. Consequently, we have to invalidate the query cache. |