summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/flush_block_commit.result15
-rw-r--r--mysql-test/t/flush_block_commit.test21
-rw-r--r--sql/handler.cc33
-rw-r--r--sql/sql_parse.cc13
-rw-r--r--sql/sql_yacc.yy3
5 files changed, 64 insertions, 21 deletions
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 785070176cb..22a4575fe6e 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -586,6 +586,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)
{
@@ -595,7 +600,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);
}
@@ -604,20 +609,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;
@@ -628,18 +641,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;
@@ -664,8 +665,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 9266ab69790..dfd68da7109 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -7251,7 +7251,7 @@ keyword:
| MULTILINESTRING {}
| MULTIPOINT {}
| MULTIPOLYGON {}
- | MUTEX_SYM {}
+ | MUTEX_SYM {}
| NAME_SYM {}
| NAMES_SYM {}
| NATIONAL_SYM {}
@@ -7343,7 +7343,6 @@ keyword:
| TIMESTAMP_ADD {}
| TIMESTAMP_DIFF {}
| TIME_SYM {}
- | TYPE_SYM {}
| TYPES_SYM {}
| UDF_RETURNS_SYM {}
| FUNCTION_SYM {}