Bug #68845 Unnecessary log_sys->mutex reacquisition in mtr_log_reserve_and_write()
Submitted: 3 Apr 2013 6:51 Modified: 15 Apr 2013 17:33
Reporter: Alexey Kopytov Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S4 (Feature request)
Version:5.1, 5.5, 5.6 OS:Any
Assigned to: CPU Architecture:Any

[3 Apr 2013 6:51] Alexey Kopytov
Description:
mtr_log_reserve_and_write() implements the following logic with respect
to log_sys->mutex: if the mini-transaction log contains a single block,
it calls log_reserve_and_write_fast() which acquires log_sys->mutex and
does a "fast" write by appending the new record to the current log
block. If the record does not fit in the current log block,
log_reserve_and_write_fast() releases log_sys->mutex and returns 0, in
which case mtr_log_reserve_and_write() immediately reacquires
log_sys->mutex by calling log_reserve_and_open() and proceeds with the
"slow" write procedure.

It doesn't make sense to release a mutex and reacquire it immediately
and benchmarks show that avoiding this helps to reduce log_sys->mutex
contention in some write-intensive workloads.

How to repeat:
Read the mtr_log_reserve_and_write() code.
[15 Apr 2013 17:33] MySQL Verification Team
I have inspected the code, debugged through it and verified that Kaamos' findings are true.

This is a small feature request, but still a valid one.

InnoDB source in this respect is a bit cryptic by using different names for same structures, like log and log_sys.
[19 Jul 2014 12:14] Laurynas Biveinis
This appears to be fixed in 5.7:

mtr_t::Command::write()
{
...
		m_end_lsn = log_reserve_and_write_fast(data, len, &m_start_lsn);

		if (m_end_lsn > 0) {
			return;
		}

		own_mutex = true;
	} else {
		own_mutex = false;
	}

	/* Open the database log for log_write_low */
	m_start_lsn = log_reserve_and_open(m_impl->m_log.size(), own_mutex);
...

where log_reserve_and_write_fast does not release the mutex and log_reserve_and_open uses own_mutex flag to either take or not take it.