Copyright (c) 2009, Facebook, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Facebook nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY Facebook, Inc ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Facebook, Inc BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Provide fast and non-blocking alternative to FLUSH TABLES WITH READ LOCK for hot backup. See mysqlha.blogspot.com/2009/10/be-careful-with-flush-tables-with-read.html for context. This adds START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT that starts an Innodb transaction and returns the master binlog filename and offset. When this is used for backups, replication should be restarted at those return values. The new START command returns 1 row with 2 columns (File, Position) on success. --- mysql-test/r/innodb_snapshot_nobinlog.result | 6 + mysql-test/r/innodb_snapshot_noinnodb.result | 5 + mysql-test/r/rpl_innodb_snapshot.result | 112 ++++++++++++ mysql-test/t/innodb_snapshot_nobinlog-master.opt | 1 + mysql-test/t/innodb_snapshot_nobinlog.test | 10 + mysql-test/t/innodb_snapshot_noinnodb-master.opt | 1 + mysql-test/t/innodb_snapshot_noinnodb.test | 9 + mysql-test/t/rpl_innodb_snapshot.test | 198 ++++++++++++++++++++++ sql/ha_innodb.cc | 28 +++- sql/ha_innodb.h | 10 +- sql/handler.cc | 23 ++- sql/handler.h | 4 +- sql/slave.h | 1 + sql/sql_parse.cc | 16 ++- sql/sql_repl.cc | 25 +++ sql/sql_yacc.yy | 4 + --- diff --git a/mysql-test/r/innodb_snapshot_nobinlog.result b/mysql-test/r/innodb_snapshot_nobinlog.result new file mode 100644 index 0000000..278b352 --- /dev/null +++ b/mysql-test/r/innodb_snapshot_nobinlog.result @@ -0,0 +1,6 @@ +SHOW MASTER STATUS; +File Position Binlog_Do_DB Binlog_Ignore_DB +START TRANSACTION; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; +ERROR HY000: Cannot start InnoDB transaction or binlog disabled diff --git a/mysql-test/r/innodb_snapshot_noinnodb.result b/mysql-test/r/innodb_snapshot_noinnodb.result new file mode 100644 index 0000000..989b304 --- /dev/null +++ b/mysql-test/r/innodb_snapshot_noinnodb.result @@ -0,0 +1,5 @@ +START TRANSACTION; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +ERROR HY000: InnoDB disabled +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; +ERROR HY000: InnoDB disabled diff --git a/mysql-test/r/rpl_innodb_snapshot.result b/mysql-test/r/rpl_innodb_snapshot.result new file mode 100644 index 0000000..e9053b7 --- /dev/null +++ b/mysql-test/r/rpl_innodb_snapshot.result @@ -0,0 +1,112 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +DROP TABLE IF EXISTS t1; +# Establish connection con1 (user=root) +# Establish connection con2 (user=root) +# Establish connection con3 (user=root) +# Establish connection con4 (user=root) +# reset replication to guarantee that master-bin.000001 is used +STOP SLAVE; +RESET SLAVE; +RESET MASTER; +CHANGE MASTER TO master_host="127.0.0.1",master_port=MASTER_PORT,master_user="root"; +START SLAVE; +# Switch to connection con1 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb; +INSERT INTO t1 VALUES(1); +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; +File Position +master-bin.000001 392 +# Switch to connection con2 +INSERT INTO t1 VALUES(2); +INSERT INTO t1 VALUES(3); +# Switch to connection con1 +SELECT * FROM t1; +a +1 +COMMIT; +SELECT * FROM t1; +a +1 +2 +3 +DROP TABLE t1; +# Switch to connection con1 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb; +INSERT INTO t1 VALUES(1); +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; +File Position +master-bin.000001 1126 +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; +File Position +master-bin.000001 1126 +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; +File Position +master-bin.000001 1126 +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; +File Position +master-bin.000001 1126 +# Switch to connection con2 +INSERT INTO t1 VALUES(2); +INSERT INTO t1 VALUES(3); +# Switch to connection con1 +SELECT * FROM t1; +a +1 +SELECT * INTO OUTFILE '/tmp/rpl_innodb_snapshot.out.file' FROM t1; +COMMIT; +# Switch to slave +CREATE TABLE t1_backup AS SELECT * FROM t1; +STOP SLAVE; +RESET SLAVE; +DELETE FROM t1; +LOAD DATA INFILE '/tmp/rpl_innodb_snapshot.out.file' INTO TABLE t1; +SELECT * FROM t1; +a +1 +CHANGE MASTER TO master_host="127.0.0.1",master_port=MASTER_PORT,master_user="root",master_log_file="master-bin.000001",master_log_pos=binlog_pos; +START SLAVE; +SELECT * FROM t1; +a +1 +2 +3 +SELECT * FROM t1_backup; +a +1 +2 +3 +DROP TABLE t1_backup; +DROP TABLE t1; +# Switch to connection con1 +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb; +INSERT INTO t1 VALUES(1); +# async queries from con2 +INSERT INTO t1 VALUES(2); +# async queries from con3 +INSERT INTO t1 VALUES(21); +# Switch to connection con1 +# Switch to connection con4 +INSERT INTO t1 VALUES(9); +# Switch to connection con1 +SELECT * INTO OUTFILE '/tmp/rpl_innodb_snapshot.out.file' FROM t1; +COMMIT; +# reap async statements +# Switch to slave +CREATE TABLE t1_backup AS SELECT * FROM t1; +STOP SLAVE; +RESET SLAVE; +DELETE FROM t1; +LOAD DATA INFILE '/tmp/rpl_innodb_snapshot.out.file' INTO TABLE t1; +CHANGE MASTER TO master_host="127.0.0.1",master_port=MASTER_PORT,master_user="root",master_log_file="master-bin.000001",master_log_pos=binlog_pos; +START SLAVE; +# sync and then query slave +ShouldBeZero +0 +DROP TABLE t1_backup; +DROP TABLE t1; +# Switch to connection default + close connections con1 and con2 diff --git a/mysql-test/t/innodb_snapshot_nobinlog-master.opt b/mysql-test/t/innodb_snapshot_nobinlog-master.opt new file mode 100644 index 0000000..14d7486 --- /dev/null +++ b/mysql-test/t/innodb_snapshot_nobinlog-master.opt @@ -0,0 +1 @@ +--skip_log_bin diff --git a/mysql-test/t/innodb_snapshot_nobinlog.test b/mysql-test/t/innodb_snapshot_nobinlog.test new file mode 100644 index 0000000..ff2e209 --- /dev/null +++ b/mysql-test/t/innodb_snapshot_nobinlog.test @@ -0,0 +1,10 @@ +-- source include/have_innodb.inc + +SHOW MASTER STATUS; + +START TRANSACTION; + +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +--error ER_UNKNOWN_ERROR +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; diff --git a/mysql-test/t/innodb_snapshot_noinnodb-master.opt b/mysql-test/t/innodb_snapshot_noinnodb-master.opt new file mode 100644 index 0000000..31d690b --- /dev/null +++ b/mysql-test/t/innodb_snapshot_noinnodb-master.opt @@ -0,0 +1 @@ +--skip_innodb diff --git a/mysql-test/t/innodb_snapshot_noinnodb.test b/mysql-test/t/innodb_snapshot_noinnodb.test new file mode 100644 index 0000000..82003ce --- /dev/null +++ b/mysql-test/t/innodb_snapshot_noinnodb.test @@ -0,0 +1,9 @@ +# -- source include/have_innodb.inc + +START TRANSACTION; + +-- error ER_UNKNOWN_ERROR +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +-- error ER_UNKNOWN_ERROR +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; diff --git a/mysql-test/t/rpl_innodb_snapshot.test b/mysql-test/t/rpl_innodb_snapshot.test new file mode 100644 index 0000000..54f9747 --- /dev/null +++ b/mysql-test/t/rpl_innodb_snapshot.test @@ -0,0 +1,198 @@ +--source include/master-slave.inc +--source include/have_innodb.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo # Establish connection con1 (user=root) +connect (con1,localhost,root,,); +--echo # Establish connection con2 (user=root) +connect (con2,localhost,root,,); +--echo # Establish connection con3 (user=root) +connect (con3,localhost,root,,); +--echo # Establish connection con4 (user=root) +connect (con4,localhost,root,,); + +--echo # reset replication to guarantee that master-bin.000001 is used +connection slave; +STOP SLAVE; +RESET SLAVE; + +connection master; +RESET MASTER; + +connection slave; +--replace_result $MASTER_MYPORT MASTER_PORT +eval CHANGE MASTER TO master_host="127.0.0.1",master_port=$MASTER_MYPORT,master_user="root"; +START SLAVE; + +### Test 1: +### - While a consistent snapshot transaction is executed, +### no external inserts should be visible to the transaction. + +--echo # Switch to connection con1 +connection con1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb; +INSERT INTO t1 VALUES(1); + +--disable_query_log +--disable_result_log +let $x=1000; +while ($x) { + START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; + dec $x; +} +--enable_query_log +--enable_result_log + +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; + +--echo # Switch to connection con2 +connection con2; +INSERT INTO t1 VALUES(2); +INSERT INTO t1 VALUES(3); + +--echo # Switch to connection con1 +connection con1; +SELECT * FROM t1; # should fetch one row +COMMIT; + +SELECT * FROM t1; # should fetch three rows + +DROP TABLE t1; + +### Test 2: +### - confirm result from snapshot select and replication replay matches original + +--echo # Switch to connection con1 +connection con1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb; +INSERT INTO t1 VALUES(1); + +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; +START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT; + +let $binlog_pos = query_get_value(START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT, Position, 1); + +--echo # Switch to connection con2 +connection con2; +INSERT INTO t1 VALUES(2); +INSERT INTO t1 VALUES(3); + +--echo # Switch to connection con1 +connection con1; +SELECT * FROM t1; + +--let $outfile = $MYSQLTEST_VARDIR/tmp/rpl_innodb_snapshot.out.file + +--replace_result $MYSQLTEST_VARDIR +eval SELECT * INTO OUTFILE '$outfile' FROM t1; +COMMIT; + +--echo # Switch to slave +sync_slave_with_master slave; + +CREATE TABLE t1_backup AS SELECT * FROM t1; +STOP SLAVE; +RESET SLAVE; +DELETE FROM t1; +--replace_result $MYSQLTEST_VARDIR +eval LOAD DATA INFILE '$outfile' INTO TABLE t1; +SELECT * FROM t1; + +--replace_result $MASTER_MYPORT MASTER_PORT $binlog_pos binlog_pos +eval CHANGE MASTER TO master_host="127.0.0.1",master_port=$MASTER_MYPORT,master_user="root",master_log_file="master-bin.000001",master_log_pos=$binlog_pos; +START SLAVE; + +connection master; +sync_slave_with_master slave; + +SELECT * FROM t1; +SELECT * FROM t1_backup; +DROP TABLE t1_backup; + +connection master; +DROP TABLE t1; +--remove_file $outfile + +### Test 3: +### - confirm result from snapshot select and replication replay matches original +### - use non-deterministic concurrency + +--echo # Switch to connection con1 +connection con1; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb; +INSERT INTO t1 VALUES(1); + +--echo # async queries from con2 +connection con2; +send INSERT INTO t1 VALUES(2); + +--echo # async queries from con3 +connection con3; +send INSERT INTO t1 VALUES(21); + +--echo # Switch to connection con1 +connection con1; + +let $binlog_pos = query_get_value(START TRANSACTION WITH CONSISTENT INNODB SNAPSHOT, Position, 1); + +--echo # Switch to connection con4 +connection con4; +INSERT INTO t1 VALUES(9); + +--echo # Switch to connection con1 +connection con1; + +--let $outfile = $MYSQLTEST_VARDIR/tmp/rpl_innodb_snapshot.out.file + +--replace_result $MYSQLTEST_VARDIR +eval SELECT * INTO OUTFILE '$outfile' FROM t1; +COMMIT; + +--echo # reap async statements +connection con2; +reap; + +connection con3; +reap; + +--echo # Switch to slave +sync_slave_with_master slave; + +CREATE TABLE t1_backup AS SELECT * FROM t1; +STOP SLAVE; +RESET SLAVE; +DELETE FROM t1; +--replace_result $MYSQLTEST_VARDIR +eval LOAD DATA INFILE '$outfile' INTO TABLE t1; + +--replace_result $MASTER_MYPORT MASTER_PORT $binlog_pos binlog_pos +eval CHANGE MASTER TO master_host="127.0.0.1",master_port=$MASTER_MYPORT,master_user="root",master_log_file="master-bin.000001",master_log_pos=$binlog_pos; +START SLAVE; + +--echo # sync and then query slave +connection master; +sync_slave_with_master slave; + +let $sum1 = `SELECT SUM(a) from t1`; +let $sum2 = `SELECT SUM(a) from t1_backup`; +--disable_query_log +eval select $sum2 - $sum1 ShouldBeZero; +--enable_query_log + +DROP TABLE t1_backup; + +connection master; +DROP TABLE t1; + +--echo # Switch to connection default + close connections con1 and con2 +connection default; +disconnect con1; +disconnect con2; +disconnect con3; +disconnect con4; + diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index df279c1..aa23a78 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1717,8 +1717,10 @@ int innobase_start_trx_and_assign_read_view( /*====================================*/ /* out: 0 */ - THD* thd) /* in: MySQL thread handle of the user for whom + THD* thd, /* in: MySQL thread handle of the user for whom the transaction should be committed */ + char* binlog_file,/* out: binlog file for last commit */ + ulonglong* binlog_offset)/* out: binlog offset for last commit */ { trx_t* trx; @@ -1738,10 +1740,34 @@ innobase_start_trx_and_assign_read_view( trx_start_if_not_started_noninline(trx); + if (binlog_file) { + /* When binlog_file is set, this code must return the current + binlog file and position for this snapshot. That can only + be done when the binlog is open and when the read view is + assigned now (not previously). Lock prepare_commit_mutex + to guarantee that InnoDB and the binlog agree on the current + commit -- otherwise, the commit may be done to the binlog + and in flight for InnoDB. */ + if (trx->read_view || !mysql_bin_log.is_open()) + DBUG_RETURN(1); + + pthread_mutex_lock(&prepare_commit_mutex); + } + /* Assign a read view if the transaction does not have it yet */ trx_assign_read_view(trx); + if (binlog_file) { + LOG_INFO li; + mysql_bin_log.get_current_log(&li); + + pthread_mutex_unlock(&prepare_commit_mutex); + + strcpy(binlog_file, li.log_file_name); + *binlog_offset = li.pos; + } + /* Set the MySQL flag to mark that there is an active transaction */ if (trx->active_trans == 0) { diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index d585934..3db38f5 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -274,7 +274,15 @@ void innobase_release_temporary_latches(THD *thd); void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset); -int innobase_start_trx_and_assign_read_view(THD* thd); +/**************************************************************************** +Args return binlog filename,offset for last commit when binlog_file not NULL. +Returns 0 on success. Might fail when binlog_file not NULL. +*/ + +int innobase_start_trx_and_assign_read_view( + THD* thd, + char* binlog_file, /* out: file name for last commit */ + ulonglong* binlog_offset); /* out: offset for last commit */ /*********************************************************************** This function is used to prepare X/Open XA distributed transaction */ diff --git a/sql/handler.cc b/sql/handler.cc index 69d8ae8..c0f75c3 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1285,21 +1285,28 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv) } -int ha_start_consistent_snapshot(THD *thd) +int ha_start_consistent_snapshot(THD *thd, bool get_master_pos, + char *binlog_file, ulonglong* binlog_offset) { #ifdef HAVE_INNOBASE_DB - if ((have_innodb == SHOW_OPTION_YES) && - !innobase_start_trx_and_assign_read_view(thd)) - return 0; + if (have_innodb == SHOW_OPTION_YES) + { + if (!innobase_start_trx_and_assign_read_view(thd, binlog_file, binlog_offset)) + return 0; + else + { + my_printf_error(ER_UNKNOWN_ERROR, + "Cannot start InnoDB transaction or binlog disabled", MYF(0)); + return 1; + } + } #endif /* Same idea as when one wants to CREATE TABLE in one engine which does not exist: */ - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, - "This MySQL server does not support any " - "consistent-read capable storage engine"); - return 0; + my_printf_error(ER_UNKNOWN_ERROR, "InnoDB disabled", MYF(0)); + return 1; } diff --git a/sql/handler.h b/sql/handler.h index 430767d..0fd2fa2 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -176,6 +176,7 @@ /* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */ #define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT 1 +#define MYSQL_START_TRANS_OPT_WITH_CONS_INNODB_SNAPSHOT 2 enum db_type { @@ -1078,7 +1079,8 @@ int ha_end_key_cache(KEY_CACHE *key_cache); int ha_release_temporary_latches(THD *thd); /* transactions: interface to handlerton functions */ -int ha_start_consistent_snapshot(THD *thd); +int ha_start_consistent_snapshot(THD *thd, bool get_master_pos, + char* master_file, ulonglong* master_offset); int ha_commit_or_rollback_by_xid(XID *xid, bool commit); int ha_commit_one_phase(THD *thd, bool all); int ha_rollback_trans(THD *thd, bool all); diff --git a/sql/slave.h b/sql/slave.h index 5ae596f..38a08af 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -529,6 +529,7 @@ void table_rule_ent_hash_to_str(String* s, HASH* h); void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a); bool show_master_info(THD* thd, MASTER_INFO* mi); bool show_binlog_info(THD* thd); +bool show_master_offset(THD* thd, const char* file, ulonglong offset); bool rpl_master_has_bug(RELAY_LOG_INFO *rli, uint bug_id); /* See if the query uses any tables that should not be replicated */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4def8ea..2650822 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -235,7 +235,15 @@ static bool begin_trans(THD *thd) thd->options|= OPTION_BEGIN; thd->server_status|= SERVER_STATUS_IN_TRANS; if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) - error= ha_start_consistent_snapshot(thd); + error= ha_start_consistent_snapshot(thd, FALSE, NULL, NULL); + else if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_INNODB_SNAPSHOT) + { + ulonglong binlog_offset; + char binlog_file[FN_REFLEN + 1]; + error= ha_start_consistent_snapshot(thd, TRUE, binlog_file, &binlog_offset); + if (!error) + error= show_master_offset(thd, binlog_file, binlog_offset); + } } return error; } @@ -1519,6 +1527,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) { bool do_release= 0; int res= 0; + DBUG_ENTER("end_trans"); if (unlikely(thd->in_sub_stmt)) @@ -4668,7 +4677,10 @@ end_with_restore_list: } if (begin_trans(thd)) goto error; - send_ok(thd); + /* When MYSQL_START_TRANS_OPT_WITH_CONS_INNODB_SNAPSHOT is set, the result has already + been sent. */ + if (!(thd->lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_INNODB_SNAPSHOT)) + send_ok(thd); break; case SQLCOM_COMMIT: if (end_trans(thd, lex->tx_release ? COMMIT_RELEASE : diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 3d2cee6..0abe4f3 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1439,6 +1439,31 @@ err: DBUG_RETURN(ret); } +bool show_master_offset(THD* thd, const char* file, ulonglong offset) +{ + Protocol *protocol= thd->protocol; + DBUG_ENTER("show_master_offset"); + List field_list; + field_list.push_back(new Item_empty_string("File", FN_REFLEN)); + field_list.push_back(new Item_return_int("Position",20, + MYSQL_TYPE_LONGLONG)); + + if (protocol->send_fields(&field_list, + Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) + DBUG_RETURN(TRUE); + + protocol->prepare_for_resend(); + + int dir_len = dirname_length(file); + protocol->store(file + dir_len, &my_charset_bin); + + protocol->store(offset); + if (protocol->write()) + DBUG_RETURN(TRUE); + + send_eof(thd); + DBUG_RETURN(FALSE); +} bool show_binlog_info(THD* thd) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 32d06c4..4b54b2d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4083,6 +4083,10 @@ start_transaction_opts: { $$= MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT; } + | WITH CONSISTENT_SYM INNOBASE_SYM SNAPSHOT_SYM + { + $$= MYSQL_START_TRANS_OPT_WITH_CONS_INNODB_SNAPSHOT; + } ; slave_thread_opts: -- 1.6.0.4.609.g474fc