对于 5.7 版本,出现锁等待时,我们可以查看 information_schema 中的几张系统表来查询事务状态。
innodb_trx 当前运行的所有事务。
innodb_locks 当前出现的锁。
innodb_lock_waits 锁等待的对应关系
锁等待发生时 查看innodb_trx表可以看到所有事务
trx_state值为LOCK WAIT 则代表该事务处于等待状态
mysql> select * from information_schema.innodb_trx\G
# innodb_trx 字段值含义
trx_id:事务ID。
trx_state:事务状态,有以下几种状态:RUNNING、LOCK WAIT、ROLLING BACK 和 COMMITTING。
trx_started:事务开始时间。
trx_requested_lock_id:事务当前正在等待锁的标识,可以和 INNODB_LOCKS 表 JOIN 以得到更多详细信息。
trx_wait_started:事务开始等待的时间。
trx_weight:事务的权重。
trx_mysql_thread_id:事务线程 ID,可以和 PROCESSLIST 表 JOIN。
trx_query:事务正在执行的 SQL 语句。
trx_operation_state:事务当前操作状态。
trx_tables_in_use:当前事务执行的 SQL 中使用的表的个数。
trx_tables_locked:当前执行 SQL 的行锁数量。
trx_lock_structs:事务保留的锁数量。
trx_isolation_level:当前事务的隔离级别。
# sys.innodb_lock_waits 视图也可看到事务等待状况,且给出了杀链接的SQL
mysql> select * from sys.innodb_lock_waits\G
sys.innodb_lock_waits 视图整合了事务等待状况,同时给出杀掉堵塞源端的 kill 语句。不过是否要杀掉链接还是需要综合考虑的。
发生死锁后会选择一个事务进行回滚,想查明死锁原因,可以执行 show engine innodb status
来查看死锁日志,根据死锁日志,结合业务逻辑来进一步定位死锁原因。
在实际应用中,我们要尽量避免死锁现象的发生,可以从以下几个方面入手:
事务尽可能小,不要讲复杂逻辑放进一个事务里。
涉及多行记录时,约定不同事务以相同顺序访问。
业务中要及时提交或者回滚事务,可减少死锁产生的概率。
表要有合适的索引。
可尝试将隔离级别改为 RC 。