Mysql 异常:Lock wait timeout exceeded; try restarting transaction的解决办法

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS Agent(兼容OpenClaw),2核4GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
简介: Mysql 异常:Lock wait timeout exceeded; try restarting transaction的解决办法

问题现象

接口响应时间超长,耗时几十秒才返回错误提示,后台日志中出现Lock wait timeout exceeded; try restarting transaction的错误

<-- java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2794)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
    at com.trs.components.wcm.publish.element.PublishContentDocumentImpl.setPublishTimeAndURL(PublishContentDocumentImpl.java:851)
    at com.trs.components.common.publish.domain.publisher.PageGenerator.updateContentPublishTime(PageGenerator.java:236)
    at com.trs.components.common.publish.domain.publisher.PageGenerator.generateDetail(PageGenerator.java:216)
    at com.trs.components.common.publish.domain.taskdispatch.PageTaskWorker.executeTask(PageTaskWorker.java:278)
    at com.trs.components.common.publish.domain.taskdispatch.PageTaskWorker.run(PageTaskWorker.java:153)
    at com.trs.components.common.publish.domain.taskdispatch.ThreadPool$Worker.run(ThreadPool.java:56)

问题场景

1、在同一事务内先后对同一条数据进行插入和更新操作;


2、分布式服务操作同一条记录;


3、瞬时出现高并发现象;


问题原因

1、在高并发的情况下,Spring事物造成数据库死锁,后续操作超时抛出异常。


2、Mysql数据库采用InnoDB模式,默认参数:innodb_lock_wait_timeout设置锁等待的时间是50s,一旦数据库锁超过这个时间就会报错


解决方法

方法一:调整超时参数

mysql官方文档如下:


当锁等待超时后innodb引擎报此错误,等待时间过长的语句被回滚(不是整个事务)。如果想让SQL语句等待其他事务更长时间之后完成,你可以增加参数innodb_lock_wait_timeout配置的值。如果有太多长时间运行的有锁的事务,你可以减小这个innodb_lock_wait_timeout的值,在特别繁忙的系统,你可以减小并发。


InnoDB事务等待一个行级锁的时间最长时间(单位是秒),超过这个时间就会放弃。默认值是50秒。一个事务A试图访问一行数据,但是这行数据正在被另一个innodb事务B锁定,此时事务A就会等待事务B释放锁,等待超过innodb_lock_wait_timeout设置的值就会报错ERROR

1205 (HY000):


innodb_lock_wait_timeout是动态参数,默认值50秒,最小值是1秒,最大值是1073741824;

set innodb_lock_wait_timeout=1500等价于set session只影响当前sessio。set global innodb_lock_wait_timeout=1500作为全局的修改方式,只会影响修改之后打开的session,不能改变当前session。


mysql> set GLOBAL innodb_lock_wait_timeout=1500;

1

方法二:解决死锁

1、查看数据库当前的进程


show processlist会显示出当前正在执行的sql语句列表,找到消耗资源最大的那条语句对应的id.

mysql> show processlist; 
+---------+------+-------------------+--------------------+---------+-------+-------+------------------+
| Id      | User | Host              | db                 | Command | Time  | State | Info             |
+---------+------+-------------------+--------------------+---------+-------+-------+------------------+
| 3205081 | root | 172.19.2.8:50317  | ********           | Sleep   | 16485 |       | NULL             |
| 3210354 | root | 172.19.2.8:51066  | information_schema | Sleep   |  3569 |       | NULL             |
| 3210630 | root | 172.19.2.12:61845 | ********           | Query   |     0 | init  | show processlist |
+---------+------+-------------------+--------------------+---------+-------+-------+------------------+
10 rows in set (0.00 sec)

2、查看当前的锁和事务

在5.5中,information_schema 库中增加了三个关于锁的表(inndodb引擎):


innodb_trx ## 当前运行的所有事务

innodb_locks ## 当前出现的锁,查看正在锁的事务

innodb_lock_waits ## 锁等待的对应关系 ,查看等待锁的事务

当前运行的所有事务

mysql> SELECT * FROM information_schema.INNODB_TRX;

当前出现的锁

mysql> SELECT * FROM information_schema.INNODB_LOCKs;

锁等待的对应关系

mysql> SELECT * FROM information_schema.INNODB_LOCK_waits;

看里面是否有正在锁定的事务线程,看看ID是否在show processlist里面的sleep线程中,如果是,就证明这个sleep的线程事务一直没有commit或者rollback而是卡住了


3、查询产生锁的具体sql

根据具体的sql,就能看出是不是死锁了,并且可以确定具体是执行了什么业务,是否可以kill;

select 
    a.trx_id 事务id ,
    a.trx_mysql_thread_id 事务线程id,
    a.trx_query 事务sql 
