Commit b4ec2309 authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-7004 - Merge scalability fixes from 10.0-power

Preallocate locks on THD mem_root to avoid expensive malloc.
parent 9bc5cec0
...@@ -68,10 +68,6 @@ ...@@ -68,10 +68,6 @@
table_handler->external_lock(thd, F_UNLCK) for each table that was locked, table_handler->external_lock(thd, F_UNLCK) for each table that was locked,
excluding one that caused failure. That means handler must cleanup itself excluding one that caused failure. That means handler must cleanup itself
in case external_lock() fails. 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 <my_global.h> #include <my_global.h>
...@@ -266,19 +262,24 @@ void reset_lock_data(MYSQL_LOCK *sql_lock, bool unlock) ...@@ -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 *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
{ {
MYSQL_LOCK *sql_lock; MYSQL_LOCK *sql_lock;
uint gld_flags= GET_LOCK_STORE_LOCKS;
DBUG_ENTER("mysql_lock_tables(tables)"); DBUG_ENTER("mysql_lock_tables(tables)");
if (lock_tables_check(thd, tables, count, flags)) if (lock_tables_check(thd, tables, count, flags))
DBUG_RETURN(NULL); 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); DBUG_RETURN(NULL);
if (mysql_lock_tables(thd, sql_lock, flags)) if (mysql_lock_tables(thd, sql_lock, flags))
{ {
/* Clear the lock type of all lock data to avoid reusage. */ /* Clear the lock type of all lock data to avoid reusage. */
reset_lock_data(sql_lock, 1); reset_lock_data(sql_lock, 1);
my_free(sql_lock); if (!(gld_flags & GET_LOCK_ON_THD))
my_free(sql_lock);
sql_lock= 0; sql_lock= 0;
} }
DBUG_RETURN(sql_lock); DBUG_RETURN(sql_lock);
...@@ -382,6 +383,13 @@ static int lock_external(THD *thd, TABLE **tables, uint count) ...@@ -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) void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock)
{ {
DBUG_ENTER("mysql_unlock_tables"); DBUG_ENTER("mysql_unlock_tables");
......
...@@ -28,7 +28,8 @@ typedef struct st_mysql_lock MYSQL_LOCK; ...@@ -28,7 +28,8 @@ typedef struct st_mysql_lock MYSQL_LOCK;
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count, uint flags); 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); 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_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count); void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table); void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
......
...@@ -521,6 +521,8 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) ...@@ -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 Before opening and locking tables the below call also waits
for old shares to go away, so the fact that we don't pass 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) ...@@ -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, if (open_and_lock_tables(thd, all_tables, FALSE,
MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK, MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK,
&lock_tables_prelocking_strategy)) &lock_tables_prelocking_strategy))
goto error; goto error_reset_bits;
if (thd->lex->type & REFRESH_FOR_EXPORT) if (thd->lex->type & REFRESH_FOR_EXPORT)
{ {
...@@ -546,15 +548,14 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) ...@@ -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(), my_error(ER_ILLEGAL_HA, MYF(0),table_list->table->file->table_type(),
table_list->db, table_list->table_name); table_list->db, table_list->table_name);
return true; goto error_reset_bits;
} }
} }
} }
if (thd->locked_tables_list.init_locked_tables(thd)) 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 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) ...@@ -565,6 +566,9 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
return FALSE; return FALSE;
error_reset_bits:
close_thread_tables(thd);
thd->variables.option_bits&= ~OPTION_TABLE_LOCK;
error: error:
return TRUE; return TRUE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment