mysql删造成表死锁研究

本文介绍了一个课件管理系统中删除文件夹时出现502错误的问题及解决方案。通过分析发现,由于SQL语句未使用索引导致表级锁,进而引起死锁。最终通过为路径字段添加索引解决了问题。

  现在互联网公司对于代码的管理越来越规范,一般都会有3个环境:开发环境,测试环境,正式环境。在开发环境进行开发,开发完成后将代码提交到测试环境进行测试,测试完毕后上线到正式环境。

  今天在正式环境上遇到一个问题,做的是一个课件管理系统,在删除文件夹的时候,报错502。使用谷歌开发者工具后没有发现问题所在,在测试环境删除文件夹可以成功,并没有出现502。查询正式服务器的日志发现课件表 doc 被锁住了。因为删除文件夹的的时候,文件夹目录里的文件也需要删除,SQL语句:delete from doc where path like 'xxx%'。doc 表的存储引擎是innodb,innodo默认是行级锁,但是行级锁是根据索引来确定,如果根据索引无法确定的时候,就会使用表级锁,而我使用的sql语句中 path 列并没有加索引,导致使用了表级锁,正式环境的并发比较大,所以在删除 doc 表数据的时候造成 doc 表死锁。

  知道了原因后,将 doc 表的 path 列加上索引后,因为like进行前缀匹配,所以能够引用到索引,再次删除的时候,可以删除成功。

  

转载于:https://www.cnblogs.com/lingerfeifei/p/5721368.html

<think>嗯,用户问的是MySQL死锁的原因和解决方法。我需要先回顾一下之前提供的引用内容,看看有没有相关的信息。引用[1]提到了死锁的产生是因为多个事务竞争资源,还举了例子,比如两个事务互相等待对方的锁。解决方法包括调整事务顺序、使用索引、减少事务时间和设置超时时间。引用[2]补充说死锁常见于事务操作,比如更新不同的顺序不一致,导致互相持有对方需要的锁。引用[4]指出死锁主要发生在InnoDB引擎中,而级锁不会产生死锁。 首先,应该解释死锁的原因,可能包括事务顺序不一致、未使用索引导致锁范围过大、长事务持有锁太久、以及系统处理死锁的机制。然后解决方法需要涵盖如何检测死锁,比如使用SHOW ENGINE INNODB STATUS,还有预防措施,比如统一事务顺序、合理使用索引、控制事务大小和时间,设置锁超时参数,以及自动重试机制。 用户可能需要具体的操作步骤,比如如何查看死锁日志,如何杀死进程,或者如何调整事务。还要注意引用中的例子,比如kill id来终止进程,或者使用show open tables查看被锁的。另外,死锁发生时,InnoDB会自动回滚其中一个事务,用户可能需要知道如何配置innodb_deadlock_detect和innodb_lock_wait_timeout参数。 是否需要分点回答原因和解决方法?可能结构要清晰,先原因再解决,每个部分分条目。同时,生成相关问题时要考虑用户可能进一步的问题,比如如何分析死锁日志,如何优化事务设计,或者具体的参数设置方法。要确保回答准确,并且引用相关的引用内容作为支持,比如引用中的例子和解决方法。</think>### MySQL死锁的原因及解决方法 #### 一、死锁产生的原因 1. **事务操作顺序不一致** 多个事务以不同顺序访问和修改同一批资源时,可能导致循环等待。例如: - 事务A先锁$T_1$,再请求锁$T_2$; - 事务B先锁$T_2$,再请求锁$T_1$; - 双方互相等待对方释放锁,形成死锁[^2][^4]。 2. **未合理使用索引** 若SQL语句未使用索引或索引失效,会导致锁范围扩大(如锁),增加资源竞争概率[^2][^3]。 3. **长事务持有锁时间过长** 事务未及时提交或回滚,长期占用锁资源,导致其他事务长时间等待[^3]。 4. **系统自动检测与超时机制** InnoDB引擎默认启用死锁检测(`innodb_deadlock_detect`),发现死锁后会自动回滚代价较小的事务。若未检测到死锁但锁等待超时(`innodb_lock_wait_timeout`),则终止请求[^1][^4]。 --- #### 二、解决方法 1. **查看并终止死锁进程** - **查看当前锁状态**: ```sql SHOW OPEN TABLES WHERE In_use > 0; -- 查看被锁的 SHOW ENGINE INNODB STATUS; -- 查看最近死锁日志[^1] ``` - **终止阻塞进程**: ```sql KILL [try_mysql_thread_id]; -- 根据锁日志中的线程ID终止进程[^1] 2. **预防措施** - **统一事务操作顺序**:确保所有事务以相同顺序访问资源,避免循环等待[^2]。 - **合理使用索引**:通过索引缩小锁范围(如行锁而非锁)[^2]。 - **控制事务粒度**:减少事务执行时间,及时提交或回滚[^3]。 - **设置锁超时参数**: ```sql SET innodb_lock_wait_timeout=30; -- 设置锁等待超时时间(秒) ``` 3. **自动重试机制** 在代码层捕获死锁异常(如`ERROR 1213`),触发事务重试逻辑[^1][^2]。 --- #### 三、示例场景分析 假设事务A和事务B按以下顺序操作: ```sql -- 事务A UPDATE aa SET name='aaa'; UPDATE bb SET name='bbb'; -- 事务B UPDATE bb SET name='xxx'; UPDATE aa SET name='yyy'; ``` 若事务A先锁$aa$,事务B先锁$bb$,双方后续请求对方持有的锁时,会触发死锁。InnoDB会回滚其中一个事务,释放资源[^1][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值