Tuesday, August 5, 2008

Mutex contention in MySQL

If you run MySQL on an SMP server and your server is busy, it is good to understand where the bottlenecks are in the server. Mutex contention is one such source. InnoDB provides mutex contention statistics via the SHOW MUTEX STATUS command. Alas, there are no statistics for the mutexes in the rest of MySQL -- unless you are willing to do a lot of refactoring. I used my favorite refactoring tool, sed, to replace many of the uses of pthread_mutex with my_mutex. my_mutex is a simple wrapper for pthread_mutex that provides contention and usage statistics and uses spin waiting prior to blocking on the pthread_mutex.

People who get to use MySQL on Solaris tell me that dtrace and mpstat provide information similar to this. Can someone post details with sample output on a blog post?

Sample output from a recently started server.
  • Locks - number of times the mutex was locked
  • Spins - number of times the caller tried to get the lock before returning or blocking on the pthread_mutex. Must be >= Locks.
  • Sleeps - number of times the caller possibly blocked by calling pthread_mutex_lock after failing to lock the mutex with pthread_mutex_trylock and spinning for ~20 microseconds.
# mysql -e 'show global mutex status'
+-------+-------+--------+----------------------------+
| Locks | Spins | Sleeps | Name           |
+-------+-------+--------+----------------------------+
|    21 |    21 |      0 | LOCK_open          |
|    18 |    18 |      0 | LOCK_thread_count|
|     0 |     0 |      0 | LOCK_status          |
|     4 |     4 |      0 | LOCK_error_log     |
Sample output from a benchmark that reloads tables using 16 database connections on an 8 core server. The mutexes are ranked by the number of Sleeps. The test runs for a few minutes. Contention doesn't appear to be that bad in this case. A mutex for the binlog has the most contention. This is what I hoped for as the statements used for the test insert ~1000 rows, so there is a lot of work done per statement. A benchmark with simpler/faster statements would likely have more contention.

        Locks    Spins     Sleeps  Name
816258  883234  2995    LOCK_log for bin log
544304  558754  602     LOCK_open
548667  552807  189     LOCK_thread_count
273654  274334  12      LOCK_global_user_stats
1088548 1088803 1       LOCK_global_read_lock
544000  544000  0       LOCK_prep_xids
459     459     0       LOCK_xid_cache
4       4       0       LOCK_error_log
274533  274581  0       LOCK_user_conn
272004  272004  0       LOCK_global_table_stats

6 comments:

  1. Hi, Mark

    Can you post your patch? :-)

    --with-fast-mutexes was introduced from 5.1, does it work too on 5.1 or 6.0?

    Thx, Xuekun

    ReplyDelete
  2. My code is too messy to share at this point. I work on 5.0 and wasn't aware that MySQL provided a spin lock. It is a great starting point for what I want. I need to extend it to collect usage statistics and then add a SQL command to export the results.

    ReplyDelete
  3. Mark... One of the MySQL developers (I forget which one) noted that they were working on a more portable mutex implementation which might help solve some of these problems.

    Exporting stats for this seems like a great idea.

    I wrote benchmark4j for java:

    http://code.google.com/p/benchmark4j/

    for similar purposes. I have a lot of tight mutex/semaphore use in our cluster which I need to debug.

    Obviously this won't work for MySQL.....

    ReplyDelete
  4. @Kevin -- Who is this developer? Of course, anything written today is likely to go into MySQL 6.X and that won't be ready for me before 3 to 5 years. For now I will backport and extend the fast mutexes from MySQL 5.1.

    ReplyDelete
  5. pthread_spin_*() is better solution for spinlock. You don't need to create wheel (with pthread_mutex_trylock) yourself.

    ReplyDelete
  6. @gslin - pthread_spin_* isn't better for this case. It provides no statistics on contention. I will use that to find hotspots and make MySQL scale on SMP. It is also only a spin lock. I can't replace the existing uses of pthread mutex with spinlocks. I want spinning followed by sleeping.

    ReplyDelete

 
Creative Commons License
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.