5056 Andrei Elkin 2012-11-21 [merge]
merge from 5.6 bugfixing branch.
modified:
sql/binlog.cc
sql/binlog.h
sql/sql_class.h
5055 Sunny Bains 2012-11-21 [merge]
Merge from mysql-5.6.
modified:
storage/innobase/include/trx0purge.h
storage/innobase/srv/srv0srv.cc
storage/innobase/trx/trx0purge.cc
=== modified file 'sql/binlog.cc'
--- a/sql/binlog.cc revid:sunny.bains@stripped
+++ b/sql/binlog.cc revid:andrei.elkin@stripped
@@ -1334,6 +1334,16 @@ Stage_manager::enroll_for(StageID stage,
if (!leader)
{
mysql_mutex_lock(&m_lock_done);
+#ifndef DBUG_OFF
+ /*
+ Leader can be awaiting all-clear to preempt follower's execution.
+ With setting the status the follower ensures it won't execute anything
+ including thread-specific code.
+ */
+ thd->transaction.flags.ready_preempt= 1;
+ if (leader_await_preempt_status)
+ mysql_cond_signal(&m_cond_preempt);
+#endif
while (thd->transaction.flags.pending)
mysql_cond_wait(&m_cond_done, &m_lock_done);
mysql_mutex_unlock(&m_lock_done);
@@ -1361,6 +1371,22 @@ THD *Stage_manager::Mutex_queue::fetch_a
DBUG_RETURN(result);
}
+#ifndef DBUG_OFF
+void Stage_manager::clear_preempt_status(THD *head)
+{
+ DBUG_ASSERT(head);
+
+ mysql_mutex_lock(&m_lock_done);
+ while(!head->transaction.flags.ready_preempt)
+ {
+ leader_await_preempt_status= true;
+ mysql_cond_wait(&m_cond_preempt, &m_lock_done);
+ }
+ leader_await_preempt_status= false;
+ mysql_mutex_unlock(&m_lock_done);
+}
+#endif
+
/**
Write a rollback record of the transaction to the binary log.
@@ -6005,6 +6031,9 @@ MYSQL_BIN_LOG::process_commit_stage_queu
{
mysql_mutex_assert_owner(&LOCK_commit);
Thread_excursion excursion(thd);
+#ifndef DBUG_OFF
+ thd->transaction.flags.ready_preempt= 1; // formality by the leader
+#endif
for (THD *head= first ; head ; head = head->next_to_commit)
{
DBUG_PRINT("debug", ("Thread ID: %lu, commit_error: %d, flags.pending: %s",
@@ -6018,6 +6047,9 @@ MYSQL_BIN_LOG::process_commit_stage_queu
If flush succeeded, attach to the session and commit it in the
engines.
*/
+#ifndef DBUG_OFF
+ stage_manager.clear_preempt_status(head);
+#endif
if (flush_error != 0)
head->commit_error= flush_error;
else if (int error= excursion.attach_to(head))
@@ -6027,6 +6059,9 @@ MYSQL_BIN_LOG::process_commit_stage_queu
bool all= head->transaction.flags.real_commit;
if (head->transaction.flags.commit_low)
{
+ /* head is parked to have exited append() */
+ DBUG_ASSERT(head->transaction.flags.ready_preempt);
+
if (int error= ha_commit_low(head, all))
head->commit_error= error;
else if (head->transaction.flags.xid_written)
@@ -6265,6 +6300,17 @@ int MYSQL_BIN_LOG::ordered_commit(THD *t
thd->transaction.flags.real_commit= all;
thd->transaction.flags.xid_written= false;
thd->transaction.flags.commit_low= !skip_commit;
+#ifndef DBUG_OFF
+ /*
+ The group commit Leader may have to wait for follower whose transaction
+ is not ready to be preempted. Initially the status is pessimistic.
+ Preemption guarding logics is necessary only when DBUG_ON is set.
+ It won't be required for the dbug-off case as long as the follower won't
+ execute any thread-specific write access code in this method, which is
+ the case as of current.
+ */
+ thd->transaction.flags.ready_preempt= 0;
+#endif
DBUG_PRINT("enter", ("flags.pending: %s, commit_error: %d, thread_id: %lu",
YESNO(thd->transaction.flags.pending),
=== modified file 'sql/binlog.h'
--- a/sql/binlog.h revid:sunny.bains@stripped
+++ b/sql/binlog.h revid:andrei.elkin@stripped
@@ -119,6 +119,10 @@ public:
{
mysql_mutex_init(key_LOCK_done, &m_lock_done, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_COND_done, &m_cond_done, NULL);
+#ifndef DBUG_OFF
+ /* reuse key_COND_done 'cos a new PSI object would be wasteful in DBUG_ON */
+ mysql_cond_init(key_COND_done, &m_cond_preempt, NULL);
+#endif
m_queue[FLUSH_STAGE].init(
#ifdef HAVE_PSI_INTERFACE
key_LOCK_flush_queue
@@ -155,6 +159,7 @@ public:
If wait_if_follower is true the thread is not the stage leader,
the thread will be wait for the queue to be processed by the
leader before it returns.
+ In DBUG-ON version the follower marks is preempt status as ready.
@param stage Stage identifier for the queue to append to.
@param first Queue to append.
@@ -172,6 +177,17 @@ public:
return m_queue[stage].pop_front();
}
+#ifndef DBUG_OFF
+ /**
+ The method ensures the follower's execution path can be preempted
+ by the leader's thread.
+ Preempt status of @c head follower is checked to engange the leader
+ into waiting when set.
+
+ @param head THD* of a follower thread
+ */
+ void clear_preempt_status(THD *head);
+#endif
/**
Fetch the entire queue and empty it.
@@ -206,6 +222,13 @@ private:
/** Mutex used for the condition variable above */
mysql_mutex_t m_lock_done;
+#ifndef DBUG_OFF
+ /** Flag is set by Leader when it starts waiting for follower's all-clear */
+ bool leader_await_preempt_status;
+
+ /** Condition variable to indicate a follower started waiting for commit */
+ mysql_cond_t m_cond_preempt;
+#endif
};
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h revid:sunny.bains@stripped
+++ b/sql/sql_class.h revid:andrei.elkin@stripped
@@ -2325,6 +2325,9 @@ public:
bool xid_written:1; // The session wrote an XID
bool real_commit:1; // Is this a "real" commit?
bool commit_low:1; // see MYSQL_BIN_LOG::ordered_commit
+#ifndef DBUG_OFF
+ bool ready_preempt:1; // internal in MYSQL_BIN_LOG::ordered_commit
+#endif
} flags;
void cleanup()
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (andrei.elkin:5055 to 5056) | Andrei Elkin | 21 Nov |