diff options
author | Dmitry Lenev <Dmitry.Lenev@oracle.com> | 2010-11-19 10:26:09 +0300 |
---|---|---|
committer | Dmitry Lenev <Dmitry.Lenev@oracle.com> | 2010-11-19 10:26:09 +0300 |
commit | b019ba2f47e7cfef2add56824938953effecff4a (patch) | |
tree | 4e0486b07de2f5676e27e519f22a1d83606f94c8 /sql/sql_table.cc | |
parent | 2d773c8b3ac5a576c9b1e3ed455cad8328711796 (diff) | |
download | mariadb-git-b019ba2f47e7cfef2add56824938953effecff4a.tar.gz |
Fix for bug #57985 "ONLINE/FAST ALTER PARTITION can fail and
leave the table unusable".
Failing ALTER statement on partitioned table could have left
this table in an unusable state. This has happened in cases
when ALTER was executed using "fast" algorithm, which doesn't
involve copying of data between old and new versions of table,
and the resulting new table was incompatible with partitioning
function in some way.
The problem stems from the fact that discrepancies between new
table definition and partitioning function are discovered only
when the table is opened. In case of "fast" algorithm this has
happened too late during ALTER's execution, at the moment when
all changes were already done and couldn't have been reverted.
In the cases when "slow" algorithm, which copies data, is used
such discrepancies are detected at the moment new table
definition is opened implicitly when new version of table is
created in storage engine. As result ALTER is aborted before
any changes to table were done.
This fix tries to address this issue by ensuring that "fast"
algorithm behaves similarly to "slow" algorithm and checks
compatibility between new definition and partitioning function
by trying to open new definition after .FRM file for it has
been created.
Long term we probably should implement some way to check
compatibility between partitioning function and new table
definition which won't involve opening it, as this should
allow much cleaner fix for this problem.
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6d5180c38d9..772496a10d5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3815,6 +3815,46 @@ void sp_prepare_create_field(THD *thd, Create_field *sql_field) (void) prepare_blob_field(thd, sql_field); } + +/** + Auxiliary function which allows to check if freshly created .FRM + file for table can be opened. + + @retval FALSE - Success. + @retval TRUE - Failure. +*/ + +static bool check_if_created_table_can_be_opened(THD *thd, + const char *path, + const char *db, + const char *table_name, + HA_CREATE_INFO *create_info, + handler *file) +{ + TABLE table; + TABLE_SHARE share; + bool result; + + /* + It is impossible to open definition of partitioned table without .par file. + */ + if (file->ha_create_handler_files(path, NULL, CHF_CREATE_FLAG, create_info)) + return TRUE; + + init_tmp_table_share(thd, &share, db, 0, table_name, path); + + result= (open_table_def(thd, &share, 0) || + open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, + 0, &table, TRUE)); + if (! result) + (void) closefrm(&table, 0); + + free_table_share(&share); + (void) file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info); + return result; +} + + /* Create a table @@ -4241,6 +4281,29 @@ bool mysql_create_table_no_lock(THD *thd, thd->thread_specific_used= TRUE; } +#ifdef WITH_PARTITION_STORAGE_ENGINE + else if (part_info && create_info->frm_only) + { + /* + For partitioned tables we can't find some problems with table + until table is opened. Therefore in order to disallow creation + of corrupted tables we have to try to open table as the part + of its creation process. + In cases when both .FRM and SE part of table are created table + is implicitly open in ha_create_table() call. + In cases when we create .FRM without SE part we have to open + table explicitly. + */ + if (check_if_created_table_can_be_opened(thd, path, db, table_name, + create_info, file)) + { + char frm_name[FN_REFLEN]; + strxmov(frm_name, path, reg_ext, NullS); + (void) mysql_file_delete(key_file_frm, frm_name, MYF(0)); + goto err; + } + } +#endif error= FALSE; err: |