Databases 13 min read

Introduction to the InnoDB Lock Module and Its Performance Optimizations

This article provides a comprehensive overview of MySQL InnoDB's lock subsystem, describing its data structures, lock compatibility matrices, lock/unlock workflows, lock splitting, inheritance and migration, and presents several optimization techniques such as avoiding lock_sys mutex, asynchronous deadlock detection, and lock_sys mutex sharding to alleviate contention in MySQL 5.7 and later versions.

Tencent Database Technology
Tencent Database Technology
Tencent Database Technology
Introduction to the InnoDB Lock Module and Its Performance Optimizations

The purpose of this article is to give a concise introduction to the InnoDB lock module, helping readers gain a basic understanding of its architecture and recent performance improvements introduced in MySQL 8.0.

1.1 Lock‑related Data Structures

struct lock_sys_t{
  LockMutex               mutex;
  hash_table_t*           rec_hash;
  hash_table_t*           prdt_hash;
  hash_table_t*           prdt_page_hash;
  LockMutex               wait_mutex;
  srv_slot_t*             waiting_threads;
  srv_slot_t*             last_slot;
  int                     n_waiting;
};

struct lock_t {
  trx_t*                  trx;
  UT_LIST_NODE_T(lock_t)  trx_locks;
  dict_index_t*           index;
  lock_t*                 hash;

  union {
    lock_table_t          tab_lock;
    lock_rec_t            rec_lock;
  };

  uint32_t                type_mode;
};

struct lock_rec_t {
  ib_uint32_t             space;
  ib_uint32_t             page_no;
  ib_uint32_t             n_bits;
};

struct lock_table_t {
  dict_table_t*           table;
  UT_LIST_NODE_T(lock_t)  locks;
};

The type_mode field of lock_t distinguishes lock types (table lock, row lock, gap lock, etc.) and lock modes (shared, exclusive, auto‑increment, etc.).

1.2 Lock Compatibility and Strength Matrices

/* Used to determine if locks from different transactions are compatible */
static const byte lock_compatibility_matrix[5][5] = {
    /*   IS   IX    S    X   AI */
    /* IS */ {TRUE, TRUE, TRUE, FALSE, TRUE},
    /* IX */ {TRUE, TRUE, FALSE, FALSE, TRUE},
    /* S  */ {TRUE, FALSE, TRUE, FALSE, FALSE},
    /* X  */ {FALSE, FALSE, FALSE, FALSE, FALSE},
    /* AI */ {TRUE, TRUE, FALSE, FALSE, FALSE}
};

/* Determines if a stronger lock already exists */
static const byte lock_strength_matrix[5][5] = {
    /*   IS   IX    S    X   AI */
    /* IS */ {TRUE, FALSE, FALSE, FALSE, FALSE},
    /* IX */ {TRUE, TRUE, FALSE, FALSE, FALSE},
    /* S  */ {TRUE, FALSE, TRUE, FALSE, FALSE},
    /* X  */ {TRUE, TRUE, TRUE, TRUE, TRUE},
    /* AI */ {FALSE, FALSE, FALSE, FALSE, TRUE}
};

1.3 Lock/Unlock Process

Using an UPDATE statement as an example, the article explains how table locks ( lock_table ) and row locks ( lock_rec_lock ) are acquired, how compatibility checks are performed, and how the lock is placed into waiting state when conflicts arise.

When a transaction commits, all its row and table locks are released via lock_trx_release_locks .

1.4 Row‑Lock Splitting, Migration, and Inheritance

Row locks can be split when a GAP lock is encountered during an insert, inherited by the next record when a deleted record leaves a GAP, or migrated when B‑tree pages split, merge, or are deleted. The article provides concrete examples and diagrams illustrating each case.

2. Optimization I – Avoiding lock_sys Mutex

Replace the integer n_waiting with an atomic variable std::atomic n_waiting{0} .

Add trx->lock->wait_lock_type to cache the lock type, allowing reads without holding lock_sys mutex.

3. Optimization II – Asynchronous Deadlock Detection

Previously, deadlock detection was performed synchronously by user threads. The new design moves the detection to the lock_wait_timeout_thread , making it almost lock‑free. New fields such as trx_t::trx_lock_t::std::atomic blocking_trx and lock_wait_table_reservations are introduced to support this.

// Deadlock detection workflow
lock_wait_update_schedule_and_check_for_deadlocks
----- lock_wait_snapshot_waiting_threads   // collect waiting tasks
----- lock_wait_build_wait_for_graph       // build wait‑for graph
----- lock_wait_find_and_handle_deadlocks // detect cycles and roll back

4. Optimization III – lock_sys Mutex Sharding

Instead of a single global mutex, the lock structures are partitioned into shards, each protected by its own mutex. A global shared latch is taken first, followed by ordered acquisition of the relevant shard mutexes to avoid deadlocks.

Examples include:

Table‑lock acquisition: global shared latch → shard mutex for the table.

Row‑lock acquisition: global shared latch → shard mutex for the page.

Unlocking: global shared latch → shard mutex → trx->mutex (must follow lock ordering).

Various latch guards such as Global_exclusive_latch_guard , Global_exclusive_try_latch , and Shard_latches_guard are illustrated with diagrams.

5. Summary

The InnoDB lock manager is a complex component; understanding its data structures, lock compatibility rules, and the described optimizations can help developers mitigate lock‑sys contention in MySQL 5.7 and earlier, and benefit from the improvements available in MySQL 8.0.21 and later.

Performance OptimizationConcurrencyInnoDBMySQLLock ManagerDatabase Internals
Tencent Database Technology
Written by

Tencent Database Technology

Tencent's Database R&D team supports internal services such as WeChat Pay, WeChat Red Packets, Tencent Advertising, and Tencent Music, and provides external support on Tencent Cloud for TencentDB products like CynosDB, CDB, and TDSQL. This public account aims to promote and share professional database knowledge, growing together with database enthusiasts.

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.