summaryrefslogtreecommitdiff
path: root/sql/handler.cc
diff options
context:
space:
mode:
authorunknown <guilhem@mysql.com>2004-08-20 16:35:23 +0200
committerunknown <guilhem@mysql.com>2004-08-20 16:35:23 +0200
commitcd8054d4318077827bcf20e640af6fcddf1d9525 (patch)
tree9d89f6beb28a1d747c302488d23cb8d5bfca7507 /sql/handler.cc
parentf758ada4bcfdf9b22b1603bc273b5e2a6436037b (diff)
downloadmariadb-git-cd8054d4318077827bcf20e640af6fcddf1d9525.tar.gz
Making FLUSH TABLES WITH READ LOCK block COMMITs of existing transactions,
in a deadlock-free manner. This splits locking the global read lock in two steps. This fixes a consequence of this bug, known as: BUG#4953 'mysqldump --master-data may report incorrect binlog position if using InnoDB' And a test. sql/handler.cc: making COMMIT wait if FLUSH TABLES WITH READ LOCK happened. sql/lock.cc: an additional stage so that FLUSH TABLES WITH READ LOCK blocks COMMIT: make_global_read_lock_block_commit(): taking the global read lock is TWO steps (2nd step is optional; without it, COMMIT of existing transactions will be allowed): lock_global_read_lock() THEN make_global_read_lock_block_commit(). sql/mysql_priv.h: new argument to wait_if_global_read_lock() sql/sql_class.h: THD::global_read_lock now an uint to reflect the 2 steps of global read lock (does not block COMMIT / does) sql/sql_db.cc: update for new prototype sql/sql_parse.cc: implementing the two steps of global read lock so that FLUSH TABLES WITH READ LOCK can block COMMIT without deadlocking with COMMITs.
Diffstat (limited to 'sql/handler.cc')
-rw-r--r--sql/handler.cc31
1 files changed, 23 insertions, 8 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index a1e738583fd..9eb129fab45 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -342,17 +342,30 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
#ifdef USING_TRANSACTIONS
if (opt_using_transactions)
{
- bool operation_done= 0;
+ bool operation_done= 0, need_start_waiters= 0;
bool transaction_commited= 0;
-
- /* Update the binary log if we have cached some queries */
- if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
+ /* If transaction has done some updates to tables */
+ if (trans == &thd->transaction.all &&
my_b_tell(&thd->transaction.trans_log))
{
- mysql_bin_log.write(thd, &thd->transaction.trans_log, 1);
- reinit_io_cache(&thd->transaction.trans_log,
- WRITE_CACHE, (my_off_t) 0, 0, 1);
- thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
+ if (error= wait_if_global_read_lock(thd, 0, 0))
+ {
+ /*
+ Note that ROLLBACK [TO SAVEPOINT] does not have this test; it's
+ because ROLLBACK never updates data, so needn't wait on the lock.
+ */
+ my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
+ error= 1;
+ }
+ else
+ need_start_waiters= 1;
+ if (mysql_bin_log.is_open())
+ {
+ mysql_bin_log.write(thd, &thd->transaction.trans_log, 1);
+ reinit_io_cache(&thd->transaction.trans_log,
+ WRITE_CACHE, (my_off_t) 0, 0, 1);
+ thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
+ }
}
#ifdef HAVE_BERKELEY_DB
if (trans->bdb_tid)
@@ -393,6 +406,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
statistic_increment(ha_commit_count,&LOCK_status);
thd->transaction.cleanup();
}
+ if (need_start_waiters)
+ start_waiting_global_read_lock(thd);
}
#endif // using transactions
DBUG_RETURN(error);