show engine innodb status 의 TRANSACTIONS 부분에서 ACTIVE TRANSACTION 으로 Lock 을 잡고 있는 쿼리를 찾아야될때가 있다. 

회사에서 가장 많이 사용중인 5.7 버전부터 테스트해 본다. 

MySQL 5.7 테스트

mysql> create table tb_test (
    -> col1 int not null primary key,
    -> col2 varchar(10) not null
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> insert into tb_test values (1, 'aaa');
Query OK, 1 row affected (0.03 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update tb_test set col2 = 'bbb' where col1 = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

ACTIVE TRANSACTION은 확인되지만 어떤 쿼리인지는 확인이 안된다. 

mysql> show engine innodb status;
...
------------
TRANSACTIONS
------------
Trx id counter 1289
Purge done for trx's n:o < 0 undo n:o < 0 state: running but idle
History list length 0
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 421405712030432, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 1288, ACTIVE 80 sec
2 lock struct(s), heap size 1136, 1 row lock(s), undo log entries 1
MySQL thread id 8, OS thread handle 139930706618112, query id 65 localhost root

mysql> select * from information_schema.innodb_locks;
Empty set, 1 warning (0.00 sec)

mysql> select * from information_schema.innodb_lock_waits;
Empty set, 1 warning (0.00 sec)

mysql> SELECT 
    ->   straight_join
    ->   w.trx_mysql_thread_id waiting_thread,w.trx_id waiting_trx_id,w.trx_query waiting_query,b.trx_mysql_thread_id blocking_thread,
    ->   b.trx_id blocking_trx_id,b.trx_query blocking_query,bl.lock_id blocking_lock_id,bl.lock_mode blocking_lock_mode,
    ->   bl.lock_type blocking_lock_type,bl.lock_table blocking_lock_table,bl.lock_index blocking_lock_index,wl.lock_id waiting_lock_id,
    ->   wl.lock_mode waiting_lock_mode,wl.lock_type waiting_lock_type,wl.lock_table waiting_lock_table,wl.lock_index waiting_lock_index
    -> FROM information_schema.INNODB_LOCK_WAITS ilw
    -> INNER JOIN information_schema.INNODB_TRX b ON b.trx_id = ilw.blocking_trx_id
    -> INNER JOIN information_schema.INNODB_TRX w ON w.trx_id = ilw.requesting_trx_id
    -> INNER JOIN information_schema.INNODB_LOCKS bl ON bl.lock_id = ilw.blocking_lock_id
    -> INNER JOIN information_schema.INNODB_LOCKS wl ON wl.lock_id = ilw.requested_lock_id;
Empty set, 3 warnings (0.00 sec)

다른 세션에서 Lock Wait 상황을 발생시키면?

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update tb_test set col2 = 'bbb' where col1 = 1;

Lock Wait 가 발생하면 확인이 된다.

mysql> select * from information_schema.INNODB_LOCK_WAITS;
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 1289              | 1289:23:3:2       | 1288            | 1288:23:3:2      |
+-------------------+-------------------+-----------------+------------------+
1 row in set, 1 warning (0.00 sec)

mysql> select * from information_schema.INNODB_TRX;
+--------+-----------+---------------------+-----------------------+---------------------+------------+---------------------+------------------------------------------------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+------------------+----------------------------+
| trx_id | trx_state | trx_started         | trx_requested_lock_id | trx_wait_started    | trx_weight | trx_mysql_thread_id | trx_query                                      | trx_operation_state | trx_tables_in_use | trx_tables_locked | trx_lock_structs | trx_lock_memory_bytes | trx_rows_locked | trx_rows_modified | trx_concurrency_tickets | trx_isolation_level | trx_unique_checks | trx_foreign_key_checks | trx_last_foreign_key_error | trx_adaptive_hash_latched | trx_adaptive_hash_timeout | trx_is_read_only | trx_autocommit_non_locking |
+--------+-----------+---------------------+-----------------------+---------------------+------------+---------------------+------------------------------------------------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+------------------+----------------------------+
| 1289   | LOCK WAIT | 2022-10-01 15:39:28 | 1289:23:3:2           | 2022-10-01 15:40:35 |          2 |                  10 | update tb_test set col2 = 'bbb' where col1 = 1 | starting index read |                 1 |                 1 |                2 |                  1136 |               2 |                 0 |                       0 | REPEATABLE READ     |                 1 |                      1 | NULL                       |                         0 |                         0 |                0 |                          0 |
| 1288   | RUNNING   | 2022-10-01 15:31:45 | NULL                  | NULL                |          3 |                   8 | NULL                                           | NULL                |                 0 |                 1 |                2 |                  1136 |               1 |                 1 |                       0 | REPEATABLE READ     |                 1 |                      1 | NULL                       |                         0 |                         0 |                0 |                          0 |
+--------+-----------+---------------------+-----------------------+---------------------+------------+---------------------+------------------------------------------------+---------------------+-------------------+-------------------+------------------+-----------------------+-----------------+-------------------+-------------------------+---------------------+-------------------+------------------------+----------------------------+---------------------------+---------------------------+------------------+----------------------------+
2 rows in set (0.00 sec)

mysql> SELECT 
    ->   straight_join
    ->   w.trx_mysql_thread_id waiting_thread,w.trx_id waiting_trx_id,w.trx_query waiting_query,b.trx_mysql_thread_id blocking_thread,
    ->   b.trx_id blocking_trx_id,b.trx_query blocking_query,bl.lock_id blocking_lock_id,bl.lock_mode blocking_lock_mode,
    ->   bl.lock_type blocking_lock_type,bl.lock_table blocking_lock_table,bl.lock_index blocking_lock_index,wl.lock_id waiting_lock_id,
    ->   wl.lock_mode waiting_lock_mode,wl.lock_type waiting_lock_type,wl.lock_table waiting_lock_table,wl.lock_index waiting_lock_index
    -> FROM information_schema.INNODB_LOCK_WAITS ilw
    -> INNER JOIN information_schema.INNODB_TRX b ON b.trx_id = ilw.blocking_trx_id
    -> INNER JOIN information_schema.INNODB_TRX w ON w.trx_id = ilw.requesting_trx_id
    -> INNER JOIN information_schema.INNODB_LOCKS bl ON bl.lock_id = ilw.blocking_lock_id
    -> INNER JOIN information_schema.INNODB_LOCKS wl ON wl.lock_id = ilw.requested_lock_id;
+----------------+----------------+------------------------------------------------+-----------------+-----------------+----------------+------------------+--------------------+--------------------+---------------------+---------------------+-----------------+-------------------+-------------------+--------------------+--------------------+
| waiting_thread | waiting_trx_id | waiting_query                                  | blocking_thread | blocking_trx_id | blocking_query | blocking_lock_id | blocking_lock_mode | blocking_lock_type | blocking_lock_table | blocking_lock_index | waiting_lock_id | waiting_lock_mode | waiting_lock_type | waiting_lock_table | waiting_lock_index |
+----------------+----------------+------------------------------------------------+-----------------+-----------------+----------------+------------------+--------------------+--------------------+---------------------+---------------------+-----------------+-------------------+-------------------+--------------------+--------------------+
|             10 | 1289           | update tb_test set col2 = 'bbb' where col1 = 1 |               8 | 1288            | NULL           | 1288:23:3:2      | X                  | RECORD             | `test`.`tb_test`    | PRIMARY             | 1289:23:3:2     | X                 | RECORD            | `test`.`tb_test`   | PRIMARY            |
+----------------+----------------+------------------------------------------------+-----------------+-----------------+----------------+------------------+--------------------+--------------------+---------------------+---------------------+-----------------+-------------------+-------------------+--------------------+--------------------+
1 row in set, 3 warnings (0.00 sec)

5.7 에서는 Lock Wait 이 발생해야 Lock 정보 확인이 가능하다.

즉 Lock 경합이 없으면 어떤 쿼리가 Lock 잡고 있는지 확인이 안된다. 

아하하하 미친다. (왜 미치냐면 이게 문제가 되고 있어서.)

 

MySQL 8.0 테스트

mysql> create table tb_test (
    -> col1 int not null primary key,
    -> col2 varchar(10) not null
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> insert into tb_test values (1, 'aaa');
Query OK, 1 row affected (0.03 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update tb_test set col2 = 'bbb' where col1 = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

ACTIVE TRANSACTION, Lock 쿼리 확인 

mysql> show engine innodb status;
------------
TRANSACTIONS
------------
Trx id counter 7713
Purge done for trx's n:o < 7710 undo n:o < 0 state: running but idle
History list length 0
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 422006973530112, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 422006973528496, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 422006973527688, not started
0 lock struct(s), heap size 1128, 0 row lock(s)
---TRANSACTION 7712, ACTIVE 26 sec
2 lock struct(s), heap size 1128, 1 row lock(s), undo log entries 1
MySQL thread id 9, OS thread handle 140531536729856, query id 26 localhost root

mysql> select * from performance_schema.data_locks;
+--------+----------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-----------+
| ENGINE | ENGINE_LOCK_ID                         | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE     | LOCK_STATUS | LOCK_DATA |
+--------+----------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-----------+
| INNODB | 140531996818648:1083:140532001090368   |                  7712 |        48 |       32 | test          | tb_test     | NULL           | NULL              | NULL       |       140532001090368 | TABLE     | IX            | GRANTED     | NULL      |
| INNODB | 140531996818648:22:4:2:140532001087456 |                  7712 |        48 |       32 | test          | tb_test     | NULL           | NULL              | PRIMARY    |       140532001087456 | RECORD    | X,REC_NOT_GAP | GRANTED     | 1         |
+--------+----------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-----------+
2 rows in set (0.01 sec)

mysql> SELECT straight_join
    ->   dl.thread_id,est.sql_text,dl.object_schema,dl.object_name,dl.index_name,
    ->   dl.lock_type,dl.lock_mode,dl.lock_status,dl.lock_data
    -> FROM performance_schema.data_locks dl 
    -> INNER JOIN performance_schema.events_statements_current est ON dl.thread_id = est.thread_id
    -> ORDER BY est.timer_start,dl.object_instance_begin;
+-----------+------------------------------------------------+---------------+-------------+------------+-----------+---------------+-------------+-----------+
| thread_id | sql_text                                       | object_schema | object_name | index_name | lock_type | lock_mode     | lock_status | lock_data |
+-----------+------------------------------------------------+---------------+-------------+------------+-----------+---------------+-------------+-----------+
|        48 | update tb_test set col2 = 'bbb' where col1 = 1 | test          | tb_test     | PRIMARY    | RECORD    | X,REC_NOT_GAP | GRANTED     | 1         |
|        48 | update tb_test set col2 = 'bbb' where col1 = 1 | test          | tb_test     | NULL       | TABLE     | IX            | GRANTED     | NULL      |
+-----------+------------------------------------------------+---------------+-------------+------------+-----------+---------------+-------------+-----------+
2 rows in set (0.00 sec)

8.0 에서는 Lock Wait 이 발생하지 않아도 Lock 을 잡고 있는 쿼리 확인이 잘된다. 

 

'MySQL' 카테고리의 다른 글

xtrabackup 옵션  (1) 2023.11.30
CPU 사용률 높은 Thread (세션) 확인  (0) 2022.10.05
auto_increment 값 모니터링  (0) 2022.09.28
Query Cache  (0) 2022.09.24
Index Hint  (0) 2022.09.22

+ Recent posts