Commit fa11d613 authored by Sergei Golubchik's avatar Sergei Golubchik

MySQL WL#5522 - InnoDB transportable tablespaces.

Cleanups:
* remove unused HA_EXTRA_EXPORT (can be added later if needed, e.g. for Aria)
* clarify the meaning of HA_CAN_EXPORT
* make all engines that support EXPORT to announce it
* reduce code duplication
parent d929342b
...@@ -200,11 +200,6 @@ enum ha_extra_function { ...@@ -200,11 +200,6 @@ enum ha_extra_function {
HA_EXTRA_ATTACH_CHILDREN, HA_EXTRA_ATTACH_CHILDREN,
HA_EXTRA_IS_ATTACHED_CHILDREN, HA_EXTRA_IS_ATTACHED_CHILDREN,
HA_EXTRA_DETACH_CHILDREN, HA_EXTRA_DETACH_CHILDREN,
/*
Prepare table for export
(e.g. quiesce the table and write table metadata).
*/
HA_EXTRA_EXPORT,
HA_EXTRA_DETACH_CHILD, HA_EXTRA_DETACH_CHILD,
/* Inform handler we will force a close as part of flush */ /* Inform handler we will force a close as part of flush */
HA_EXTRA_PREPARE_FOR_FORCED_CLOSE HA_EXTRA_PREPARE_FOR_FORCED_CLOSE
......
...@@ -155,9 +155,9 @@ UNLOCK TABLES; ...@@ -155,9 +155,9 @@ UNLOCK TABLES;
DROP TABLE t1; DROP TABLE t1;
# Test 6: Unsupported storage engines. # Test 6: Unsupported storage engines.
# #
CREATE TABLE t1(a INT) engine= MyISAM; CREATE TABLE t1(a INT) engine= MEMORY;
FLUSH TABLE t1 FOR EXPORT; FLUSH TABLE t1 FOR EXPORT;
ERROR HY000: Storage engine MyISAM of the table `test`.`t1` doesn't have this option ERROR HY000: Storage engine MEMORY of the table `test`.`t1` doesn't have this option
DROP TABLE t1; DROP TABLE t1;
# Connection con1 # Connection con1
# Connection defalt # Connection defalt
......
...@@ -267,7 +267,7 @@ DROP TABLE t1; ...@@ -267,7 +267,7 @@ DROP TABLE t1;
--echo # Test 6: Unsupported storage engines. --echo # Test 6: Unsupported storage engines.
--echo # --echo #
CREATE TABLE t1(a INT) engine= MyISAM; CREATE TABLE t1(a INT) engine= MEMORY;
--error ER_ILLEGAL_HA --error ER_ILLEGAL_HA
FLUSH TABLE t1 FOR EXPORT; FLUSH TABLE t1 FOR EXPORT;
DROP TABLE t1; DROP TABLE t1;
......
...@@ -249,7 +249,9 @@ enum enum_alter_inplace_result { ...@@ -249,7 +249,9 @@ enum enum_alter_inplace_result {
/* /*
Storage engine supports table export using the Storage engine supports table export using the
FLUSH TABLE <table_list> FOR EXPORT statement. FLUSH TABLE <table_list> FOR EXPORT statement
(meaning, after this statement one can copy table files out of the
datadir and later "import" (somehow) in another MariaDB instance)
*/ */
#define HA_CAN_EXPORT (1LL << 45) #define HA_CAN_EXPORT (1LL << 45)
......
...@@ -4221,25 +4221,16 @@ end_with_restore_list: ...@@ -4221,25 +4221,16 @@ end_with_restore_list:
if (check_global_access(thd,RELOAD_ACL)) if (check_global_access(thd,RELOAD_ACL))
goto error; goto error;
if (first_table && lex->type & REFRESH_READ_LOCK) if (first_table && lex->type & (REFRESH_READ_LOCK|REFRESH_FOR_EXPORT))
{ {
/* Check table-level privileges. */ /* Check table-level privileges. */
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
FALSE, UINT_MAX, FALSE)) FALSE, UINT_MAX, FALSE))
goto error; goto error;
if (flush_tables_with_read_lock(thd, all_tables)) if (flush_tables_with_read_lock(thd, all_tables))
goto error; goto error;
my_ok(thd);
break;
}
else if (first_table && lex->type & REFRESH_FOR_EXPORT)
{
/* Check table-level privileges. */
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
FALSE, UINT_MAX, FALSE))
goto error;
if (flush_tables_for_export(thd, all_tables))
goto error;
my_ok(thd); my_ok(thd);
break; break;
} }
......
...@@ -407,7 +407,8 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, ...@@ -407,7 +407,8 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
/** /**
Implementation of FLUSH TABLES <table_list> WITH READ LOCK. Implementation of FLUSH TABLES <table_list> WITH READ LOCK
and FLUSH TABLES <table_list> FOR EXPORT
In brief: take exclusive locks, expel tables from the table In brief: take exclusive locks, expel tables from the table
cache, reopen the tables, enter the 'LOCKED TABLES' mode, cache, reopen the tables, enter the 'LOCKED TABLES' mode,
...@@ -496,6 +497,8 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) ...@@ -496,6 +497,8 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
goto error; goto error;
} }
if (thd->lex->type & REFRESH_READ_LOCK)
{
/* /*
Acquire SNW locks on tables to be flushed. Don't acquire global Acquire SNW locks on tables to be flushed. Don't acquire global
IX and database-scope IX locks on the tables as this will make IX and database-scope IX locks on the tables as this will make
...@@ -518,6 +521,7 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) ...@@ -518,6 +521,7 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
/* Reset ticket to satisfy asserts in open_tables(). */ /* Reset ticket to satisfy asserts in open_tables(). */
table_list->mdl_request.ticket= NULL; table_list->mdl_request.ticket= NULL;
} }
}
/* /*
Before opening and locking tables the below call also waits Before opening and locking tables the below call also waits
...@@ -531,72 +535,11 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables) ...@@ -531,72 +535,11 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
*/ */
if (open_and_lock_tables(thd, all_tables, FALSE, if (open_and_lock_tables(thd, all_tables, FALSE,
MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK, MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK,
&lock_tables_prelocking_strategy) || &lock_tables_prelocking_strategy))
thd->locked_tables_list.init_locked_tables(thd))
{
goto error; goto error;
}
thd->variables.option_bits|= OPTION_TABLE_LOCK;
/*
We don't downgrade MDL_SHARED_NO_WRITE here as the intended
post effect of this call is identical to LOCK TABLES <...> READ,
and we didn't use thd->in_lock_talbes and
thd->sql_command= SQLCOM_LOCK_TABLES hacks to enter the LTM.
*/
return FALSE;
error:
return TRUE;
}
/**
Prepare tables for export (transportable tablespaces) by
a) waiting until write transactions/DDL operations using these
tables have completed.
b) block new write operations/DDL operations on these tables.
Once this is done, notify the storage engines using handler::extra().
Finally, enter LOCK TABLES mode, so that locks are held
until UNLOCK TABLES is executed.
@param thd Thread handler
@param all_tables TABLE_LIST for tables to be exported
@retval false Ok
@retval true Error
*/
bool flush_tables_for_export(THD *thd, TABLE_LIST *all_tables)
{
Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
/*
This is called from SQLCOM_FLUSH, the transaction has
been committed implicitly.
*/
if (thd->locked_tables_mode) if (thd->lex->type & REFRESH_FOR_EXPORT)
{ {
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
return true;
}
/*
Acquire SNW locks on tables to be exported. Don't acquire
global IX as this will make this statement incompatible
with FLUSH TABLES WITH READ LOCK.
*/
if (open_and_lock_tables(thd, all_tables, false,
MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK,
&lock_tables_prelocking_strategy))
{
return true;
}
// Check if all storage engines support FOR EXPORT. // Check if all storage engines support FOR EXPORT.
for (TABLE_LIST *table_list= all_tables; table_list; for (TABLE_LIST *table_list= all_tables; table_list;
table_list= table_list->next_global) table_list= table_list->next_global)
...@@ -608,26 +551,24 @@ bool flush_tables_for_export(THD *thd, TABLE_LIST *all_tables) ...@@ -608,26 +551,24 @@ bool flush_tables_for_export(THD *thd, TABLE_LIST *all_tables)
return true; return true;
} }
} }
// Notify the storage engines that the tables should be made ready for export.
for (TABLE_LIST *table_list= all_tables; table_list;
table_list= table_list->next_global)
{
handler *handler_file= table_list->table->file;
int error= handler_file->extra(HA_EXTRA_EXPORT);
if (error)
{
handler_file->print_error(error, MYF(0));
return true;
}
} }
// Enter LOCKED TABLES mode.
if (thd->locked_tables_list.init_locked_tables(thd)) if (thd->locked_tables_list.init_locked_tables(thd))
return true; goto error;
thd->variables.option_bits|= OPTION_TABLE_LOCK; thd->variables.option_bits|= OPTION_TABLE_LOCK;
return false; /*
We don't downgrade MDL_SHARED_NO_WRITE here as the intended
post effect of this call is identical to LOCK TABLES <...> READ,
and we didn't use thd->in_lock_talbes and
thd->sql_command= SQLCOM_LOCK_TABLES hacks to enter the LTM.
*/
return FALSE;
error:
return TRUE;
} }
......
...@@ -22,6 +22,5 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options, ...@@ -22,6 +22,5 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
TABLE_LIST *tables, int *write_to_binlog); TABLE_LIST *tables, int *write_to_binlog);
bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables); bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables);
bool flush_tables_for_export(THD *thd, TABLE_LIST *all_tables);
#endif #endif
...@@ -1829,7 +1829,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1829,7 +1829,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
object_privilege object_privilege_list user_list user_and_role_list object_privilege object_privilege_list user_list user_and_role_list
rename_list rename_list
clear_privileges flush_options flush_option clear_privileges flush_options flush_option
opt_flush_lock flush_options_list opt_flush_lock flush_lock flush_options_list
equal optional_braces equal optional_braces
opt_mi_check_type opt_to mi_check_types opt_mi_check_type opt_to mi_check_types
table_to_table_list table_to_table opt_table_list opt_as table_to_table_list table_to_table opt_table_list opt_as
...@@ -12779,17 +12779,15 @@ flush_options: ...@@ -12779,17 +12779,15 @@ flush_options:
YYPS->m_lock_type= TL_READ_NO_INSERT; YYPS->m_lock_type= TL_READ_NO_INSERT;
YYPS->m_mdl_type= MDL_SHARED_HIGH_PRIO; YYPS->m_mdl_type= MDL_SHARED_HIGH_PRIO;
} }
opt_table_list {} opt_table_list opt_flush_lock
opt_flush_lock {}
| flush_options_list | flush_options_list
; ;
opt_flush_lock: opt_flush_lock:
/* empty */ {} /* empty */ {}
| WITH READ_SYM LOCK_SYM optional_flush_tables_arguments | flush_lock
{ {
TABLE_LIST *tables= Lex->query_tables; TABLE_LIST *tables= Lex->query_tables;
Lex->type|= REFRESH_READ_LOCK | $4;
for (; tables; tables= tables->next_global) for (; tables; tables= tables->next_global)
{ {
tables->mdl_request.set_type(MDL_SHARED_NO_WRITE); tables->mdl_request.set_type(MDL_SHARED_NO_WRITE);
...@@ -12797,6 +12795,11 @@ opt_flush_lock: ...@@ -12797,6 +12795,11 @@ opt_flush_lock:
tables->open_type= OT_BASE_ONLY; /* Ignore temporary tables. */ tables->open_type= OT_BASE_ONLY; /* Ignore temporary tables. */
} }
} }
;
flush_lock:
WITH READ_SYM LOCK_SYM optional_flush_tables_arguments
{ Lex->type|= REFRESH_READ_LOCK | $4; }
| FOR_SYM | FOR_SYM
{ {
if (Lex->query_tables == NULL) // Table list can't be empty if (Lex->query_tables == NULL) // Table list can't be empty
...@@ -12804,18 +12807,8 @@ opt_flush_lock: ...@@ -12804,18 +12807,8 @@ opt_flush_lock:
my_parse_error(ER(ER_NO_TABLES_USED)); my_parse_error(ER(ER_NO_TABLES_USED));
MYSQL_YYABORT; MYSQL_YYABORT;
} }
}
EXPORT_SYM
{
TABLE_LIST *tables= Lex->query_tables;
Lex->type|= REFRESH_FOR_EXPORT; Lex->type|= REFRESH_FOR_EXPORT;
for (; tables; tables= tables->next_global) } EXPORT_SYM
{
tables->mdl_request.set_type(MDL_SHARED_NO_WRITE);
tables->required_type= FRMTYPE_TABLE; /* Don't try to flush views. */
tables->open_type= OT_BASE_ONLY; /* Ignore temporary tables. */
}
}
; ;
flush_options_list: flush_options_list:
......
...@@ -107,7 +107,7 @@ public: ...@@ -107,7 +107,7 @@ public:
{ {
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD | return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_STATS_RECORDS_IS_EXACT | HA_STATS_RECORDS_IS_EXACT | HA_CAN_EXPORT |
HA_HAS_RECORDS | HA_CAN_REPAIR | HA_HAS_RECORDS | HA_CAN_REPAIR |
HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY); HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY);
} }
......
...@@ -106,7 +106,7 @@ public: ...@@ -106,7 +106,7 @@ public:
ulonglong table_flags() const ulonglong table_flags() const
{ {
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT | return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_CAN_EXPORT |
HA_CAN_REPAIR); HA_CAN_REPAIR);
} }
ulong index_flags(uint idx, uint part, bool all_parts) const ulong index_flags(uint idx, uint part, bool all_parts) const
......
...@@ -667,7 +667,7 @@ ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg) ...@@ -667,7 +667,7 @@ ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
:handler(hton, table_arg), file(0), :handler(hton, table_arg), file(0),
int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER | int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_CAN_VIRTUAL_COLUMNS | HA_CAN_VIRTUAL_COLUMNS | HA_CAN_EXPORT |
HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS | HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS | HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
......
...@@ -89,7 +89,7 @@ public: ...@@ -89,7 +89,7 @@ public:
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_FILE_BASED | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_FILE_BASED |
HA_ANY_INDEX_MAY_BE_UNIQUE | HA_CAN_BIT_FIELD | HA_ANY_INDEX_MAY_BE_UNIQUE | HA_CAN_BIT_FIELD |
HA_HAS_RECORDS | HA_HAS_RECORDS | HA_CAN_EXPORT |
HA_NO_COPY_ON_ALTER | HA_NO_COPY_ON_ALTER |
HA_DUPLICATE_POS); HA_DUPLICATE_POS);
} }
......
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