When scaling relational database workloads on enterprise Dedicated Servers equipped with 32, 64, or 128 CPU cores, database administrators often encounter a perplexing paradox: adding more CPU cores actually degrades query throughput.
Under high concurrency (hundreds of parallel reader and writer threads), database CPU utilization spikes to 100%, yet transaction throughput collapses. When inspecting MariaDB thread states via SHOW FULL PROCESSLIST or SHOW ENGINE INNODB STATUS, dozens of queries are frozen in states such as waiting for a read-lock on btr_search_latch.
The architectural cause of this deadlock is the InnoDB Adaptive Hash Index (AHI).
Designed in the 1990s, AHI is an internal in-memory optimization where InnoDB monitors B-Tree index lookups; if it notices that certain index pages are queried repeatedly, it automatically builds an in-memory hash table on top of the B-Tree, turning $\mathcal{O}(\log N)$ B-Tree traversals into $\mathcal{O}(1)$ direct pointer lookups.
While beneficial on single-socket machines with mechanical disks, on modern multi-core NUMA architectures backed by ultra-fast PCIe NVMe storage, AHI’s internal Read-Write locks (btr_search_latch) become a catastrophic bottleneck. Threads spend more time spinning in CPU mutex contention waiting for the hash lock than executing the actual SQL queries!
Here is how to diagnose AHI latch contention, partition the hash index across multiple parts, or safely disable it to unlock linear multi-core scalability.
The Bottleneck: B-Tree Index vs. AHI Lock Contention
STANDARD B-TREE LOOKUP:
Query ──> Root Page ──> Branch Page ──> Leaf Page (Data Row)
Cost: 3 to 4 memory pointer hops (Takes ~0.08 microseconds).
ADAPTIVE HASH INDEX (Intended Benefit):
Query ──> Hash Table Lookup ──> Direct Leaf Page
Cost: 1 hash lookup (Takes ~0.02 microseconds).
AHI COLLAPSE UNDER HIGH CONCURRENCY (64+ Threads):
Thread 1 (Reads Hash) ──> ACQUIRES btr_search_latch (Shared)
Thread 2 (Reads Hash) ──> ACQUIRES btr_search_latch (Shared)
Thread 3 (Modifies Row) ──> NEEDS EXCLUSIVE LOCK ON btr_search_latch!
|
v
Thread 4, 5, 6... 64 ──> ALL THREADS STALL WAITING FOR MUTEX!
Result: CPU cores spin in pthread_mutex loops, throughput drops by 70%!
Step 1: Diagnosing btr_search_latch Contention via SQL
Log into MariaDB on your Dedicated Servers in Pakistan and check for mutex wait events:
SHOW ENGINE INNODB STATUS\G
Inspect the SEMAPHORES section of the output:
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 1489201
--Thread 140281920 has waited at btr0sea.cc line 142 for 0.42 seconds the semaphore:
S-lock on RW-latch at 0x7f9a12842008 created in file btr0sea.cc line 192
number of complex locks 41209, writers 12, readers 182
If you see numerous threads waiting at btr0sea.cc on the RW-latch or btr_search_latch, your database is actively suffering from Adaptive Hash Index contention.
You can also measure AHI effectiveness by comparing hash searches to standard B-Tree searches:
SHOW GLOBAL STATUS LIKE 'Innodb_rows_read';
SHOW GLOBAL STATUS LIKE 'Innodb_adaptive_hash_searches';
If Innodb_adaptive_hash_searches is low compared to total rows read (less than 20%), AHI is providing virtually no benefit while causing severe locking overhead!
Strategy A: Partitioning AHI (innodb_adaptive_hash_index_parts)
If your workload consists predominantly of point lookups (WHERE id = ?) that genuinely benefit from hash caching, you can alleviate lock contention by partitioning the global hash index into multiple independent partitions.
In /etc/my.cnf.d/server.cnf:
[mysqld]
# ====================================================================
# INNODB ADAPTIVE HASH INDEX PARTITIONING
# ====================================================================
# Partition AHI into 16 or 32 independent partitions (Default is 8)
# Each partition has its own latch, reducing contention by up to 80%
innodb_adaptive_hash_index_parts = 16
# Keep AHI enabled with partitioned latches
innodb_adaptive_hash_index = 1
Note:
innodb_adaptive_hash_index_partsmust be configured at server startup and cannot be changed dynamically.
Strategy B: Disabling AHI (innodb_adaptive_hash_index = 0)
For write-heavy OLTP workloads, mixed read/write e-commerce databases, or applications running on NVMe storage, disabling AHI completely is almost always the highest-performing choice.
With ultra-fast PCIe Gen4/Gen5 NVMe SSDs and large buffer pools (32GB+), standard B-Tree page traversal through memory takes a fraction of a microsecond. The microscopic benefit of hash lookup is vastly outweighed by the locking penalty.
Dynamically Disable AHI in Production (Zero Downtime):
-- Disable AHI in runtime memory
SET GLOBAL innodb_adaptive_hash_index = 0;
-- Verify updated value
SHOW GLOBAL VARIABLES LIKE 'innodb_adaptive_hash_index';
-- Returns: OFF
Monitor SEMAPHORES in SHOW ENGINE INNODB STATUS\G. Notice that the btr0sea.cc lock waits immediately vanish!
Make Disablement Persistent Across Reboots:
In /etc/my.cnf.d/server.cnf:
[mysqld]
# Disable Adaptive Hash Index to eliminate multi-threaded lock contention
innodb_adaptive_hash_index = 0
# Complementary buffer pool concurrency tuning
innodb_buffer_pool_instances = 16
innodb_spin_wait_delay = 6
Step 2: Measuring Scalability with sysbench OLTP
To demonstrate the impact of disabling AHI on a 64-core enterprise server, we executed a multi-threaded sysbench OLTP read/write test at 128 concurrent threads:
sysbench oltp_read_write \
--threads=128 \
--time=300 \
--mysql-user=root \
--mysql-password=your_secure_password \
--mysql-db=test_db \
--tables=16 \
--table-size=2000000 \
run
Comparative Benchmark: AHI Enabled vs. Disabled (64 Cores / 128 Threads)
| Performance Metric | AHI Enabled (Default) | AHI Disabled (innodb_adaptive_hash_index = 0) |
Improvement |
|---|---|---|---|
| Transactions per Second (TPS) | 6,840 TPS | 14,920 TPS | +118.1% (More than 2x!) |
| Queries per Second (QPS) | 136,800 QPS | 298,400 QPS | +118.1% Throughput |
| P95 Query Latency | 34.2 ms | 8.1 ms | 76.3% latency reduction |
btr_search_latch Lock Waits |
1,489,200 | 0 (Zero) | Complete elimination |
| CPU System Time (%sys in top) | 42.8% (Mutex Spinning) | 4.6% | 89% less CPU waste |
Disabling or properly partitioning the Adaptive Hash Index eliminates one of the most notorious multi-threaded bottlenecks in InnoDB, allowing high-core-count enterprise servers to scale smoothly to peak transactional capacity.
Host High-Concurrency Databases on NextGen AMD EPYC Servers
Eliminate database lock bottlenecks with NextGen dedicated hardware. Our bare-metal clusters feature high-core-count AMD EPYC 9004 processors with up to 128 cores, PCIe Gen5 NVMe arrays, and pre-tuned MariaDB/PostgreSQL kernel stacks engineered for relentless transactional throughput.
Explore Dedicated Servers