diff options
author | Sergey Vojtovich <svoj@mariadb.org> | 2016-04-21 16:51:00 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2016-04-22 13:01:15 +0400 |
commit | 994030c0e25c26c51602fde14d316552edf0a922 (patch) | |
tree | c2ea89ac0a68f82a9fc94f469ae4d9a2fa5d6afb /sql/sql_insert.cc | |
parent | 298e1d3f71cce89c83645ea9cc1eade4bdaf4917 (diff) | |
download | mariadb-git-994030c0e25c26c51602fde14d316552edf0a922.tar.gz |
MDEV-8889 - Assertion `next_insert_id == 0' failed in handler::ha_external_lock
There was a race condition between delayed insert thread and connection thread
actually performing INSERT/REPLACE DELAYED. It was triggered by concurrent
INSERT/REPLACE DELAYED and statements that flush the same table either
explicitely or implicitely (like FLUSH TABLE, ALTER TABLE, ...).
This race condition was caused by a gap in delayed thread shutdown logic,
which allowed concurrent connection running INSERT/REPLACE DELAYED to change
essential data consequently leaving table in semi-consistent state.
Specifically query thread could decrease "tables_in_use" reference counter in
this gap, causing delayed insert thread to shutdown without releasing auto
increment and table lock.
Fixed by extending condition so that delayed insert thread won't shutdown
until there're locked tables.
Also removed volatile qualifier from tables_in_use and stacked_inserts since
they're supposed to be protected by mutexes.
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r-- | sql/sql_insert.cc | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 42d88395060..b0151182a88 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1978,7 +1978,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 @@ -2863,7 +2863,8 @@ 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 } |