MySQL所谓的乐观锁与悲观锁
Posted gqy02
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL所谓的乐观锁与悲观锁 相关的知识,希望对你有一定的参考价值。
原文: http://blog.gqylpy.com/gqy/382
"## 乐观锁
总是认为不会产生并发问题,每次去取数据时总认为不会有其它线程对数据进行修改,因此不会上锁。
但是在更新时会判断其它线程在这之前有没有对数据进行修改,一般会使用版本号机制会CAS操作实现。
版本号方式
????????一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加1。当线程A要更新数据时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值与此时数据库中的version值相等,才会提交更新操作。否则将重新更新操作,直到更新成功。
sql核心代码:
update table set x=x+1, version=version+1 where id=#id and version=#version;
CAS操作方式
????????即 comparse and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新数据时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试。
悲观锁
????????总是假设最坏的情况,每次取数据时都认为其它线程会修改,所以都会加锁(读锁,写锁,行锁),当其它线程要访问数据时,都需要阻塞挂起,可以依靠数据库实现,如行锁、读锁和写锁等,都是在操作之前加锁,在java中,synchronized的思想也是悲观锁。
Python Django项目中的用法:
# 将访问量加1
models.BlogInfo.objects.filter(id=id).select_for_update().update(visit=F('visit') + 1)
# select_for_update():行级锁,所有匹配的行将被锁定,直到事务执行结束
# 一般情况下,如果其它事务锁定了相关行,那么本查询将被阻塞,直到锁被释放
# 如果不想使查询被阻塞,可添加参数 nowait=True
# 如果其它事务持有冲突的锁,互斥锁,那么查询将引发 DatabaseError异常
# 你也可以使用参数 skip_locked=True 忽略锁定的行
# 但要注意的是:nowait=True 与 skip_locked=True 是互斥的,同时使用将抛出异常
"
原文: http://blog.gqylpy.com/gqy/382
以上是关于MySQL所谓的乐观锁与悲观锁 的主要内容,如果未能解决你的问题,请参考以下文章