From: Jon Olav Hauglid Date: May 3 2012 8:12am Subject: bzr push into mysql-trunk-wl6168 branch (jon.hauglid:3870 to 3871) WL#6169 List-Archive: http://lists.mysql.com/commits/143717 Message-Id: <201205030812.q438CIYR022697@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3871 Jon Olav Hauglid 2012-05-03 WL#6169 FLUSH TABLES ... FOR EXPORT -- runtime This worklog adds the runtime side for the new FOR EXPORT option for FLUSH TABLES . The FLUSH TABLES FOR EXPORT statement: - Acquires MDL_SHARED_NO_WRITE metadata lock on the tables listed in . The effect is that FLUSH TABLES FOR EXPORT will block until all active transactions that have updated any table in have completed. While FLUSH TABLES FOR EXPORT is in effect, no new updating transactions and no DDL statements are allowed. Read-only transactions will not be affected. - Enters LOCK TABLES mode so that locks are held until the UNLOCK TABLES statement is executed. - Notifies the storage engine by calling handler::extra() using the new flag HA_EXTRA_EXPORT. This allows the storage engine to perform any steps needed to make the table ready for export (e.g. quiesce the table and write metadata file). The worklog also adds a new ha_table_flags() flag: HA_CAN_EXPORT_TABLESPACE. This flags indicates that a given storage engine support FLUSH TABLES FOR EXPORT. If such a statement includes tables for which the storage engine does not have this flag, an error will be returned. modified: include/my_base.h include/mysql_com.h mysql-test/r/flush_table.result mysql-test/t/flush_table.test sql/handler.h sql/sql_parse.cc sql/sql_reload.cc sql/sql_reload.h sql/sql_yacc.yy storage/innobase/handler/ha_innodb.cc 3870 Jon Olav Hauglid 2012-05-02 [merge] Merge from mysql-trunk to mysql-trunk-wl6168 No conflicts removed: mysql-test/suite/rpl/r/rpl_row_find_row_debug.result mysql-test/suite/rpl/t/rpl_row_find_row_debug.test added: mysql-test/extra/rpl_tests/rpl_row_idempotency.test mysql-test/include/rpl_hash_scan_assertion.inc mysql-test/lib/My/Memcache.pm mysql-test/r/func_group_innodb_16k.result mysql-test/suite/innodb/include/innodb_dict.inc mysql-test/suite/innodb/r/innodb-alter-debug.result mysql-test/suite/innodb/r/innodb-alter.result mysql-test/suite/innodb/r/innodb_bug13867871.result mysql-test/suite/innodb/t/innodb-alter-debug.test mysql-test/suite/innodb/t/innodb-alter.test mysql-test/suite/innodb/t/innodb_bug13867871.test mysql-test/suite/rpl/r/rpl_row_hash_scan.result mysql-test/suite/rpl/r/rpl_row_hash_scan_sanity.result mysql-test/suite/rpl/t/rpl_report_port-master.opt mysql-test/suite/rpl/t/rpl_row_hash_scan.test mysql-test/suite/rpl/t/rpl_row_hash_scan_sanity.test mysql-test/suite/sys_vars/r/slave_rows_search_algorithms_basic.result mysql-test/suite/sys_vars/t/slave_rows_search_algorithms_basic.test mysql-test/t/func_group_innodb_16k.test modified: extra/comp_err.c libmysqld/lib_sql.cc mysql-test/collections/default.daily mysql-test/extra/rpl_tests/rpl_record_compare.test mysql-test/include/handler.inc mysql-test/include/order_by.inc mysql-test/include/subquery.inc mysql-test/lib/My/ConfigFactory.pm mysql-test/lib/mtr_cases.pm mysql-test/mysql-test-run.pl mysql-test/r/alter_table.result mysql-test/r/create.result mysql-test/r/ctype_create.result mysql-test/r/drop.result mysql-test/r/events_2.result mysql-test/r/explain.result mysql-test/r/explain_json_all.result mysql-test/r/explain_json_none.result mysql-test/r/func_group_innodb.result mysql-test/r/func_time.result mysql-test/r/handler_innodb.result mysql-test/r/handler_myisam.result mysql-test/r/information_schema.result mysql-test/r/mysql.result mysql-test/r/mysqld--help-notwin.result mysql-test/r/mysqld--help-win.result mysql-test/r/order_by_all.result mysql-test/r/order_by_icp_mrr.result mysql-test/r/order_by_none.result mysql-test/r/subquery_all.result mysql-test/r/subquery_all_bka.result mysql-test/r/subquery_all_bka_nixbnl.result mysql-test/r/subquery_nomat_nosj.result mysql-test/r/subquery_nomat_nosj_bka.result mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result mysql-test/r/subquery_none.result mysql-test/r/subquery_none_bka.result mysql-test/r/subquery_none_bka_nixbnl.result mysql-test/suite/explain_json_validate/r/explain_json_validate.result mysql-test/suite/innodb/r/innodb-index-online.result mysql-test/suite/innodb/r/innodb-index.result mysql-test/suite/innodb/r/innodb_bug21704.result mysql-test/suite/innodb/r/innodb_corrupt_bit.result mysql-test/suite/innodb/t/innodb-index-online.test mysql-test/suite/innodb/t/innodb-index.test mysql-test/suite/innodb/t/innodb_bug21704.test mysql-test/suite/innodb/t/innodb_corrupt_bit.test mysql-test/suite/opt_trace/r/bugs_no_prot_all.result mysql-test/suite/opt_trace/r/bugs_no_prot_none.result mysql-test/suite/opt_trace/r/bugs_ps_prot_all.result mysql-test/suite/opt_trace/r/bugs_ps_prot_none.result mysql-test/suite/opt_trace/r/range_no_prot.result mysql-test/suite/opt_trace/r/range_ps_prot.result mysql-test/suite/rpl/r/rpl_bug26395.result mysql-test/suite/rpl/r/rpl_filter_tables_not_exist.result mysql-test/suite/rpl/r/rpl_parallel_start_stop.result mysql-test/suite/rpl/r/rpl_relayrotate.result mysql-test/suite/rpl/r/rpl_report_port.result mysql-test/suite/rpl/r/rpl_row_idempotency.result mysql-test/suite/rpl/r/rpl_row_rec_comp_innodb.result mysql-test/suite/rpl/r/rpl_row_rec_comp_myisam.result mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result mysql-test/suite/rpl/t/rpl_bug26395.test mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test mysql-test/suite/rpl/t/rpl_parallel_start_stop.test mysql-test/suite/rpl/t/rpl_relayrotate.test mysql-test/suite/rpl/t/rpl_report_port.test mysql-test/suite/rpl/t/rpl_row_idempotency.test mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test mysql-test/suite/sys_vars/r/bind_address_basic.result mysql-test/suite/sys_vars/t/bind_address_basic.test mysql-test/t/create.test mysql-test/t/ctype_create.test mysql-test/t/drop.test mysql-test/t/events_2.test mysql-test/t/func_group_innodb.test mysql-test/t/func_time.test mysql-test/t/handler_myisam.test mysql-test/t/information_schema.test mysql-test/t/overflow.test sql-common/my_time.c sql/datadict.cc sql/derror.cc sql/event_db_repository.cc sql/field.cc sql/field.h sql/filesort.cc sql/ha_partition.cc sql/handler.cc sql/handler.h sql/item_buff.cc sql/item_cmpfunc.cc sql/item_cmpfunc.h sql/item_subselect.cc sql/item_timefunc.cc sql/log.cc sql/log_event.cc sql/log_event.h sql/log_event_old.cc sql/mysqld.cc sql/mysqld.h sql/opt_range.cc sql/opt_sum.cc sql/partition_info.cc sql/rpl_info_table.cc sql/rpl_slave.cc sql/rpl_utility.cc sql/rpl_utility.h sql/sp.cc sql/sql_acl.cc sql/sql_bitmap.h sql/sql_class.h sql/sql_db.cc sql/sql_executor.cc sql/sql_handler.cc sql/sql_help.cc sql/sql_insert.cc sql/sql_join_buffer.cc sql/sql_optimizer.cc sql/sql_parse.cc sql/sql_planner.cc sql/sql_select.cc sql/sql_show.cc sql/sql_table.cc sql/sql_test.cc sql/sql_time.cc sql/sql_tmp_table.cc sql/sql_update.cc sql/sql_yacc.yy sql/sys_vars.cc sql/table.cc sql/table.h sql/tztime.cc storage/blackhole/ha_blackhole.h storage/csv/ha_tina.cc storage/federated/ha_federated.cc storage/innobase/api/api0api.cc storage/innobase/dict/dict0dict.cc storage/innobase/dict/dict0load.cc storage/innobase/dict/dict0mem.cc storage/innobase/fil/fil0fil.cc storage/innobase/handler/ha_innodb.cc storage/innobase/handler/ha_innodb.h storage/innobase/handler/handler0alter.cc storage/innobase/include/dict0dict.h storage/innobase/include/dict0dict.ic storage/innobase/include/dict0mem.h storage/innobase/include/dict0stats.ic storage/innobase/include/fil0fil.h storage/innobase/include/fts0priv.ic storage/innobase/include/fts0types.ic storage/innobase/include/row0merge.h storage/innobase/include/row0upd.ic storage/innobase/include/srv0srv.h storage/innobase/row/row0ins.cc storage/innobase/row/row0log.cc storage/innobase/row/row0merge.cc storage/innobase/row/row0mysql.cc storage/innobase/row/row0sel.cc storage/innobase/row/row0upd.cc storage/innobase/sync/sync0arr.cc unittest/gunit/decimal-t.cc unittest/gunit/dynarray-t.cc unittest/gunit/fake_table.h unittest/gunit/stdcxx-t.cc === modified file 'include/my_base.h' --- a/include/my_base.h 2012-04-24 06:21:11 +0000 +++ b/include/my_base.h 2012-05-03 08:10:14 +0000 @@ -193,7 +193,12 @@ enum ha_extra_function { HA_EXTRA_ADD_CHILDREN_LIST, HA_EXTRA_ATTACH_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 }; /* Compatible option, to be deleted in 6.0 */ === modified file 'include/mysql_com.h' --- a/include/mysql_com.h 2012-04-10 12:20:05 +0000 +++ b/include/mysql_com.h 2012-05-03 08:10:14 +0000 @@ -150,6 +150,7 @@ enum enum_server_command #define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */ #define REFRESH_DES_KEY_FILE 0x40000L #define REFRESH_USER_RESOURCES 0x80000L +#define REFRESH_FOR_EXPORT 0x100000L /* FLUSH TABLES ... FOR EXPORT */ #define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */ #define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */ === modified file 'mysql-test/r/flush_table.result' --- a/mysql-test/r/flush_table.result 2012-04-12 06:38:47 +0000 +++ b/mysql-test/r/flush_table.result 2012-05-03 08:10:14 +0000 @@ -150,15 +150,157 @@ DROP PROCEDURE export; # new FLUSH TABLES ... FOR EXPORT syntax: FLUSH TABLES FOR EXPORT; ERROR 42000: No tables used near 'FOR EXPORT' at line 1 -CREATE TABLE t1 (i INT); +CREATE TABLE t1 (i INT) engine=InnoDB; CREATE TABLE t2 LIKE t1; FLUSH TABLES t1, t2 FOR EXPORT; UNLOCK TABLES; DROP TABLES t1, t2; # new "EXPORT" keyword is a valid table name: -CREATE TABLE export (i INT); +CREATE TABLE export (i INT) engine=InnoDB; # it's ok to lock the "export" table for export: FLUSH TABLE export FOR EXPORT; UNLOCK TABLES; DROP TABLE export; +# +# WL#6169 FLUSH TABLES ... FOR EXPORT -- runtime +# +# Test 1: Views, temporary tables, non-existent tables +# +CREATE VIEW v1 AS SELECT 1; +CREATE TEMPORARY TABLE t1 (a INT); +FLUSH TABLES v1 FOR EXPORT; +ERROR HY000: 'test.v1' is not BASE TABLE +FLUSH TABLES t1 FOR EXPORT; +ERROR 42S02: Table 'test.t1' doesn't exist +FLUSH TABLES non_existent FOR EXPORT; +ERROR 42S02: Table 'test.non_existent' doesn't exist +DROP TEMPORARY TABLE t1; +DROP VIEW v1; +# Test 2: Blocked by update transactions, blocks updates. +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) engine= InnoDB; +CREATE TABLE t2 (a INT) engine= InnoDB; +# Connection con1 +START TRANSACTION; +INSERT INTO t1 VALUES (1, 1); +# Connection default +# Should be blocked +# Sending: +FLUSH TABLES t1 FOR EXPORT; +# Connection con1 +COMMIT; +# Connection default +# Reaping: FLUSH TABLES t1 FOR EXPORT +# Connection con1 +# Should not be blocked +INSERT INTO t2 VALUES (1); +# Should be blocked +# Sending: +INSERT INTO t1 VALUES (2, 2); +# Connection default +UNLOCK TABLES; +# Connection con1 +# Reaping: INSERT INTO t1 VALUES (2, 2); +# Test 3: Read operations should not be affected. +# +START TRANSACTION; +SELECT * FROM t1; +a b +1 1 +2 2 +# Connection default +# Should not be blocked +FLUSH TABLES t1 FOR EXPORT; +# Connection con1 +COMMIT; +# Should not be blocked +SELECT * FROM t1; +a b +1 1 +2 2 +# Connection default +UNLOCK TABLES; +# Test 4: Blocked by DDL, blocks DDL. +# +START TRANSACTION; +SELECT * FROM t1; +a b +1 1 +2 2 +# Connection con2 +# Sending: +ALTER TABLE t1 ADD INDEX i1(b); +# Connection con1 +# Should be blocked +FLUSH TABLE t1 FOR EXPORT; +# Connection default +COMMIT; +# Connection con2 +# Reaping ALTER TABLE ... +# Connection con1 +# Reaping FLUSH TABLE t1 FOR EXPORT +UNLOCK TABLES; +# Connection default +FLUSH TABLE t1 FOR EXPORT; +# Connection con2 +# Should be blocked +DROP TABLE t1; +# Connection default +UNLOCK TABLES; +# Connection con2 +# Reaping DROP TABLE t1 +# Connection default +DROP TABLE t2; +# Test 5: Compatibilty with FLUSH TABLES WITH READ LOCK +# +CREATE TABLE t1(a INT) engine= InnoDB; +FLUSH TABLES WITH READ LOCK; +# Connection con1 +# This should not block +FLUSH TABLE t1 FOR EXPORT; +UNLOCK TABLES; +# Connection default +UNLOCK TABLES; +DROP TABLE t1; +# Test 6: Unsupported storage engines. +# +CREATE TABLE t1(a INT) engine= MyISAM; +FLUSH TABLE t1 FOR EXPORT; +ERROR HY000: Table storage engine for 't1' doesn't have this option +DROP TABLE t1; +# Connection con1 +# Connection defalt +# Test 7: Check privileges required. +# +CREATE DATABASE db1; +CREATE TABLE db1.t1 (a INT) engine= InnoDB; +GRANT RELOAD, SELECT, LOCK TABLES ON *.* TO user1@localhost; +GRANT CREATE, DROP ON *.* TO user2@localhost; +GRANT RELOAD, SELECT ON *.* TO user3@localhost; +GRANT SELECT, LOCK TABLES ON *.* TO user4@localhost; +GRANT RELOAD, LOCK TABLES ON *.* TO user5@localhost; +# Connection con1 as user1 +FLUSH TABLE db1.t1 FOR EXPORT; +UNLOCK TABLES; +# Connection default +# Connection con1 as user2 +FLUSH TABLE db1.t1 FOR EXPORT; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +# Connection default +# Connection con1 as user3 +FLUSH TABLE db1.t1 FOR EXPORT; +ERROR 42000: Access denied for user 'user3'@'localhost' to database 'db1' +# Connection default +# Connection con1 as user4 +FLUSH TABLE db1.t1 FOR EXPORT; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +# Connection default +# Connection con1 as user5 +FLUSH TABLE db1.t1 FOR EXPORT; +ERROR 42000: SELECT command denied to user 'user5'@'localhost' for table 't1' +# Connection default +DROP USER user1@localhost, user2@localhost, user3@localhost, +user4@localhost, user5@localhost; +DROP TABLE db1.t1; +DROP DATABASE db1; # End of 5.6 tests === modified file 'mysql-test/t/flush_table.test' --- a/mysql-test/t/flush_table.test 2012-04-12 06:38:47 +0000 +++ b/mysql-test/t/flush_table.test 2012-05-03 08:10:14 +0000 @@ -163,7 +163,7 @@ DROP PROCEDURE export; --error ER_PARSE_ERROR FLUSH TABLES FOR EXPORT; -CREATE TABLE t1 (i INT); +CREATE TABLE t1 (i INT) engine=InnoDB; CREATE TABLE t2 LIKE t1; FLUSH TABLES t1, t2 FOR EXPORT; @@ -173,7 +173,7 @@ DROP TABLES t1, t2; --echo # new "EXPORT" keyword is a valid table name: -CREATE TABLE export (i INT); +CREATE TABLE export (i INT) engine=InnoDB; --echo # it's ok to lock the "export" table for export: @@ -182,5 +182,269 @@ UNLOCK TABLES; DROP TABLE export; + +--echo # +--echo # WL#6169 FLUSH TABLES ... FOR EXPORT -- runtime +--echo # + +--echo # Test 1: Views, temporary tables, non-existent tables +--echo # + +CREATE VIEW v1 AS SELECT 1; +CREATE TEMPORARY TABLE t1 (a INT); + +--error ER_WRONG_OBJECT +FLUSH TABLES v1 FOR EXPORT; +--error ER_NO_SUCH_TABLE +FLUSH TABLES t1 FOR EXPORT; +--error ER_NO_SUCH_TABLE +FLUSH TABLES non_existent FOR EXPORT; + +DROP TEMPORARY TABLE t1; +DROP VIEW v1; + +--echo # Test 2: Blocked by update transactions, blocks updates. +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT) engine= InnoDB; +CREATE TABLE t2 (a INT) engine= InnoDB; + +--echo # Connection con1 +--connect (con1, localhost, root) +START TRANSACTION; +INSERT INTO t1 VALUES (1, 1); + +--echo # Connection default +--connection default +--echo # Should be blocked +--echo # Sending: +--send FLUSH TABLES t1 FOR EXPORT + +--echo # Connection con1 +--connection con1 +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for table metadata lock" AND + info = "FLUSH TABLES t1 FOR EXPORT"; +--source include/wait_condition.inc +COMMIT; + +--echo # Connection default +--connection default +--echo # Reaping: FLUSH TABLES t1 FOR EXPORT +--reap + +--echo # Connection con1 +--connection con1 +--echo # Should not be blocked +INSERT INTO t2 VALUES (1); +--echo # Should be blocked +--echo # Sending: +--send INSERT INTO t1 VALUES (2, 2) + +--echo # Connection default +--connection default +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for table metadata lock" AND + info = "INSERT INTO t1 VALUES (2, 2)"; +--source include/wait_condition.inc +UNLOCK TABLES; + +--echo # Connection con1 +--connection con1 +--echo # Reaping: INSERT INTO t1 VALUES (2, 2); +--reap + +--echo # Test 3: Read operations should not be affected. +--echo # + +START TRANSACTION; +SELECT * FROM t1; + +--echo # Connection default +--connection default +--echo # Should not be blocked +FLUSH TABLES t1 FOR EXPORT; + +--echo # Connection con1 +--connection con1 +COMMIT; +--echo # Should not be blocked +SELECT * FROM t1; + +--echo # Connection default +--connection default +UNLOCK TABLES; + +--echo # Test 4: Blocked by DDL, blocks DDL. +--echo # + +START TRANSACTION; +SELECT * FROM t1; + +--echo # Connection con2 +--connect (con2, localhost, root) +--echo # Sending: +--send ALTER TABLE t1 ADD INDEX i1(b) + +--echo # Connection con1 +--connection con1 +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for table metadata lock" AND + info = "ALTER TABLE t1 ADD INDEX i1(b)"; +--source include/wait_condition.inc +--echo # Should be blocked +--send FLUSH TABLE t1 FOR EXPORT + +--echo # Connection default +--connection default +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for table metadata lock" AND + info = "FLUSH TABLE t1 FOR EXPORT"; +--source include/wait_condition.inc +COMMIT; + +--echo # Connection con2 +--connection con2 +--echo # Reaping ALTER TABLE ... +--reap + +--echo # Connection con1 +--connection con1 +--echo # Reaping FLUSH TABLE t1 FOR EXPORT +--reap +UNLOCK TABLES; + +--echo # Connection default +--connection default +FLUSH TABLE t1 FOR EXPORT; + +--echo # Connection con2 +--connection con2 +--echo # Should be blocked +--send DROP TABLE t1 + +--echo # Connection default +--connection default +let $wait_condition= + SELECT COUNT(*) = 1 FROM information_schema.processlist + WHERE state = "Waiting for table metadata lock" AND + info = "DROP TABLE t1"; +--source include/wait_condition.inc +UNLOCK TABLES; + +--echo # Connection con2 +--connection con2 +--echo # Reaping DROP TABLE t1 +--reap +--disconnect con2 +--source include/wait_until_disconnected.inc + +--echo # Connection default +--connection default +DROP TABLE t2; + +--echo # Test 5: Compatibilty with FLUSH TABLES WITH READ LOCK +--echo # + +CREATE TABLE t1(a INT) engine= InnoDB; +FLUSH TABLES WITH READ LOCK; + +--echo # Connection con1 +--connection con1 +--echo # This should not block +FLUSH TABLE t1 FOR EXPORT; +UNLOCK TABLES; + +--echo # Connection default +--connection default +UNLOCK TABLES; +DROP TABLE t1; + +--echo # Test 6: Unsupported storage engines. +--echo # + +CREATE TABLE t1(a INT) engine= MyISAM; +--error ER_ILLEGAL_HA +FLUSH TABLE t1 FOR EXPORT; +DROP TABLE t1; + +--echo # Connection con1 +--connection con1 +--disconnect con1 +--source include/wait_until_disconnected.inc + +--echo # Connection defalt +--connection default + +--echo # Test 7: Check privileges required. +--echo # + +CREATE DATABASE db1; +CREATE TABLE db1.t1 (a INT) engine= InnoDB; +GRANT RELOAD, SELECT, LOCK TABLES ON *.* TO user1@localhost; +GRANT CREATE, DROP ON *.* TO user2@localhost; +GRANT RELOAD, SELECT ON *.* TO user3@localhost; +GRANT SELECT, LOCK TABLES ON *.* TO user4@localhost; +GRANT RELOAD, LOCK TABLES ON *.* TO user5@localhost; + +--echo # Connection con1 as user1 +--connect(con1, localhost, user1) +FLUSH TABLE db1.t1 FOR EXPORT; +UNLOCK TABLES; +--disconnect con1 +--source include/wait_until_disconnected.inc + +--echo # Connection default +--connection default + +--echo # Connection con1 as user2 +--connect(con1, localhost, user2) +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +FLUSH TABLE db1.t1 FOR EXPORT; +--disconnect con1 +--source include/wait_until_disconnected.inc + +--echo # Connection default +--connection default + +--echo # Connection con1 as user3 +--connect(con1, localhost, user3) +--error ER_DBACCESS_DENIED_ERROR +FLUSH TABLE db1.t1 FOR EXPORT; +--disconnect con1 +--source include/wait_until_disconnected.inc + +--echo # Connection default +--connection default + +--echo # Connection con1 as user4 +--connect(con1, localhost, user4) +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +FLUSH TABLE db1.t1 FOR EXPORT; +--disconnect con1 +--source include/wait_until_disconnected.inc + +--echo # Connection default +--connection default + +--echo # Connection con1 as user5 +--connect(con1, localhost, user5) +--error ER_TABLEACCESS_DENIED_ERROR +FLUSH TABLE db1.t1 FOR EXPORT; +--disconnect con1 +--source include/wait_until_disconnected.inc + +--echo # Connection default +--connection default +DROP USER user1@localhost, user2@localhost, user3@localhost, + user4@localhost, user5@localhost; +DROP TABLE db1.t1; +DROP DATABASE db1; + + --echo # End of 5.6 tests === modified file 'sql/handler.h' --- a/sql/handler.h 2012-05-02 12:04:42 +0000 +++ b/sql/handler.h 2012-05-03 08:10:14 +0000 @@ -202,6 +202,12 @@ enum enum_alter_inplace_result { */ #define HA_READ_OUT_OF_SYNC (LL(1) << 40) +/* + Storage engine supports table export using the + FLUSH TABLE FOR EXPORT statement. +*/ +#define HA_CAN_EXPORT (LL(1) << 41) + /* bits in index_flags(index_number) for what you can do with index */ #define HA_READ_NEXT 1 /* TODO really use this flag */ #define HA_READ_PREV 2 /* supports ::index_prev */ === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2012-04-30 07:13:31 +0000 +++ b/sql/sql_parse.cc 2012-05-03 08:10:14 +0000 @@ -4033,6 +4033,17 @@ end_with_restore_list: 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); + break; + } /* reload_acl_and_cache() will tell us if we are allowed to write to the === modified file 'sql/sql_reload.cc' --- a/sql/sql_reload.cc 2012-04-13 12:00:39 +0000 +++ b/sql/sql_reload.cc 2012-05-03 08:10:14 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -454,7 +454,7 @@ bool flush_tables_with_read_lock(THD *th /* Before opening and locking tables the below call also waits for old shares to go away, so the fact that we don't pass - MYSQL_LOCK_IGNORE_FLUSH flag to it is important. + MYSQL_OPEN_IGNORE_FLUSH flag to it is important. Also we don't pass MYSQL_OPEN_HAS_MDL_LOCK flag as we want to open underlying tables if merge table is flushed. For underlying tables of the merge the below call has to @@ -484,4 +484,79 @@ error: } +/** + 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) + { + 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. + for (TABLE_LIST *table_list= all_tables; table_list; + table_list= table_list->next_global) + { + if (!(table_list->table->file->ha_table_flags() & HA_CAN_EXPORT)) + { + my_error(ER_ILLEGAL_HA, MYF(0), table_list->table_name); + 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)) + return true; + thd->variables.option_bits|= OPTION_TABLE_LOCK; + + return false; +} === modified file 'sql/sql_reload.h' --- a/sql/sql_reload.h 2010-12-07 16:11:13 +0000 +++ b/sql/sql_reload.h 2012-05-03 08:10:14 +0000 @@ -1,6 +1,6 @@ #ifndef SQL_RELOAD_INCLUDED #define SQL_RELOAD_INCLUDED -/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,4 +23,6 @@ bool reload_acl_and_cache(THD *thd, unsi bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables); +bool flush_tables_for_export(THD *thd, TABLE_LIST *all_tables); + #endif === modified file 'sql/sql_yacc.yy' --- a/sql/sql_yacc.yy 2012-05-02 12:48:08 +0000 +++ b/sql/sql_yacc.yy 2012-05-03 08:10:14 +0000 @@ -12346,13 +12346,8 @@ opt_flush_lock: } EXPORT_SYM { - /* - Following code is a temporary copy of the "WITH READ LOCK" logic - from the previous rule. - TODO: Runtime: replace with the "FOR EXPORT" implementation. - */ TABLE_LIST *tables= Lex->query_tables; - Lex->type|= REFRESH_READ_LOCK; + Lex->type|= REFRESH_FOR_EXPORT; for (; tables; tables= tables->next_global) { tables->mdl_request.set_type(MDL_SHARED_NO_WRITE); === modified file 'storage/innobase/handler/ha_innodb.cc' --- a/storage/innobase/handler/ha_innodb.cc 2012-04-30 13:39:52 +0000 +++ b/storage/innobase/handler/ha_innodb.cc 2012-05-03 08:10:14 +0000 @@ -2082,7 +2082,7 @@ ha_innobase::ha_innobase( HA_BINLOG_ROW_CAPABLE | HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ | HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT | - HA_CAN_FULLTEXT_EXT), + HA_CAN_FULLTEXT_EXT | HA_CAN_EXPORT), start_of_scan(0), num_write_row(0) {} No bundle (reason: useless for push emails).