How to Check and Monitor Active MySQL Locks: A Complete Guide


2 views

MySQL implements several locking strategies to maintain data integrity during concurrent operations. The main types include:

  • Table-level locks (MyISAM)
  • Row-level locks (InnoDB)
  • Metadata locks
  • Gap locks
  • Next-key locks

The primary way to view locks in MySQL is through the INFORMATION_SCHEMA database or SHOW ENGINE commands.

Using INFORMATION_SCHEMA


SELECT * FROM information_schema.INNODB_TRX;
SELECT * FROM information_schema.INNODB_LOCKS;
SELECT * FROM information_schema.INNODB_LOCK_WAITS;

Using SHOW ENGINE INNODB STATUS


SHOW ENGINE INNODB STATUS\G

Here's a comprehensive query to identify blocking transactions:


SELECT 
  r.trx_id waiting_trx_id,
  r.trx_mysql_thread_id waiting_thread,
  r.trx_query waiting_query,
  b.trx_id blocking_trx_id,
  b.trx_mysql_thread_id blocking_thread,
  b.trx_query blocking_query
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;

For MySQL 5.7+ you can check metadata locks with:


SELECT * FROM performance_schema.metadata_locks;

Create a stored procedure for regular lock checks:


DELIMITER //
CREATE PROCEDURE monitor_locks()
BEGIN
  SELECT NOW() AS check_time, COUNT(*) AS lock_count 
  FROM information_schema.INNODB_LOCKS;
  
  SELECT * FROM information_schema.INNODB_LOCK_WAITS;
END //
DELIMITER ;

MySQL 8.0+ provides enhanced lock monitoring:


SELECT * FROM performance_schema.events_waits_current 
WHERE EVENT_NAME LIKE '%lock%';

Case 1: Long-running transactions causing locks


-- Identify long transactions
SELECT * FROM information_schema.INNODB_TRX 
WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60;

Case 2: Uncommitted transactions holding locks


-- Check for idle transactions
SELECT * FROM information_schema.INNODB_TRX 
WHERE trx_state = 'RUNNING' AND trx_operation_state IS NULL;

To view all active locks in MySQL, you can query the performance_schema and information_schema tables. The most comprehensive approach combines several system tables:

SELECT 
    r.trx_id waiting_trx_id,
    r.trx_mysql_thread_id waiting_thread,
    r.trx_query waiting_query,
    b.trx_id blocking_trx_id,
    b.trx_mysql_thread_id blocking_thread,
    b.trx_query blocking_query
FROM 
    performance_schema.data_lock_waits w
    INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_engine_transaction_id
    INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_engine_transaction_id;

For different MySQL versions, you might need these alternative queries:

Using SHOW ENGINE INNODB STATUS

SHOW ENGINE INNODB STATUS\G

Look for the "TRANSACTIONS" section which shows lock information including wait-for graphs.

For MySQL 5.7+

SELECT * FROM sys.innodb_lock_waits;

Enable these performance schema instruments for detailed lock tracking:

UPDATE performance_schema.setup_instruments 
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE 'wait/lock/%';

UPDATE performance_schema.setup_consumers 
SET ENABLED = 'YES'
WHERE NAME LIKE 'events_waits%';

To distinguish between different lock modes:

SELECT 
    lock_type,
    lock_mode,
    lock_status,
    lock_data
FROM 
    performance_schema.data_locks
WHERE 
    THREAD_ID = sys.ps_thread_id(connection_id());

Create a stored procedure for regular lock checks:

DELIMITER //
CREATE PROCEDURE monitor_locks(IN interval_seconds INT, IN max_checks INT)
BEGIN
    DECLARE counter INT DEFAULT 0;
    WHILE counter < max_checks DO
        SELECT NOW() AS check_time, * FROM sys.innodb_lock_waits;
        SET counter = counter + 1;
        DO SLEEP(interval_seconds);
    END WHILE;
END //
DELIMITER ;

Key columns to analyze:

  • blocking_trx_id: The transaction holding the lock
  • waiting_trx_id: The transaction waiting for the lock
  • lock_mode: X (exclusive), S (shared), etc.
  • lock_type: RECORD (row lock) or TABLE (table lock)

Enable deadlock logging in my.cnf:

[mysqld]
innodb_print_all_deadlocks = ON

Then check MySQL error log for detailed deadlock reports.