Databases 4 min read

Diagnosing and Resolving High CPU Usage in MySQL 5.6 Caused by Mutex Contention and Excessive malloc/free

The article analyzes a MySQL 5.6 high‑CPU issue triggered by a frequently executed query with many UID values, identifies mutex contention and excessive memory allocation in InnoDB as root causes, and presents a solution of switching the memory allocator to tcmalloc with configuration changes.

Aikesheng Open Source Community
Aikesheng Open Source Community
Aikesheng Open Source Community
Diagnosing and Resolving High CPU Usage in MySQL 5.6 Caused by Mutex Contention and Excessive malloc/free

Background

The MySQL instance (5.6.29, master‑slave) on CentOS 6.8 experienced frequent CPU spikes when a specific query selecting many uid values (hundreds per execution) ran concurrently. The query uses the index idx_msg_uid_time and runs in seconds when executed alone, but exceeds an hour under concurrency, causing high CPU usage.

Diagnosis

Using mpstat -P ALL 1 revealed most CPU consumption in the sys (system call) portion. perf top showed the hotspot in _spin_lock . A detailed perf report indicated that the CPU was mainly spent on mutex contention.

Further tracing with pt‑pmp highlighted heavy activity in mem_heap_alloc and mem_heap_free . The InnoDB call stack for reading a row was examined, showing the path:

row_search_for_mysql → row_vers_build_for_consistent_read → mem_heap_create_block_func → mem_area_alloc → malloc → _L_unlock_10151 → __lll_unlock_wait_private

The function row_vers_build_for_consistent_read loops until a suitable snapshot is found, invoking mem_heap_alloc/free on each iteration. Because the table test_history is frequently updated, its undo history becomes long, making snapshot searches expensive and causing many malloc/free calls. The default Linux memory allocator (ptmalloc) suffers from lock contention under such heavy allocation patterns, eventually triggering OS‑level spinlocks.

Solution

Replace the default memory allocator with tcmalloc , which handles high‑concurrency allocations more efficiently. Add the following line to my.cnf under the [mysqld_safe] section and restart MySQL:

[mysqld_safe]
malloc-lib=tcmalloc

After applying the change, the instance ran for over 72 hours without recurring CPU spikes, and the CPU usage before and after the modification showed a significant reduction.

PerformanceInnoDBMySQLMutexCPUMemory AllocationTCMalloc
Aikesheng Open Source Community
Written by

Aikesheng Open Source Community

The Aikesheng Open Source Community provides stable, enterprise‑grade MySQL open‑source tools and services, releases a premium open‑source component each year (1024), and continuously operates and maintains them.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.