summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAditya A <aditya.a@oracle.com>2013-06-14 11:22:05 +0530
committerAditya A <aditya.a@oracle.com>2013-06-14 11:22:05 +0530
commitdfb6f63bcf379dcefda43808a2d9f0d80254e3ad (patch)
tree389499896bca3d23e5cce2260fc647e068a471de
parentaf23963e643d943e1a8e7a683d13cdf30487b785 (diff)
downloadmariadb-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.result4
-rw-r--r--mysql-test/t/partition_error.test5
-rw-r--r--sql/ha_partition.cc44
-rw-r--r--sql/ha_partition.h2
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