diff options
author | Aditya A <aditya.a@oracle.com> | 2013-06-14 11:22:05 +0530 |
---|---|---|
committer | Aditya A <aditya.a@oracle.com> | 2013-06-14 11:22:05 +0530 |
commit | dfb6f63bcf379dcefda43808a2d9f0d80254e3ad (patch) | |
tree | 389499896bca3d23e5cce2260fc647e068a471de | |
parent | af23963e643d943e1a8e7a683d13cdf30487b785 (diff) | |
download | mariadb-git-dfb6f63bcf379dcefda43808a2d9f0d80254e3ad.tar.gz |
Bug#13548704 ALGORITHM USED FOR DROPPING PARTITIONED TABLE CAN LEAD
TO INCONSISTENCY
PROBLEM
--------
When we drop a partitoned table , we first gather the
information about partitions in the table from the
table_name.par file and store it in an internal data
structure.Then we delete this file and the data in
the table. If the server crashes after deleting the
file,then after recovering we cannot access the table
.Even we cannot drop the table ,because drop algorithm
requires par file to read the partition information.
FIX
---
1. We move the part of deleting par file after deleting
all the table data from the storage egine.
2. During drop operation if we detect that the par
file is missing then we delete the .frm file,since
there is no way of recovering without par file.
[Approved by Mattias rb#2576 ]
-rw-r--r-- | mysql-test/r/partition_error.result | 4 | ||||
-rw-r--r-- | mysql-test/t/partition_error.test | 5 | ||||
-rw-r--r-- | sql/ha_partition.cc | 44 | ||||
-rw-r--r-- | sql/ha_partition.h | 2 |
4 files changed, 35 insertions, 20 deletions
diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 269b6875430..e5ac1371a9b 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -662,8 +662,8 @@ test.t1 check Error Incorrect information in file: './test/t1.frm' test.t1 check error Corrupt SELECT * FROM t1; ERROR HY000: Failed to read from the .par file -# Note that it is currently impossible to drop a partitioned table -# without the .par file +# Note that we will remove the frm file when we detect that +# .par file has been deleted. DROP TABLE t1; ERROR 42S02: Unknown table 't1' # diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 7e574fd6a42..746e52bd623 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -698,11 +698,10 @@ FLUSH TABLES; CHECK TABLE t1; --error ER_UNKNOWN_ERROR SELECT * FROM t1; ---echo # Note that it is currently impossible to drop a partitioned table ---echo # without the .par file +--echo # Note that we will remove the frm file when we detect that +--echo # .par file has been deleted. --error ER_BAD_TABLE_ERROR DROP TABLE t1; ---remove_file $MYSQLD_DATADIR/test/t1.frm --remove_file $MYSQLD_DATADIR/test/t1#P#p0.MYI --remove_file $MYSQLD_DATADIR/test/t1#P#p0.MYD diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 69cf5f74df6..778725c88cf 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1864,15 +1864,15 @@ char *ha_partition::update_table_comment(const char *comment) names of the partitions and the underlying storage engines. */ -uint ha_partition::del_ren_cre_table(const char *from, +int ha_partition::del_ren_cre_table(const char *from, const char *to, TABLE *table_arg, HA_CREATE_INFO *create_info) { int save_error= 0; - int error; + int error= HA_ERR_INTERNAL_ERROR; char from_buff[FN_REFLEN], to_buff[FN_REFLEN], from_lc_buff[FN_REFLEN], - to_lc_buff[FN_REFLEN]; + to_lc_buff[FN_REFLEN], buff[FN_REFLEN]; char *name_buffer_ptr; const char *from_path; const char *to_path= NULL; @@ -1884,24 +1884,28 @@ uint ha_partition::del_ren_cre_table(const char *from, if (create_info && create_info->options & HA_LEX_CREATE_TMP_TABLE) { my_error(ER_PARTITION_NO_TEMPORARY, MYF(0)); - DBUG_RETURN(TRUE); + DBUG_RETURN(error); + } + + fn_format(buff,from, "", ha_par_ext, MY_APPEND_EXT); + /* Check if the par file exists */ + if (my_access(buff,F_OK)) + { + /* + If the .par file does not exist, return HA_ERR_NO_SUCH_TABLE, + This will signal to the caller that it can remove the .frm + file. + */ + error= HA_ERR_NO_SUCH_TABLE; + DBUG_RETURN(error); } if (get_from_handler_file(from, ha_thd()->mem_root, false)) - DBUG_RETURN(TRUE); + DBUG_RETURN(error); DBUG_ASSERT(m_file_buffer); DBUG_PRINT("enter", ("from: (%s) to: (%s)", from, to)); name_buffer_ptr= m_name_buffer_ptr; file= m_file; - if (to == NULL && table_arg == NULL) - { - /* - Delete table, start by delete the .par file. If error, break, otherwise - delete as much as possible. - */ - if ((error= handler::delete_table(from))) - DBUG_RETURN(error); - } /* Since ha_partition has HA_FILE_BASED, it must alter underlying table names if they do not have HA_FILE_BASED and lower_case_table_names == 2. @@ -1940,6 +1944,18 @@ uint ha_partition::del_ren_cre_table(const char *from, save_error= error; i++; } while (*(++file)); + + if (to == NULL && table_arg == NULL) + { + DBUG_EXECUTE_IF("crash_before_deleting_par_file", DBUG_SUICIDE();); + + /* Delete the .par file. If error, break.*/ + if ((error= handler::delete_table(from))) + DBUG_RETURN(error); + + DBUG_EXECUTE_IF("crash_after_deleting_par_file", DBUG_SUICIDE();); + } + if (to != NULL) { if ((error= handler::rename_table(from, to))) diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 16d8f27bd71..8757ecc7619 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -285,7 +285,7 @@ private: delete_table, rename_table and create uses very similar logic which is packed into this routine. */ - uint del_ren_cre_table(const char *from, const char *to, + int del_ren_cre_table(const char *from, const char *to, TABLE *table_arg, HA_CREATE_INFO *create_info); /* One method to create the table_name.par file containing the names of the |