点开工具、字典、anything


Laravel中的mysql事务

<p>2019-09-20 20:50:39 星期五 王志伟</p> <p><strong>触发场景:</strong> 做矩阵后台栏目文章数据迁移,大量怼数据请求更新文章,通过swoole重新保存文章的缓存</p> <p><strong>遭遇问题:</strong> 由于每次循环都要做两次更新,所以这里使用了事务。</p> <pre><code>foreach($aas as $aa){ DB::beginTransaction(); if(!$aa) continue; DB::commit(); }</code></pre> <p>这个时候数据大量跑入swoole,出现队列堆积问题,经过查日志,发现由于事务死锁导致无法往下执行</p> <pre><code>Lock wait timeout exceeded; try restarting transaction</code></pre> <p><strong>问题分析:</strong> 由于数据入队时先开启事务,但部分不可用数据在判断出<strong>continue</strong>了,导致本次事务没有走到<strong>commit</strong>,又开启了下一个事务,由于laravel的事务嵌套处理,使未<strong>commit</strong>的事务触发死锁,而导致swoole里的数据库操作无法使用。</p> <p><strong>结论:</strong> mysql本身事务机制:在开启事务后未提交事务时,如果开启了下一个事务,会默认将上一个事务rollback laravel事务机制:事务A未提交,又开启事务B时,会将事务B作为子事务嵌套于事务A中,只有最外层的事务A提交时,才会同时提交A的子事务,而此处事务A已经不能提交了,所以造成了事务死锁</p> <p><strong>解决:</strong> 代码问题,结构改造如下:</p> <pre><code>foreach($aas as $aa){ if(!$aa) continue; DB::beginTransaction(); DB::commit(); }</code></pre> <p>注意事务不要被中间隔断,事务尽量缩短包含范围</p>

页面列表

ITEM_HTML