From b4ec230917a50cbc1e406f5175189c8359bcb9a0 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Tue, 2 Dec 2014 14:54:30 +0400 Subject: MDEV-7004 - Merge scalability fixes from 10.0-power Preallocate locks on THD mem_root to avoid expensive malloc. --- sql/lock.cc | 20 ++++++++++++++------ sql/lock.h | 3 ++- sql/sql_reload.cc | 12 ++++++++---- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/sql/lock.cc b/sql/lock.cc index a0796db7367..c9aa49a4057 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -68,10 +68,6 @@ table_handler->external_lock(thd, F_UNLCK) for each table that was locked, excluding one that caused failure. That means handler must cleanup itself in case external_lock() fails. - - @todo - Change to use my_malloc() ONLY when using LOCK TABLES command or when - we are forced to use mysql_lock_merge. */ #include @@ -266,19 +262,24 @@ void reset_lock_data(MYSQL_LOCK *sql_lock, bool unlock) MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags) { MYSQL_LOCK *sql_lock; + uint gld_flags= GET_LOCK_STORE_LOCKS; DBUG_ENTER("mysql_lock_tables(tables)"); if (lock_tables_check(thd, tables, count, flags)) DBUG_RETURN(NULL); - if (! (sql_lock= get_lock_data(thd, tables, count, GET_LOCK_STORE_LOCKS))) + if (!(thd->variables.option_bits & OPTION_TABLE_LOCK)) + gld_flags|= GET_LOCK_ON_THD; + + if (! (sql_lock= get_lock_data(thd, tables, count, gld_flags))) DBUG_RETURN(NULL); if (mysql_lock_tables(thd, sql_lock, flags)) { /* Clear the lock type of all lock data to avoid reusage. */ reset_lock_data(sql_lock, 1); - my_free(sql_lock); + if (!(gld_flags & GET_LOCK_ON_THD)) + my_free(sql_lock); sql_lock= 0; } DBUG_RETURN(sql_lock); @@ -382,6 +383,13 @@ static int lock_external(THD *thd, TABLE **tables, uint count) } +void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock) +{ + mysql_unlock_tables(thd, sql_lock, + thd->variables.option_bits & OPTION_TABLE_LOCK); +} + + void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock) { DBUG_ENTER("mysql_unlock_tables"); diff --git a/sql/lock.h b/sql/lock.h index ca2f267f3d5..341d7a20f9f 100644 --- a/sql/lock.h +++ b/sql/lock.h @@ -28,7 +28,8 @@ typedef struct st_mysql_lock MYSQL_LOCK; MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, uint flags); bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags); -void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock= 1); +void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock); +void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock); void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock); void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count); void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table); diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index ca632f4a2fb..fe494c760dc 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -521,6 +521,8 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) } } + thd->variables.option_bits|= OPTION_TABLE_LOCK; + /* Before opening and locking tables the below call also waits for old shares to go away, so the fact that we don't pass @@ -534,7 +536,7 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) if (open_and_lock_tables(thd, all_tables, FALSE, MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK, &lock_tables_prelocking_strategy)) - goto error; + goto error_reset_bits; if (thd->lex->type & REFRESH_FOR_EXPORT) { @@ -546,15 +548,14 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) { my_error(ER_ILLEGAL_HA, MYF(0),table_list->table->file->table_type(), table_list->db, table_list->table_name); - return true; + goto error_reset_bits; } } } if (thd->locked_tables_list.init_locked_tables(thd)) - goto error; + goto error_reset_bits; - thd->variables.option_bits|= OPTION_TABLE_LOCK; /* We don't downgrade MDL_SHARED_NO_WRITE here as the intended @@ -565,6 +566,9 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) return FALSE; +error_reset_bits: + close_thread_tables(thd); + thd->variables.option_bits&= ~OPTION_TABLE_LOCK; error: return TRUE; } -- cgit v1.2.1