diff --git a/mysql-test/r/flush_block_commit.result b/mysql-test/r/flush_block_commit.result index 2e9f1920937..39f4a3719ef 100644 --- a/mysql-test/r/flush_block_commit.result +++ b/mysql-test/r/flush_block_commit.result @@ -37,3 +37,18 @@ show create database test; Database Create Database test CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */ drop table t1; +create table t1 (a int) engine=innodb; +reset master; +set autocommit=0; +insert t1 values (1); +flush tables with read lock; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 98 + commit; +show master status; +File Position Binlog_Do_DB Binlog_Ignore_DB +master-bin.000001 276 +unlock tables; +drop table t1; +set autocommit=1; diff --git a/mysql-test/t/flush_block_commit.test b/mysql-test/t/flush_block_commit.test index 49d68d05fb6..29ef7b8a0b9 100644 --- a/mysql-test/t/flush_block_commit.test +++ b/mysql-test/t/flush_block_commit.test @@ -76,3 +76,24 @@ select * from t1; show create database test; drop table t1; + +# FLUSH TABLES WITH READ LOCK should block writes to binlog too +connection con1; +create table t1 (a int) engine=innodb; +reset master; +set autocommit=0; +insert t1 values (1); +connection con2; +flush tables with read lock; +show master status; +connection con1; +send commit; +connection con2; +sleep 1; +show master status; +unlock tables; +connection con1; +reap; +drop table t1; +set autocommit=1; + diff --git a/sql/handler.cc b/sql/handler.cc index dc63b4b038f..8315ec6bb1a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -587,6 +587,11 @@ int ha_commit_trans(THD *thd, bool all) #ifdef USING_TRANSACTIONS if (trans->nht) { + if (is_real_trans && wait_if_global_read_lock(thd, 0, 0)) + { + ha_rollback_trans(thd, all); + DBUG_RETURN(1); + } DBUG_EXECUTE_IF("crash_commit_before", abort();); if (!trans->no_2pc && trans->nht > 1) { @@ -596,7 +601,7 @@ int ha_commit_trans(THD *thd, bool all) if ((err= (*(*ht)->prepare)(thd, all))) { my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); - error=1; + error= 1; } statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status); } @@ -605,20 +610,28 @@ int ha_commit_trans(THD *thd, bool all) (error= !(cookie= tc_log->log(thd, xid))))) { ha_rollback_trans(thd, all); - return 1; + error= 1; + goto end; } - DBUG_EXECUTE_IF("crash_commit_after_log", abort();); + DBUG_EXECUTE_IF("crash_commit_after_log", abort();); } error=ha_commit_one_phase(thd, all) ? cookie ? 2 : 1 : 0; DBUG_EXECUTE_IF("crash_commit_before_unlog", abort();); if (cookie) tc_log->unlog(cookie, xid); DBUG_EXECUTE_IF("crash_commit_after", abort();); +end: + if (is_real_trans) + start_waiting_global_read_lock(thd); } #endif /* USING_TRANSACTIONS */ DBUG_RETURN(error); } +/* + NOTE - this function does not care about global read lock. + A caller should. +*/ int ha_commit_one_phase(THD *thd, bool all) { int error=0; @@ -629,18 +642,6 @@ int ha_commit_one_phase(THD *thd, bool all) #ifdef USING_TRANSACTIONS if (trans->nht) { - bool need_start_waiters= 0; - if (is_real_trans) - { - if ((error= wait_if_global_read_lock(thd, 0, 0))) - { - my_error(ER_ERROR_DURING_COMMIT, MYF(0), error); - error= 1; - } - else - need_start_waiters= 1; - } - for (ht=trans->ht; *ht; ht++) { int err; @@ -665,8 +666,6 @@ int ha_commit_one_phase(THD *thd, bool all) thd->variables.tx_isolation=thd->session_tx_isolation; thd->transaction.cleanup(); } - if (need_start_waiters) - start_waiting_global_read_lock(thd); } #endif /* USING_TRANSACTIONS */ DBUG_RETURN(error); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ac1b1148cf8..b1f50f68e32 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4414,10 +4414,19 @@ unsent_create_error: else if (thd->transaction.xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE) { - if (ha_commit_one_phase(thd, 1)) + if (wait_if_global_read_lock(thd, 0, 0)) + { + ha_rollback(thd); my_error(ER_XAER_RMERR, MYF(0)); + } else - send_ok(thd); + { + if (ha_commit_one_phase(thd, 1)) + my_error(ER_XAER_RMERR, MYF(0)); + else + send_ok(thd); + start_waiting_global_read_lock(thd); + } } else { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9ff7f4449b2..2c493e27581 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7275,7 +7275,7 @@ keyword: | MULTILINESTRING {} | MULTIPOINT {} | MULTIPOLYGON {} - | MUTEX_SYM {} + | MUTEX_SYM {} | NAME_SYM {} | NAMES_SYM {} | NATIONAL_SYM {} @@ -7367,7 +7367,6 @@ keyword: | TIMESTAMP_ADD {} | TIMESTAMP_DIFF {} | TIME_SYM {} - | TYPE_SYM {} | TYPES_SYM {} | UDF_RETURNS_SYM {} | FUNCTION_SYM {}