面试题 --- 乐观锁与悲观锁

乐观锁(Optimistic Locking)

乐观锁是基于一种假设:即多个事务同时访问同一数据的概率较低,因此它们不会经常产生冲突。在这种机制下乐观锁(Optimistic Locking)

乐观锁是基于一种假设:即多个事务同时访问同一数据的概率较低,因此它们不会经常产生冲突。在这种机制下,事务在开始时不会立即锁定数据,而是在提交事务时检查数据是否被其他事务修改过。如果数据未被修改,则事务成功提交;如果数据已被修改,则事务会回滚。

在数据库中实现乐观锁通常有以下几种方法:

时间戳(Timestamp):在数据表中添加一个额外的列,通常称为"时间戳"或"版本号"。每次数据被修改时,这个时间戳或版本号都会更新。查询数据时,会检查当前时间戳是否与数据库中的时间戳一致。如果一致,则允许更新;如果不一致,表示数据在读取和更新之间已被修改,事务会失败。

版本号(Version Number):类似于时间戳,但使用整数作为版本号。每次数据更新时,版本号递增。事务在更新数据时会检查版本号,只有当版本号与预期相匹配时,才进行更新并将版本号递增。

悲观锁(Pessimistic Locking)

悲观锁则是基于另一种假设:即多个事务同时访问同一数据的概率较高,可能会导致冲突。因此,悲观锁在事务开始时就会锁定所需的数据,防止其他事务进行修改,直到当前事务提交或回滚。

悲观锁的实现方式通常包括:

行锁(Row Locks):数据库在行级别上加锁,确保事务在读取或写入特定数据时不会被其他事务干扰。

表锁(Table Locks):数据库在整个表级别上加锁,这通常会影响性能,因为它阻止了对表的所有访问,直到锁被释放。

选择乐观锁还是悲观锁

选择使用乐观锁还是悲观锁取决于具体的应用场景和并发水平。乐观锁适合冲突较少的环境,可以提高并发性能,因为它避免了锁定带来的开销。而悲观锁更适用于冲突频繁的环境,尤其是在数据修改非常关键且不能容忍失败的情况下。

在数据库中实现乐观锁通常有以下几种方法:

时间戳(Timestamp):在数据表中添加一个额外的列,通常称为"时间戳"或"版本号"。每次数据被修改时,这个时间戳或版本号都会更新。查询数据时,会检查当前时间戳是否与数据库中的时间戳一致。如果一致,则允许更新;如果不一致,表示数据在读取和更新之间已被修改,事务会失败。

版本号(Version Number):类似于时间戳,但使用整数作为版本号。每次数据更新时,版本号递增。事务在更新数据时会检查版本号,只有当版本号与预期相匹配时,才进行更新并将版本号递增。

悲观锁(Pessimistic Locking)

悲观锁则是基于另一种假设:即多个事务同时访问同一数据的概率较高,可能会导致冲突。因此,悲观锁在事务开始时就会锁定所需的数据,防止其他事务进行修改,直到当前事务提交或回滚。

悲观锁的实现方式通常包括:

行锁(Row Locks):数据库在行级别上加锁,确保事务在读取或写入特定数据时不会被其他事务干扰。

表锁(Table Locks):数据库在整个表级别上加锁,这通常会影响性能,因为它阻止了对表的所有访问,直到锁被释放。

选择乐观锁还是悲观锁

选择使用乐观锁还是悲观锁取决于具体的应用场景和并发水平。乐观锁适合冲突较少的环境,可以提高并发性能,因为它避免了锁定带来的开销。而悲观锁更适用于冲突频繁的环境,尤其是在数据修改非常关键且不能容忍失败的情况下。

使用场景:

乐观锁:在商品库存表中,商品销售频繁,在更新库存信息时采用乐观锁。我们采用的方法是:给库存表的数据表添加一个标识字段------版本号(version),在每次执行入库的sql语句时,在执行条件中添加一个where条件判断version是否与之前读取的一致,如果满足,则修改对应内容以及版本号更新(如+1),如果不满足,则事务回滚,重新执行。
悲观锁:在一个银行转账系统中,转账操作涉及从一个账户扣除金额并添加到另一个账户。这种操作对数据的一致性要求非常高,因为同时进行的转账操作可能会导致错误的余额计算。在这种情况下,可以使用悲观锁。当一个转账操作开始时,系统会锁定涉及的账户记录,确保在此期间其他转账操作无法修改这些记录。直到转账操作完成并释放锁后,其他事务才能继续进行。

相关推荐
Java牛马2 小时前
SpringBoot Starter 依赖相关总结
java·spring·springboot·starter·自动装配·依赖
吴声子夜歌3 小时前
Java面试——Spring Cloud原理及应用(二)
java·spring cloud·面试
东小西3 小时前
【SAA实战】第 1 篇:ReactAgent 入门——先撸个"会调工具的助手"跑起来
java·人工智能·spring
正儿八经的少年3 小时前
布隆过滤器(解决redis缓存穿透步骤之一)
数据库·redis·缓存
xrandzj4 小时前
MySQL8.0 从零通关核心操作手册(Ubuntu实战版)
数据库·mysql
我不会插花弄玉4 小时前
4.数据类型【由浅入深-MySQL】
数据库·mysql
mqiqe4 小时前
AgentScope Java 2.0 协议集成全景解析:A2A、AG-UI、Agent Protocol 三大开放协议实战指南
java·开发语言·ui
denggun123454 小时前
yield
前端·数据库·python
脉动数据行情4 小时前
Java 实现台股 TWSE/TPEx 行情采集(个股 + K 线)
java·开发语言·twse·tpex·台股
ltl4 小时前
SQLite Rollback Journal:写前拷贝与提交点
数据库