mysql for update lock 悲观锁 解决并发问题
mysql常用的锁有for update 和 for update in share mode两种
锁的区别
- for update 我认为是悲观锁,其他事务读会被阻塞等待,写被禁止,且不准多次加锁
- for update in share mode 读取不等待,写入会被禁止,可被多次加锁
in share mode的问题
如果两个事务对同一行数据加锁很容易导致,两个事务都更新失败
使用场景
基于以上特点介绍,in share mode可以用于两个表关联时,保护主表数据不被修改,for update更适合保护单表单行数据的正确性,适合投票、提现等场景
测试验证
以下代码验证for update的作用
表maxcount中marks初始为8,每次减1,当他大于0时,将当时数据保存,类似于抽奖中控制最大奖品数的问题
tp中lock(true)会默认使用for update锁,我们每次测试修改代码即可
并发配置
使用ab发400并发
ab -n 400 -c 400 http://127.0.0.1/
测试代码
$marks = -1;
Db::transaction(function() use ($maxcount,&$marks,$meta){
$max = $maxcount->where([
'userid' => 'shuaka1500',
'reason' => '2018-09-06 00:00:00',
])->lock(true)->find();
$max->setDec('marks', 1);
$marks = $max->marks;
if ($marks >= 0)
{
$meta->data([
'post_id'=>$marks
], true);
$meta->save();
}
});
事务+for update
这是正确的用法,我们发现数据记录都是合理的,并且数据都是按顺序记录,有效解决了并发问题
无事务+无锁
这时数据出现了错误,但是由于没有开启事务,性能比较强,所以并没有多记录
事务+无锁
由于开启了事务,mysql性能下降,又没有正确使用锁,在并发时多记录了数据,如果这时抽奖,发出的奖品就会过多问题严重
,本来8个奖品,现在发了10个出去
最后更新于 2018-09-19 15:27:29 并被添加「mysql for update lock 悲观锁 解决并发问题」标签,已有 900 位童鞋阅读过。
恭喜老范喜提678篇技术好文。
恭喜老范喜提678篇技术好文。