Lock wait timeout exceeded; try restarting transaction-Mysql报错

Posted 遇见美好,遇见妳

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lock wait timeout exceeded; try restarting transaction-Mysql报错相关的知识,希望对你有一定的参考价值。

一、问题由来

现在在做一个小程序的后台,使用Java写的,数据库使用的mysql,之前一直调试的时候都好好的,今天在调试的时候突然就报一个错:

### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: update 表名 set update_time = now(), pet_state = ?, first_interaction_time = now(), stock_count = stock_count + 1, update_name = ? where pet_id = ?
### Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

因为做的这个业务操作比较复杂,这只是其中一个操作,里面又是新增,又是查询,又是修改之类的,总之一大堆操作。

写好代码后也是自己第一次进行测试,怎么突然就报这个错误呢?大致意思就是:超过锁定等待超时;尝试重新启动事务。

二、问题分析

拿到这个BUG,立马使用搜索引擎进行搜索,网友给出了一些回答,有的说是在同一个事务之中,对同一个数据进行了新增和修改操作。

有的说是某一个事务执行的时间太长,直接kill掉即可。总之有一点,就是这个操作是在事务之中进行的,在执行过程中由于不知道的原因

导致执行过长最终出现问题。自己调试过两三次都是同样的结果,我索性就打个断点进行调试,看看问题出在哪里,很幸运的是,很快找到

问题的原因。自己在一段代码中由于不小心写了一个无限循环,并且这个无限循环是在一个事务当中进行执行的,最终出现问题。
三、解决方案

 

 

 找到问题的原因后,立马修改代码,从新进行测试,问题解决。虽然问题是自己写代码时不小心导致的,但是也让自己学习

到了一个新的知识点,Mysql的事务执行是有一个设定的时长的,如果超过这个时长就可能出现标题中的问题。吃一堑,长一智,

不断学习,不断进步!

038 lock wait timeout exceeded;try restarting transaction

 场景:有两个会话,其中会话1在事务操作,会话2在等待这个事务操作完成,然后会有这个报错产生。

  通过查询资料,在这里整理一下。

一:总结timeout参数的作用

1.操作

  技术分享图片

 

