Mysql造成锁的情况有很多,以下列了4种情况:

  • 执行DML操作没有commit,再执行删除操作就会锁表;
  • 在同一事务内先后对同一条数据进行插入和更新操作;
  • 表索引设计不当,导致数据库出现死锁;
  • 长事物,阻塞DDL,继而阻塞所有同表的后续操作。

出现事务锁表等待,解决的办法有四种:
(1)找出出现锁表的事务进程杀死;
(2)进行sql语句分析,优化慢sql;
(3)把事务等待时间延长;
(4)修改表的存储引擎为innodb。

一、找出出现锁表的事务进程,然后将其杀死

# 查看数据库当前正在执行的进程,只是显示部分
show  processlist;
# 显示所有的正在进行的进程
show full processlist; 

# 当前运行的所有事务
SELECT * FROM information_schema.INNODB_TRX;

# 当前出现的锁
SELECT * FROM information_schema.INNODB_LOCKs;

# 锁等待的对应关系
SELECT * FROM information_schema.INNODB_LOCK_waits;

#解释:看事务表INNODB_TRX,里面是否有正在锁定的事务线程,
看看ID是否在show processlist里面的sleep线程中,
如果是,就证明这个sleep的线程事务一直没有commit或者rollback而是卡住了。
trx_mysql_thread_id  即为事务线程id。
我们需要使用kill id 命令将其杀死。

二、进行sql语句分析,优化慢sql

找到出现问题源代码位置,然后分析一下是否存在慢sql,然后对其进行优化。最好还是检查一下事务的使用是否使用正确,如果事务使用不正确也会导致这样的问题。

三、延长事务超时等待时间

# 将事务超时等待的时间设置长一点 执行以下两条sql
SET GLOBAL innodb_lock_wait_timeout = 5000; 
SET innodb_lock_wait_timeout = 5000; 

四、查看和修改表的存储引擎

# 查看当前数据库所支持的引擎 (mysql5.5.5以前默认是MyISAM,mysql5.5.5以后默认是InnoDB)
show ENGINES;

# 查看当前数据库的版本
SELECT VERSION();

# 查看表使用的存储引擎
show table status from db_name where name='table_name';

# 修改表的存储引擎
alter table table_name engine=innodb;

参考链接:
(1) https://www.jianshu.com/p/0b4aaa93e7f6 (事务锁表分析以及解决方案)
(2) https://stackoverflow.com/questions/2766785/fixing-lock-wait-timeout-exceeded-try-restarting-transaction-for-a-stuck-my/10315184 (Stack Overflow 事务锁表解决方案)
(3)https://zhuanlan.zhihu.com/p/30743094 (show processlist 详解)
(4)https://dev.mysql.com/doc/refman/5.6/en/general-thread-states.html (mysql官网 States 的状态解析描述)
(5) https://ningyu1.github.io/site/post/75-mysql-lock-wait-timeout-exceeded/ (事务问题分析以及解决方案)