diff options
author | Nirbhay Choubey <nirbhay@mariadb.com> | 2016-04-29 16:50:58 -0400 |
---|---|---|
committer | Nirbhay Choubey <nirbhay@mariadb.com> | 2016-04-29 16:50:58 -0400 |
commit | 8a1efa1bdd29b756c93a3ddbd8ad6fadec1082bc (patch) | |
tree | 9827e75d29817f3ddbc2008ba2b5b21553c14c5e /sql/sql_insert.cc | |
parent | 7c42b47e67918104fddd121a1ca9fede28ed47cf (diff) | |
parent | 9eba34f08675c31b0796eeb127582be827773070 (diff) | |
download | mariadb-git-8a1efa1bdd29b756c93a3ddbd8ad6fadec1082bc.tar.gz |
Merge branch '10.0' into 10.0-galera
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r-- | sql/sql_insert.cc | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index c4dc41f7626..90614624aa6 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2010, 2016, 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 @@ -1592,9 +1592,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) else table->file->insert_id_for_cur_row= insert_id_for_cur_row; bool is_duplicate_key_error; - if (table->file->is_fatal_error(error, HA_CHECK_DUP)) + if (table->file->is_fatal_error(error, HA_CHECK_ALL)) goto err; - is_duplicate_key_error= table->file->is_fatal_error(error, 0); + is_duplicate_key_error= + table->file->is_fatal_error(error, HA_CHECK_ALL & ~HA_CHECK_DUP); if (!is_duplicate_key_error) { /* @@ -1722,7 +1723,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) error != HA_ERR_RECORD_IS_THE_SAME) { if (info->ignore && - !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + !table->file->is_fatal_error(error, HA_CHECK_ALL)) { if (!(thd->variables.old_behavior & OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) @@ -1852,7 +1853,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) { DEBUG_SYNC(thd, "write_row_noreplace"); if (!info->ignore || - table->file->is_fatal_error(error, HA_CHECK_DUP)) + table->file->is_fatal_error(error, HA_CHECK_ALL)) goto err; if (!(thd->variables.old_behavior & OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE)) @@ -1982,7 +1983,7 @@ public: TABLE *table; mysql_mutex_t mutex; mysql_cond_t cond, cond_client; - volatile uint tables_in_use,stacked_inserts; + uint tables_in_use, stacked_inserts; volatile bool status; /** When the handler thread starts, it clones a metadata lock ticket @@ -2624,14 +2625,16 @@ static void end_delayed_insert(THD *thd) void kill_delayed_threads(void) { + DBUG_ENTER("kill_delayed_threads"); mysql_mutex_lock(&LOCK_delayed_insert); // For unlink from list I_List_iterator<Delayed_insert> it(delayed_threads); Delayed_insert *di; while ((di= it++)) { - di->thd.killed= KILL_CONNECTION; mysql_mutex_lock(&di->thd.LOCK_thd_data); + if (di->thd.killed < KILL_CONNECTION) + di->thd.killed= KILL_CONNECTION; if (di->thd.mysys_var) { mysql_mutex_lock(&di->thd.mysys_var->mutex); @@ -2652,6 +2655,7 @@ void kill_delayed_threads(void) mysql_mutex_unlock(&di->thd.LOCK_thd_data); } mysql_mutex_unlock(&LOCK_delayed_insert); // For unlink from list + DBUG_VOID_RETURN; } @@ -2849,6 +2853,12 @@ pthread_handler_t handle_delayed_insert(void *arg) /* Tell client that the thread is initialized */ mysql_cond_signal(&di->cond_client); + /* + Inform mdl that it needs to call mysql_lock_abort to abort locks + for delayed insert. + */ + thd->mdl_context.set_needs_thr_lock_abort(TRUE); + /* Now wait until we get an insert or lock to handle */ /* We will not abort as long as a client thread uses this thread */ @@ -2857,6 +2867,7 @@ pthread_handler_t handle_delayed_insert(void *arg) if (thd->killed) { uint lock_count; + DBUG_PRINT("delayed", ("Insert delayed killed")); /* Remove this from delay insert list so that no one can request a table from this @@ -2867,11 +2878,15 @@ pthread_handler_t handle_delayed_insert(void *arg) lock_count=di->lock_count(); mysql_mutex_unlock(&LOCK_delayed_insert); mysql_mutex_lock(&di->mutex); - if (!lock_count && !di->tables_in_use && !di->stacked_inserts) + if (!lock_count && !di->tables_in_use && !di->stacked_inserts && + !thd->lock) break; // Time to die } /* Shouldn't wait if killed or an insert is waiting. */ + DBUG_PRINT("delayed", + ("thd->killed: %d di->status: %d di->stacked_inserts: %d", + thd->killed, di->status, di->stacked_inserts)); if (!thd->killed && !di->status && !di->stacked_inserts) { struct timespec abstime; @@ -2911,6 +2926,9 @@ pthread_handler_t handle_delayed_insert(void *arg) mysql_mutex_unlock(&di->thd.mysys_var->mutex); mysql_mutex_lock(&di->mutex); } + DBUG_PRINT("delayed", + ("thd->killed: %d di->tables_in_use: %d thd->lock: %d", + thd->killed, di->tables_in_use, thd->lock != 0)); if (di->tables_in_use && ! thd->lock && !thd->killed) { @@ -2971,9 +2989,19 @@ pthread_handler_t handle_delayed_insert(void *arg) { DBUG_ENTER("handle_delayed_insert-cleanup"); di->table=0; - thd->killed= KILL_CONNECTION; // If error mysql_mutex_unlock(&di->mutex); + /* + Protect against mdl_locks trying to access open tables + We use KILL_CONNECTION_HARD here to ensure that + THD::notify_shared_lock() dosn't try to access open tables after + this. + */ + mysql_mutex_lock(&thd->LOCK_thd_data); + thd->killed= KILL_CONNECTION_HARD; // If error + thd->mdl_context.set_needs_thr_lock_abort(0); + mysql_mutex_unlock(&thd->LOCK_thd_data); + close_thread_tables(thd); // Free the table thd->mdl_context.release_transactional_locks(); mysql_cond_broadcast(&di->cond_client); // Safety |