2.具体解释

  1)connect_timeout
  The number of seconds that the mysqld server waits for a connect packet before responding with Bad handshake
  Increasing the connect_timeout value might help if clients frequently encounter errors of the form Lost connection to MySQL server at ‘XXX‘, system error: errno.
  翻译:mysql服务等待连接包的时间(单位秒),超过这个时间就会抛出‘坏握手‘的响应。如果客户端经常遇到形如:Lost connection to MySQL server at ‘XXX‘, system error: errno的错误,那么增加connect_timeout的值可以有所帮助;
  说下mysql处理客户端请求的过程:
  mysql的基本原理应该是有个监听线程循环接收请求,当有请求来时,创建线程(或者从线程池中取)来处理这个请求。由于mysql连接采用TCP协议,那么之前势必是需要进行TCP三次握手的。TCP三次握手成功之后,客户端会进入阻塞,等待服务端的消息。服务端这个时候会创建一个线程(或者从线程池中取一个线程)来处理请求,主要验证部分包括host和用户名密码验证。host验证我们比较熟悉,因为在用grant命令授权用户的时候是有指定host的。用户名密码认证则是服务端先生成一个随机数发送给客户端,客户端用该随机数和密码进行多次加密后发送给服务端验证。如果通过,整个连接握手过程完成
  2)delayed_insert_timeout
  insert delay操作延迟的秒数,这里不是insert操作,而是insert delayed,延迟插入。 该参数再以后即将被遗弃,可不关注!
  3)innodb_flush_log_at_timeout
  这个是5.6中才出现的,是InnoDB特有的参数,日志刷新时间间隔,默认是1秒
  4)innodb_lock_wait_timeout
  InnoDB事务等待一个行级锁的时间最长时间(单位是秒),超过这个时间就会放弃。默认值是50秒
  5)innodb_rollback_on_timeout
  在innodb中,如果这个参数为 on,那么当事务中的最后一个语句超时的时候,就会回滚这个事务,默认是off,关闭状态。
  6)interactive_timeout (交互式) 和wait_timeout(非交互式)
  交互式和非交互式链接的超时设置,防止客户端长时间链接数据库,什么都不做处于sleep状态,强制关闭长时间的sleep链接。
  还是先看官方文档,从文档上来看wait_timeout和interactive_timeout都是指不活跃的连接超时时间,连接线程启动的时候wait_timeout会根据是交互模式还是非交互模式被设置为这两个值中的一个。如果我们运行mysql -uroot -p命令登陆到mysql,wait_timeout就会被设置为interactive_timeout的值。如果我们在wait_timeout时间内没有进行任何操作,那么再次操作的时候就会提示超时,这需要mysql client重新连接。默认情况先两值的都为28800(8h),一般情况下将两值都设置为1000s就行了。
  7)lock_wait_timeout
  获取元数据锁的超时时间。这个适合用于除了系统表之外的所有表(mysql库之外)。
  区别于innodb_lock_wait_timeout是针对dml操作的行级锁的等待时间 ,而lock_wait_timeout是数据结构ddl操作的锁的等待时间
  8)
  net_read_timeout
  net_write_timeout
  这两个表示数据库发送网络包和接受网络包的超时时间。
  9)rpl_stop_slave_timeout(默认值即可,无需修改)
  在 5.6.13开始以及以后的版本中,可以通过这个参数控制stop slave 的执行时间,在重放一个大的事务的时候,突然执行stop slave,命令 stop slave会执行很久(时间设置的太短会time out),这个时候可能产生死锁或阻塞,严重影响性能,默认值和最大值都是31536000秒(一年)
  10)slave_net_timeout
  The number of seconds to wait for more data from the master before the slave considers the connection broken, aborts the read, and tries to reconnect. The first retry occurs immediately after the timeout. The interval between retries is controlled by the MASTER_CONNECT_RETRY option for the CHANGE MASTER TO statement, and the number of reconnection attempts is limited by the --master-retry-count option. The default is 3600 seconds (one hour).
  翻译:从库等待主库更多的数据的时间,超过这个时间(默认值是3600 ),slave就认为这个连接有问题了,并且终止继续读取主库的变化,尝试从新连接主库。等待超时后立马尝试第一次从新连接,之后重连的时间间隔由CHANGE MASTER TO 的时候指定 MASTER_CONNECT_RETRY=的值 控制,重连的次数由CHANGE MASTER TO 的时候指定master-retry-count=的值 控制。
 
二:解决
1.针对本问题的解释
  当锁等待超时后innodb引擎报此错误,等待时间过长的语句被回滚(不是整个事务)。如果想让SQL语句等待其他事务更长时间之后完成,你可以增加参数innodb_lock_wait_timeout配置的值。如果有太多长时间运行的有锁的事务,你可以减小这个innodb_lock_wait_timeout的值,在特别繁忙的系统,你可以减小并发。
  InnoDB事务等待一个行级锁的时间最长时间(单位是秒),超过这个时间就会放弃。默认值是50秒。一个事务A试图访问一行数据,但是这行数据正在被另一个innodb事务B锁定,此时事务A就会等待事务B释放锁,等待超过innodb_lock_wait_timeout设置的值就会报错ERROR 1205 (HY000)
 
2.理论值
  innodb_lock_wait_timeout是动态参数,默认值50秒,最小值是1秒,最大值是1073741824;
 
3.setinnodb_lock_wait_timeout=1500; 和 set global innodb_lock_wait_timeout=1500;的区别。
  前者等价于set session只影响当前session,后者作为全局的修改方式,只会影响修改之后打开的session;注意后者不能改变当前session;
 
4.调大参数
  技术分享图片

 

5.重新实验

  时间更久后的实验,目前是没有问题了。

  没有出现锁表的问题,因为,这里只是简单的实验,不会出现那个情况。

   
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 


以上是关于Lock wait timeout exceeded; try restarting transaction-Mysql报错的主要内容,如果未能解决你的问题,请参考以下文章

038 lock wait timeout exceeded;try restarting transaction

mysql Lock wait timeout exceeded; try restarting transaction解决

MySQL 锁等待超时(Lock wait timeout exceeded)

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql, Lock wait timeout exceeded; try restarting 解决

Mysql错误: ERROR 1205: Lock wait timeout exceeded解决办法