<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[Heck's  Blog]]></title> 
<link>https://www.heckjj.com/index.php</link> 
<description><![CDATA[一瞬间的决定，往往可以改变很多，事实上，让自己成功的往往不是知识，是精神！ 如果你总是为自己找借口，那只好让成功推迟。执行力，今天！]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[Heck's  Blog]]></copyright>
<item>
<link>https://www.heckjj.com/post//</link>
<title><![CDATA[Lock wait timeout exceeded; try restarting transaction]]></title> 
<author>Heck &lt;@hecks.tk&gt;</author>
<category><![CDATA[数据库]]></category>
<pubDate>Fri, 22 Oct 2021 06:46:52 +0000</pubDate> 
<guid>https://www.heckjj.com/post//</guid> 
<description>
<![CDATA[ 
	一、问题<br/>### Cause: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction;<br/><br/><br/>现象：接口响应时间超长，耗时几十秒才返回错误提示，后台日志中出现Lock wait timeout exceeded; try restarting transaction的错误<br/><br/>二、原因分析<br/>使用InnoDB表类型的时候，锁等待超过了innodb_lock_wait_timeout（默认是50s）设置的时间,所以报错<br/><br/>三、可能出现场景<br/>1、在同一事务内先后对同一条数据进行插入和更新操作<br/><br/>2、多台服务器操作同一数据库<br/><br/>3、瞬时出现高并发现象，spring事务造成数据库死锁，后续操作超时抛出异常<br/><br/>4、事务A对记录C进行更新/删除操作的请求未commit时，事务B也对记录C进行更新/删除操作。此时，B会等A提交事务，释放行锁。当等待时间超过innodb_lock_wait_timeout设置值时，会产生“LOCK WAIT”事务。<br/><br/>四、解决方案<br/>1、【治标方法】innodb_lock_wait_timeout 锁定等待时间改大<br/><br/>SELECT<br/>&nbsp;&nbsp;@@innodb_lock_wait_timeout;<br/><br/>innodb_lock_wait_timeout = 50<br/><br/>修改为<br/>SET @@innodb_lock_wait_timeout = 500;<br/><br/>innodb_lock_wait_timeout = 500<br/><br/>缺点：全局更改，影响也是全局的，等待时间加长，容易使等待事务增多导致堆积问题。<br/><br/>2、【治标方法】事务信息查询<br/><br/>SELECT * FROM information_schema.innodb_trx<br/><br/>查到一个一直没有提交的只读事务（trx_state=”LOCK WAIT”），找到对应线程，执行：<br/><br/>kill 线程ID(trx_mysql_thread_id)<br/><br/>3、【治标方法】如果杀掉线程依然不能解决，可以查找执行线程耗时比较久的任务，kill掉<br/><br/>SELECT * from information_schema.`PROCESSLIST` WHERE Time &gt; 1000 AND USER = &#039;xxx&#039; ORDER BY TIME desc;<br/><br/>kill 线程ID<br/><br/>4、【根本解决方法！】找到锁表的事务，分析锁表原因，进行优化。<br/><br/>实例：司机APP进行运单签收，需要对et_waybill_info表某些记录进行更新操作。一直处于锁等待状态，直到超时报错。<br/><br/>经排查，发现：系统定时器定时执行任务，将所有未标识亮的已装车或签收的运单，按批次处理，如果运单装车了但长时间未上传GPS、温湿度等信息，会一直被定时器处理。数据量越积越大，队列长时间等待，对et_waybill_info表锁住没有释放，致使签收要操作et_waybill_info表无法拿到锁，进行数据操作。<br/><br/>临时解决方案：停掉定时器任务<br/><br/>根本解决方案：优化定时器<br/><br/>五、预防措施<br/>1、开始事务（@transtion）指定超时时 间<br/><br/>例：@Transactional( rollbackFor = Exception.class , isolation = Isolation.REPEATABLE_READ, timeout = 30)<br/><br/>2、事务中存在批量修改、删除语句的时候，where条件尽量加索引<br/><br/>3、事务中存在批量修改、删除语句的时候，尽可能减少事务的执行时间<br/><br/>4、减少并发线程数<br/><br/>六、相关信息<br/>1、innodb_lock_wait_timeout和lock_wait_timeout<br/>innodb_lock_wait_timeout：InnoDB事务等待一个行级锁的时间最长时间（单位是秒），超过这个时间就会放弃。默认值是50秒<br/><br/>lock_wait_timeout：获取元数据锁的超时时间。这个适合用于除了系统表之外的所有表（mysql库之外）。<br/><br/>区别于innodb_lock_wait_timeout是针对dml操作的行级锁的等待时间 ，而lock_wait_timeout是数据结构ddl操作的锁的等待时间<br/><br/>2、事务相关表<br/>INNODB_TRX&nbsp;&nbsp;当前运行的所有事务<br/><br/> <br/><br/>INNODB_LOCKS&nbsp;&nbsp;当前出现的锁，查看正在锁的事务<br/><br/> <br/><br/>INNODB_LOCK_WAITS&nbsp;&nbsp;锁等待的对应关系，查看等待锁的事务<br/><br/> <br/><br/>3、information_schema和performance_schema<br/>information_schema：对数据库元数据的抽象分析，由此提供了SQL语句方式来查询数据库运行时状态，每次对infomation_schema的查询都产生对metadata的互斥访问，影响其他数据库的访问性能。这张数据表保存了MySQL服务器所有数据库的信息。如数据库名，数据库的表，表栏的数据类型与访问权限等。<br/><br/>performance_schema：内存型数据库，使用performance_schema存储引擎，通过事件机制将mysql服务的运行时状态采集并存储在performance_schema数据库。用于监控MySQL server在一个较低级别的运行过程中的资源消耗、资源等待等情况。<br/><br/>七、总结<br/>1、当看到mysql报错时，可以根据报错的信息及错误号去分析报错原因，然后冷静分析，透过现象看本质，从根本上解决问题。少用治标不治本的方案，还可能会带来其他问题。<br/><br/>2、了解了mysql里几张事务相关表<br/><br/>3、初识information_schema和performance_schema
]]>
</description>
</item><item>
<link>https://www.heckjj.com/post//#blogcomment</link>
<title><![CDATA[[评论] Lock wait timeout exceeded; try restarting transaction]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>https://www.heckjj.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>