创新互联GoFrame教程:GoFrame链式操作-悲观锁&乐观锁

悲观锁(​Pessimistic Lock​),顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁、表锁、读锁、写锁等,都是在做操作之前先上锁。

成都创新互联是创新、创意、研发型一体的综合型网站建设公司,自成立以来公司不断探索创新,始终坚持为客户提供满意周到的服务,在本地打下了良好的口碑,在过去的10年时间我们累计服务了上千家以及全国政企客户,如成都自上料搅拌车等企业单位,完善的项目管理流程,严格把控项目进度与质量监控加上过硬的技术实力获得客户的一致称扬。

乐观锁(​Optimistic Lock​),顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量。

悲观锁使用

相关方法

func (m *Model) LockUpdate() *Model
func (m *Model) LockShared() *Model

gdb​模块的链式操作提供了两个方法帮助您在​SQL​语句中实现“悲观锁”。可以在查询中使用​LockShared​方法从而在运行语句时带一把”共享锁“。共享锁可以避免被选择的行被修改直到事务提交:

db.Model("users").Ctx(ctx).Where("votes>?", 100).LockShared().All();

上面这个查询等价于下面这条SQL语句:

SELECT * FROM `users` WHERE `votes` > 100 LOCK IN SHARE MODE

此外你还可以使用​LockUpdate​方法。该方法用于创建​FOR UPDATE​锁,避免选择行被其它共享锁修改或删除:

db.Model("users").Ctx(ctx).Where("votes>?", 100).LockUpdate().All();

上面这个查询等价于下面这条SQL语句:

SELECT * FROM `users` WHERE `votes` > 100 FOR UPDATE

FOR UPDATE​ 与 ​LOCK IN SHARE MODE​ 都是用于确保被选中的记录值不能被其它事务更新(上锁),两者的区别在于 ​LOCK IN SHARE MODE​ 不会阻塞其它事务读取被锁定行记录的值,而 ​FOR UPDATE​会阻塞其他锁定性读对锁定行的读取(非锁定性读仍然可以读取这些记录,​LOCK IN SHARE MODE​ 和 ​FOR UPDATE​都是锁定性读)。

这么说比较抽象,我们举个计数器的例子:在一条语句中读取一个值,然后在另一条语句中更新这个值。使用 ​LOCK IN SHARE MODE​ 的话可以允许两个事务读取相同的初始化值,所以执行两个事务之后最终计数器的值+1;而如果使用 ​FOR UPDATE​的话,会锁定第二个事务对记录值的读取直到第一个事务执行完成,这样计数器的最终结果就是+2了。

乐观锁使用

乐观锁,大多是基于数据版本 (Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个​version​字段来实现。

读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

锁机制总结

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行重试,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

分享标题:创新互联GoFrame教程:GoFrame链式操作-悲观锁&乐观锁
文章路径:http://www.36103.cn/qtweb/news39/2889.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联