当前位置:Gxlcms > 数据库问题 > 【MySQL】所谓的乐观锁与悲观锁 -- 2019-08-08 20:39:47

【MySQL】所谓的乐观锁与悲观锁 -- 2019-08-08 20:39:47

时间:2021-07-01 10:21:17 帮助过:14人阅读

原文: http://106.13.73.98/__/175/

乐观锁

总是认为不会产生并发问题,每次去取数据时总认为不会有其它线程对数据进行修改,因此不会上锁。
但是在更新时会判断其它线程在这之前有没有对数据进行修改,一般会使用版本号机制会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://106.13.73.98/__/175/

【MySQL】所谓的乐观锁与悲观锁 -- 2019-08-08 20:39:47

标签:次数   model   被锁   python   异常   code   zed   并发   数据库   

人气教程排行