Commit 7f8627e3 authored by Vasil Dimov's avatar Vasil Dimov

Manually merge a changeset from mysql-5.1-security:

  ------------------------------------------------------------
  revno: 3475
  revision-id: jimmy.yang@oracle.com-20100804103744-vbpeghipkz6pyc9z
  parent: jimmy.yang@oracle.com-20100804101133-c38qqbm0fkwn9jhc
  committer: Jimmy Yang <jimmy.yang@oracle.com>
  branch nick: mysql-5.1-security
  timestamp: Wed 2010-08-04 03:37:44 -0700
  message:
    Fix bug #54678, InnoDB, TRUNCATE, ALTER, I_S SELECT, crash or deadlock
    
    rb://399 approved by Sunny Bains
  modified:
    storage/innodb_plugin/ChangeLog 2425@16c675df-0fcb-4bc9-8058-dcc011a37293:branches%2Fzip%2FChangeLog
    storage/innodb_plugin/include/dict0dict.h 2@16c675df-0fcb-4bc9-8058-dcc011a37293:trunk%2Finclude%2Fdict0dict.h
    storage/innodb_plugin/include/dict0dict.ic 2@16c675df-0fcb-4bc9-8058-dcc011a37293:trunk%2Finclude%2Fdict0dict.ic
    storage/innodb_plugin/row/row0mysql.c 2@16c675df-0fcb-4bc9-8058-dcc011a37293:trunk%2Frow%2Frow0mysql.c
parent 5ecd1920
......@@ -707,6 +707,22 @@ ulint
dict_table_zip_size(
/*================*/
const dict_table_t* table); /*!< in: table */
/*********************************************************************//**
Obtain exclusive locks on all index trees of the table. This is to prevent
accessing index trees while InnoDB is updating internal metadata for
operations such as truncate tables. */
UNIV_INLINE
void
dict_table_x_lock_indexes(
/*======================*/
dict_table_t* table); /*!< in: table */
/*********************************************************************//**
Release the exclusive locks on all index tree. */
UNIV_INLINE
void
dict_table_x_unlock_indexes(
/*========================*/
dict_table_t* table); /*!< in: table */
/********************************************************************//**
Checks if a column is in the ordering columns of the clustered index of a
table. Column prefixes are treated like whole columns.
......
......@@ -490,6 +490,48 @@ dict_table_zip_size(
return(dict_table_flags_to_zip_size(table->flags));
}
/*********************************************************************//**
Obtain exclusive locks on all index trees of the table. This is to prevent
accessing index trees while InnoDB is updating internal metadata for
operations such as truncate tables. */
UNIV_INLINE
void
dict_table_x_lock_indexes(
/*======================*/
dict_table_t* table) /*!< in: table */
{
dict_index_t* index;
ut_a(table);
ut_ad(mutex_own(&(dict_sys->mutex)));
/* Loop through each index of the table and lock them */
for (index = dict_table_get_first_index(table);
index != NULL;
index = dict_table_get_next_index(index)) {
rw_lock_x_lock(dict_index_get_lock(index));
}
}
/*********************************************************************//**
Release the exclusive locks on all index tree. */
UNIV_INLINE
void
dict_table_x_unlock_indexes(
/*========================*/
dict_table_t* table) /*!< in: table */
{
dict_index_t* index;
ut_a(table);
ut_ad(mutex_own(&(dict_sys->mutex)));
for (index = dict_table_get_first_index(table);
index != NULL;
index = dict_table_get_next_index(index)) {
rw_lock_x_unlock(dict_index_get_lock(index));
}
}
/********************************************************************//**
Gets the number of fields in the internal representation of an index,
including fields added by the dictionary system.
......
......@@ -2808,6 +2808,15 @@ row_truncate_table_for_mysql(
trx->table_id = table->id;
/* Lock all index trees for this table, as we will
truncate the table/index and possibly change their metadata.
All DML/DDL are blocked by table level lock, with
a few exceptions such as queries into information schema
about the table, MySQL could try to access index stats
for this kind of query, we need to use index locks to
sync up */
dict_table_x_lock_indexes(table);
if (table->space && !table->dir_path_of_temp_table) {
/* Discard and create the single-table tablespace. */
ulint space = table->space;
......@@ -2824,6 +2833,7 @@ row_truncate_table_for_mysql(
|| fil_create_new_single_table_tablespace(
space, table->name, FALSE, flags,
FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
dict_table_x_unlock_indexes(table);
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: TRUNCATE TABLE %s failed to"
......@@ -2927,6 +2937,10 @@ row_truncate_table_for_mysql(
mem_heap_free(heap);
/* Done with index truncation, release index tree locks,
subsequent work relates to table level metadata change */
dict_table_x_unlock_indexes(table);
dict_hdr_get_new_id(&new_id, NULL, NULL);
info = pars_info_create();
......
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