diff --git a/include/mysql_com.h b/include/mysql_com.h index 7eac3b113d2..dec184133dc 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -118,6 +118,8 @@ enum enum_server_command #define NET_WRITE_TIMEOUT 60 /* Timeout on write */ #define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */ +#define ONLY_KILL_QUERY 1 + struct st_vio; /* Only C */ typedef struct st_vio Vio; diff --git a/sql/lex.h b/sql/lex.h index 2992acfe4c6..f61cca00d51 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -104,6 +104,7 @@ static SYMBOL symbols[] = { { "COMMITTED", SYM(COMMITTED_SYM),0,0}, { "COMPRESSED", SYM(COMPRESSED_SYM),0,0}, { "CONCURRENT", SYM(CONCURRENT),0,0}, + { "CONNECTION", SYM(CONNECTION_SYM),0,0}, { "CONSTRAINT", SYM(CONSTRAINT),0,0}, { "CREATE", SYM(CREATE),0,0}, { "CROSS", SYM(CROSS),0,0}, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 62d2620ad75..9a3c265affb 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -45,7 +45,7 @@ char *sql_strdup(const char *str); char *sql_strmake(const char *str,uint len); gptr sql_memdup(const void * ptr,unsigned size); void sql_element_free(void *ptr); -void kill_one_thread(THD *thd, ulong id); +void kill_one_thread(THD *thd, ulong id, bool only_kill_query); bool net_request_file(NET* net, const char* fname); char* query_table_status(THD *thd,const char *db,const char *table_name); diff --git a/sql/sql_class.h b/sql/sql_class.h index f07410770e3..f1817876fc3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -549,6 +549,7 @@ public: bool system_thread,in_lock_tables,global_read_lock; bool query_error, bootstrap, cleanup_done; bool volatile killed; + bool volatile only_kill_query; bool prepare_command; bool tmp_table_used; sp_rcontext *spcont; // SP runtime context diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0fa05e13f9c..278b7b92574 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -848,7 +848,7 @@ pthread_handler_decl(handle_one_connection,arg) init_sql_alloc(&thd->mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); init_sql_alloc(&thd->transaction.mem_root, TRANS_MEM_ROOT_BLOCK_SIZE, TRANS_MEM_ROOT_PREALLOC); - while (!net->error && net->vio != 0 && !thd->killed) + while (!net->error && net->vio != 0 && !(thd->killed && !thd->only_kill_query)) { if (do_command(thd)) break; @@ -1054,6 +1054,12 @@ bool do_command(THD *thd) } else { + if (thd->only_kill_query) + { + thd->killed= FALSE; + thd->only_kill_query= FALSE; + } + packet=(char*) net->read_pos; command = (enum enum_server_command) (uchar) packet[0]; if (command >= COM_END) @@ -1473,7 +1479,7 @@ restore_user: { statistic_increment(com_stat[SQLCOM_KILL],&LOCK_status); ulong id=(ulong) uint4korr(packet); - kill_one_thread(thd,id); + kill_one_thread(thd,id,false); break; } case COM_DEBUG: @@ -2899,7 +2905,7 @@ mysql_execute_command(THD *thd) reload_acl_and_cache(thd, lex->type, tables); break; case SQLCOM_KILL: - kill_one_thread(thd,lex->thread_id); + kill_one_thread(thd,lex->thread_id, lex->type & ONLY_KILL_QUERY); break; case SQLCOM_SHOW_GRANTS: res=0; @@ -4195,7 +4201,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) This is written such that we have a short lock on LOCK_thread_count */ -void kill_one_thread(THD *thd, ulong id) +void kill_one_thread(THD *thd, ulong id, bool only_kill_query) { THD *tmp; uint error=ER_NO_SUCH_THREAD; @@ -4215,7 +4221,13 @@ void kill_one_thread(THD *thd, ulong id) if ((thd->master_access & SUPER_ACL) || !strcmp(thd->user,tmp->user)) { - tmp->awake(1 /*prepare to die*/); + if (only_kill_query) + { + tmp->killed= 1; + tmp->only_kill_query= 1; + } + else + tmp->awake(1 /*prepare to die*/); error=0; } else diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 43cfe94bdea..db5b9038ecb 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -202,6 +202,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token COLUMNS %token COLUMN_SYM %token CONCURRENT +%token CONNECTION_SYM %token CONSTRAINT %token CONVERT_SYM %token DATABASES @@ -4303,18 +4304,23 @@ purge_option: /* kill threads */ kill: - KILL_SYM expr + KILL_SYM kill_option expr { LEX *lex=Lex; - if ($2->fix_fields(lex->thd, 0, &$2) || $2->check_cols(1)) + if ($3->fix_fields(lex->thd, 0, &$3) || $3->check_cols(1)) { send_error(lex->thd, ER_SET_CONSTANTS_ONLY); YYABORT; } lex->sql_command=SQLCOM_KILL; - lex->thread_id= (ulong) $2->val_int(); + lex->thread_id= (ulong) $3->val_int(); }; +kill_option: + /* empty */ { Lex->type= 0; } + | CONNECTION_SYM { Lex->type= 0; } + | QUERY_SYM { Lex->type= ONLY_KILL_QUERY; }; + /* change database */ use: USE_SYM ident