【数据库死锁】线上问题之数据库死锁

原本平静的一天,惊现生产项目瘫痪问题,马上打开日志,发现后台日志提示了多个“com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction”

大概去了解一下这个异常:

解释:MYSQL事务回滚异常,超过锁等待超时;尝试重新启动事务
原因:执行update的SQL语句时,由于表被锁座,无法更新,导致时间超时;
此时在数据库对当前表进行update语句更新时,会提示:时间超时
当执行一个方法请求到数据库,抛出当前异常时,即使定位到执行的是哪一条SQL语句。确定是哪一张表;
MYSQL中手动执行该update语句时,提示:失败,等待锁超时;

解决方案:
1.查看数据库被锁表的进程,若表被锁住,可以查看到当前锁表的进程信息,若表被一直锁住不释放,则信息会一直存在;
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
2.找到当前锁表的进程ID,即:trx_mysql_thread_id,将其终止
kill 进程ID;
此时当前表会被释放,即可正常进行update操作。

以上只是解决锁表的临时解决方案,并不推荐,应该从造成锁表的原因去调整,避免后续执行方法时也会锁表;

实际问题

但是当时的实际情况是,确实有很多被锁的事务,对应了多张表,但是查看代码,并没有添加事务,重启服务也没有解决这个问题,想到肯能是数据库服务的问题,最后一看,数据库的服务器内存满了…

扩展

  1. 查看未提交的事务
    select * from information_schema.INNODB_TRX;

  2. 查看正在锁的事务
    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

  3. 查看正在等待锁的事务
    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

  4. 查看进程
    show processlist

  5. 查看是否锁表
    show open tables where in_use > 0

  6. 杀死被锁的进程
    trx_mysql_thread_id为被锁的事务id,可以使用kill 线程id 杀死对应的线程,达到释放锁效果

参考

生产异常 Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceed

mysql查询死锁sql

猜你喜欢

转载自blog.csdn.net/qq_48424581/article/details/129408747
今日推荐