MySQL提供了查看当前数据库锁请求的三种方法:

1. show  full  processlist命令
  观察state和info列
2. show engine  innodb status\G 命令
  查看 TRANSACTIONS 部分和 LATEST DETECTED DEADLOCK 两个部分
3. information_shcema下的三张表(通过这三张表可以更新监控当前事物并且分析存在的锁问题)
 —— innodb_trx ( 打印innodb内核中的当前活跃(ACTIVE)事务) 
 —— innodb_locks  ( 打印当前状态产生的innodb锁 仅在有锁等待时打印)
 —— innodb_lock_waits (打印当前状态产生的innodb锁等待 仅在有锁等待时打印) 

 1) innodb_trx表结构说明 (摘取最能说明问题的8个字段)

字段名

说明

trx_id

innodb存储引擎内部唯一的事物ID

trx_state

当前事物状态(running和lock wait两种状态)

trx_started  

事物的开始时间

trx_requested_lock_id

等待事物的锁ID,如trx_state的状态为Lock wait,那么该值带表当前事物等待之前事物占用资源的ID,若trx_state不是Lock wait 则该值为NULL

trx_wait_started

事物等待的开始时间

trx_weight

事物的权重,在innodb存储引擎中,当发生死锁需要回滚的时,innodb存储引擎会选择该值最小的进行回滚

trx_mysql_thread_id

mysql中的线程id, 即show  processlist显示的结果

trx_query 

事物运行的SQL语句

 2)innodb_locks表结构说明

字段名

说明

lock_id 

锁的ID

lock_trx_id

事物的ID

lock_mode

锁的模式(S锁与X锁两种模式)

lock_type

锁的类型 表锁还是行锁(RECORD)

lock_table

要加锁的表

lock_index

锁住的索引

lock_space

锁住对象的space id

lock_page 

事物锁定页的数量,若是表锁则该值为NULL

lock_rec

事物锁定行的数量,若是表锁则该值为NULL

lock_data

事物锁定记录主键值,若是表锁则该值为NULL(此选项不可信)

 3)innodb_lock_waits表结构说明

字段名

说明

requesting_trx_id

申请锁资源的事物ID

requested_lock_id

申请的锁的ID

blocking_trx_id

阻塞其他事物的事物ID

blocking_lock_id

阻塞其他锁的锁ID

可以根据这三张表进行联合查询,得到更直观更清晰的结果,可以参考如下SQL(可根据自己的分析习惯适进行调整)

select
 r.trx_isolation_level,
 r.trx_id waiting_trx_id,
 r.trx_mysql_thread_id  waiting_trx_thread,
 r.trx_state  waiting_trx_state,
 lr.lock_mode waiting_trx_lock_mode,
 lr.lock_type  waiting_trx_lock_type,
 lr.lock_table  waiting_trx_lock_table,
 lr.lock_index  waiting_trx_lock_index,
 r.trx_query  waiting_trx_query,
 b.trx_id  blocking_trx_id,
 b.trx_mysql_thread_id  blocking_trx_thread,
 b.trx_state  blocking_trx_state,
 lb.lock_mode blocking_trx_lock_mode,
 lb.lock_type  blocking_trx_lock_type,
 lb.lock_table  blocking_trx_lock_table,
 lb.lock_index  blocking_trx_lock_index,
 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 
 inner  join   information_schema.innodb_locks  lb
 on  lb.lock_trx_id=w.blocking_trx_id
 inner  join   information_schema.innodb_locks  lr
 on  lr.lock_trx_id=w.requesting_trx_id\G;
 *************************** 1. row ***************************
     trx_isolation_level: REPEATABLE READ
          waiting_trx_id: 2900247
      waiting_trx_thread: 1070
       waiting_trx_state: LOCK WAIT
   waiting_trx_lock_mode: S
   waiting_trx_lock_type: RECORD
  waiting_trx_lock_table: `jiang_test`.`test`
  waiting_trx_lock_index: PRIMARY
       waiting_trx_query: select * from test where id=3 lock in share mode
         blocking_trx_id: 2900241
     blocking_trx_thread: 1137
      blocking_trx_state: RUNNING
  blocking_trx_lock_mode: X
  blocking_trx_lock_type: RECORD
 blocking_trx_lock_table: `jiang_test`.`test`
 blocking_trx_lock_index: PRIMARY
          blocking_query: NULL
 1 row in set (0.01 sec)

 

4、可以通过检查InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况:

mysql> show status like 'innodb_row_lock%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| InnoDB_row_lock_current_waits | 0     |
| InnoDB_row_lock_time          | 0     |
| InnoDB_row_lock_time_avg      | 0     |
| InnoDB_row_lock_time_max      | 0     |
| InnoDB_row_lock_waits         | 0     |
+-------------------------------+-------+

5 rows in set (0.01 sec)

如果发现锁争用比较严重,如InnoDB_row_lock_waits和InnoDB_row_lock_time_avg的值比较高,还可以通过设置InnoDB Monitors来进一步观察发生锁冲突的表、数据行等,并分析锁争用的原因。

具体方法如下:

mysql> CREATE TABLE innodb_monitor(a INT) ENGINE=INNODB;
Query OK, 0 rows affected (0.14 sec)

然后就可以用下面的语句来进行查看:

mysql> Show innodb status\G;
*************************** 1. row ***************************
  Type: InnoDB
  Name:
Status:
…
…
------------
TRANSACTIONS
------------
Trx id counter 0 117472192
Purge done for trx's n:o < 0 117472190 undo n:o < 0 0
History list length 17
Total number of lock structs in row lock hash table 0
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 117472185, not started, process no 11052, OS thread id 1158191456
MySQL thread id 200610, query id 291197 localhost root
---TRANSACTION 0 117472183, not started, process no 11052, OS thread id 1158723936
MySQL thread id 199285, query id 291199 localhost root
Show innodb status
…

监视器可以通过发出下列语句来停止查看:

mysql> DROP TABLE innodb_monitor;
Query OK, 0 rows affected (0.05 sec)

设置监视器后,在SHOW INNODB STATUS的显示内容中,会有详细的当前锁等待的信息,包括表名、锁类型、锁定记录的情况等,便于进行进一步的分析和问题的确定。打开监视器以后,默认情况下每15秒会向日志中记录监控的内容,如果长时间打开会导致.err文件变得非常的巨大,所以用户在确认问题原因之后,要记得删除监控表以关闭监视器,或者通过使用“--console”选项来启动服务器以关闭写日志文件。