数据库常见面试题:数据库的悲观锁、乐观锁区别对比

面试题 潘老师 2个月前 (02-10) 40 ℃ (0) 扫码查看

在数据库面试中,经常会被问到数据库的悲观锁和乐观锁的区别对比。但很多开发小伙伴,即便工作了多年,可能对数据库锁的概念还一知半解,更别提深入理解悲观锁和乐观锁了。在程序员面试中,数据库锁可是高频考点,面试官常借此考察求职者对数据库工作原理、隔离机制和并发控制等知识的掌握程度。这是因为随着系统不断迭代升级,在高并发场景下,数据库锁的应用不可或缺。下面,咱们就来详细聊聊这两种锁。

一、悲观锁:保守的资源守护者

悲观锁,从名字就能看出它秉持着一种比较“悲观”的态度。它假设每次事务操作时,都极有可能修改同一个资源,如果并发操作,必然会引发问题。为了避免这种情况,悲观锁选择直接给资源上锁。在同一时刻,只允许一个数据库事务对资源进行修改操作。

从SQL语句层面来看,实现悲观锁常用的方式是 select for update 。举个例子,当一个事务执行这条语句时,它会把选中的记录锁住。此时,如果其他事务也尝试对这些记录进行操作,就只能等待。直到当前持有锁的事务提交,释放了锁,其他事务才有机会获取锁并执行操作。这就好比在一个狭窄的通道口,每次只允许一个人通过,其他人必须在外面排队等候,是一种串行化的操作方式。这种方式虽然保证了数据的一致性,但在高并发场景下,由于很多事务需要等待锁的释放,可能会导致性能下降。

二、乐观锁:积极的并发探索者

乐观锁则秉持着一种“乐观”的理念,它认为大多数情况下,事务是读取数据的操作,更新数据的情况较少,即“查多改少”。所以在初始阶段,它不会像悲观锁那样直接给资源上锁,而是允许各个事务自由访问数据。

那乐观锁如何解决并发写的问题呢?这里引入了“版本号”的概念。简单来说,数据库中的每一条记录都对应一个版本号。当事务读取数据时,会获取到当前的版本号;在执行更新操作时,会把读取到的版本号作为条件写在 where 语句中。更新完成后,版本号会自动加一。如果在更新时发现当前版本号与之前读取的不一致,那就意味着在这个过程中,数据已经被其他事务修改过了。此时,为了保证数据的一致性,当前更新操作会失败,并抛出异常,由前端业务来处理后续逻辑。

这就好比大家在一个开放的图书馆里看书,每个人都可以自由拿书阅读。但当有人想要修改书籍内容时,需要先检查版本号。如果版本号变了,就说明这本书在他阅读期间被别人修改过了,他就不能直接修改,得重新获取最新版本再尝试。这种方式在一定程度上提高了并发性能,因为它不会一开始就阻塞事务,只有在数据真的发生冲突时才进行处理。

三、乐观锁并非万能钥匙

虽然乐观锁在并发性能上有优势,但它也并非适用于所有场景。在并发量特别大的场景下,比如电商的秒杀促销活动,大量用户同时抢购商品,频繁地扣减库存。由于乐观锁的版本号机制,同一时间只有一个事务能成功扣减库存,其他事务都会失败,这些失败的事务就需要重新尝试,比如重新刷新页面、再次发起请求等。这无疑会给系统带来巨大的请求压力,严重时甚至可能拖垮整个业务平台,这就是所谓的重试开销。

所以,乐观锁更适合用在访问量大但修改量少的场景中。在这种场景下,它既能充分发挥并发访问的优势,又能通过版本号机制有效锁定资源,确保数据的一致性。此外,乐观锁在幂等控制方面也有应用,感兴趣的同学可以深入了解一下。

数据库的悲观锁和乐观锁各有特点和适用场景。在实际开发中,我们需要根据业务场景的并发情况、数据一致性要求等因素,合理选择使用哪种锁。如果大家对这两种锁还有疑问,欢迎在评论区留言讨论,咱们一起进步!


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/ms/14135.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】