from 
    INFORMATION_SCHEMA.INNODB_LOCKS b,
    INFORMATION_SCHEMA.innodb_trx a 
where 
    b.lock_trx_id=a.trx_id;

4、杀掉死锁的事务

查询出所有有锁的事务对应的线程ID(注意是线程id,不是事务id),通过information_schema.processlist表中的连接信息生成需要处理掉的MySQL连接的语句临时文件,然后执行临时文件中生成的指令。

mysql> select concat('KILL ',a.trx_mysql_thread_id ,';') from INFORMATION_SCHEMA.INNODB_LOCKS b,INFORMATION_SCHEMA.innodb_trx a where b.lock_trx_id=a.trx_id;
+------------------------+
| concat('KILL ',id,';') |
+------------------------+
| KILL 3205081;            |
| KILL 3210354;            |
| KILL 3210630;            |
+------------------------+
18 rows in set (0.00 sec)

如果太多的话可以导出到txt再批量执行

mysql> select concat('KILL ',a.trx_mysql_thread_id ,';') from INFORMATION_SCHEMA.INNODB_LOCKS b,INFORMATION_SCHEMA.innodb_trx a where b.lock_trx_id=a.trx_id into outfile '/tmp/kill.txt';

KILL命令允许自选的CONNECTION或QUERY修改符:KILL CONNECTION与不含修改符的KILL一样:它会终止与给定的thread_id有关的连接。KILL QUERY会终止连接当前正在执行的语句,但是会保持连接的原状。KILL命令的语法格式如下:

KILL [CONNECTION | QUERY] thread_id

运行kill命令

mysql> kill 3205081;
Query OK, 0 rows affected (0.00 sec)
mysql> kill 3210354;
Query OK, 0 rows affected (0.00 sec)

参考:


Lock wait timeout exceeded:http://blog.itpub.net/29654823/viewspace-2150471/


MySQL事务锁问题:https://cloud.tencent.com/developer/article/1356959


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
关系型数据库 MySQL Python
python安装MySQL-python:EnvironmentError解决办法
python安装MySQL-python:EnvironmentError解决办法
254 1
|
关系型数据库 MySQL Java
MySQL数据锁:Record Lock,Gap Lock 和 Next-Key Lock
本文基于 MySQL 8.0.30 版本及 InnoDB 引擎,深入解析三种行锁机制:记录锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-key Lock)。记录锁锁定索引记录,确保事务唯一修改;间隙锁锁定索引间的间隙,防止新记录插入;临键锁结合两者,锁定范围并记录自身,有效避免幻读现象。通过具体示例展示了不同锁的作用机制及其在并发控制中的应用。
1555 2
|
数据采集 中间件 关系型数据库
Mac系统通过brew安装mysql5.7后,启动报错的解决办法
Mac系统通过brew安装mysql5.7后,启动报错的解决办法
1221 2
|
关系型数据库 MySQL
MySQL 8.0 - Authentication plugin ‘caching_sha2_password‘ cannot be loaded 原因及解决办法
MySQL 8.0 - Authentication plugin ‘caching_sha2_password‘ cannot be loaded 原因及解决办法
741 1
|
SQL 关系型数据库 MySQL
问题1:Navicat连接不上mysql8的简单解决办法
问题1:Navicat连接不上mysql8的简单解决办法
2728 2
|
SQL 关系型数据库 MySQL
MySQL异常一之: You can‘t specify target table for update in FROM clause解决办法
这篇文章介绍了如何解决MySQL中“不能在FROM子句中指定更新的目标表”(You can't specify target table for update in FROM clause)的错误,提供了错误描述、需求说明、错误做法和正确的SQL写法。
3070 0
|
关系型数据库 MySQL Linux
【Linux】安装Mysql(附加service mysql启动失败 提示unit not found 解决办法)
【Linux】安装Mysql(附加service mysql启动失败 提示unit not found 解决办法)
1372 0
|
关系型数据库 MySQL 索引
mysql索引失效的原因以及解决办法
该内容列举了索引失效的五个原因,包括:条件表达式中的函数使用、不等于操作符、列类型不匹配、LIKE操作的模糊匹配和数据量过小。并提供了对应的解决办法:避免函数操作索引列、使用合适条件、保证类型匹配、选择合适索引、优化表结构和使用索引提示。
1272 1
|
分布式计算 关系型数据库 MySQL
MaxCompute产品使用合集之用flink mysql的数据同步到mc的Transaction Table2.0,时间会比mysql的时间多8小时,是什么导致的
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
262 0
|
SQL 关系型数据库 MySQL
【错误】mysql 出现 “1067 - Invalid default value for ‘UPDATE_TIME‘ “ 错误提示的解决办法
【错误】mysql 出现 “1067 - Invalid default value for ‘UPDATE_TIME‘ “ 错误提示的解决办法
1172 1

推荐镜像

更多