Commit 738ee005 authored by unknown's avatar unknown
Browse files

Bug#12845 - Stress test: Server crashes on CREATE .. SELECT statement

Solution for 5.0.
Changed calls to open_table(). Requested to ignore
flush at places where the command did already lock tables.
This could happen in CREATE ... SELECT and ALTER TABLE.

No test case. The bug can only be triggered by true concurrency.
The stress test suite provides a test case for this.


sql/sql_base.cc:
  Bug#12845 - Stress test: Server crashes on  CREATE .. SELECT statement
  Solution for 5.0.
  Changed open_table() so that ignoring flush requests
  is dependend on the 'flags' parameter as ignoring drop
  request was already. This aims for consistent behaviour.
sql/sql_table.cc:
  Bug#12845 - Stress test: Server crashes on  CREATE .. SELECT statement
  Solution for 5.0.
  Changed calls to open_table(). Requested to ignore
  flush at places where the command did already lock tables.
  This could happen in CREATE ... SELECT and ALTER TABLE.
parent e7b5b5c8
Loading
Loading
Loading
Loading
+15 −13
Original line number Diff line number Diff line
@@ -1030,23 +1030,23 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)

  SYNOPSIS
    open_table()
      thd         Thread context
      table_list  Open first table in list
      refresh     Pointer to memory that will be set to 1 if
                  we need to close all tables and reopen them
                  If this is a NULL pointer, then the is no version
                  number checking and the table is not put in the
                  thread-open-list
    thd                 Thread context.
    table_list          Open first table in list.
    refresh      INOUT  Pointer to memory that will be set to 1 if
                        we need to close all tables and reopen them.
                        If this is a NULL pointer, then the table is not
                        put in the thread-open-list.
    flags               Bitmap of flags to modify how open works:
                    MYSQL_LOCK_IGNORE_FLUSH - Open table even if someone
                    has done a flush or namelock on it.
                          MYSQL_LOCK_IGNORE_FLUSH - Open table even if
                          someone has done a flush or namelock on it.
                          No version number checking is done.

  IMPLEMENTATION
    Uses a cache of open tables to find a table not in use.

  RETURN
    NULL  Open failed.  If refresh is set then one should close
          all other tables and retry the open
          all other tables and retry the open.
    #     Success. Pointer to TABLE object for open table.
*/

@@ -1201,9 +1201,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,

  if (!thd->open_tables)
    thd->version=refresh_version;
  else if (thd->version != refresh_version && refresh)
  else if ((thd->version != refresh_version) &&
           ! (flags & MYSQL_LOCK_IGNORE_FLUSH))
  {
    /* Someone did a refresh while thread was opening tables */
    if (refresh)
      *refresh=1;
    VOID(pthread_mutex_unlock(&LOCK_open));
    DBUG_RETURN(0);
+4 −2
Original line number Diff line number Diff line
@@ -1756,7 +1756,8 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
                            create_info, *extra_fields, *keys, 0,
                            select_field_count))
    {
      if (!(table= open_table(thd, create_table, thd->mem_root, (bool*)0, 0)))
      if (! (table= open_table(thd, create_table, thd->mem_root, (bool*) 0,
                               MYSQL_LOCK_IGNORE_FLUSH)))
        quick_rm_table(create_info->db_type, create_table->db,
                       table_case_name(create_info, create_table->table_name));
    }
@@ -3579,7 +3580,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
      bzero((void*) &tbl, sizeof(tbl));
      tbl.db= new_db;
      tbl.table_name= tbl.alias= tmp_name;
      new_table= open_table(thd, &tbl, thd->mem_root, 0, 0);
      new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
                            MYSQL_LOCK_IGNORE_FLUSH);
    }
    else
    {