数据库悲观锁和乐观锁的区别

前言

MySQL本身不直接提供悲观锁(Pessimistic Locking)和乐观锁(Optimistic Locking)的实现机制,因为这些锁的概念通常是在应用层面通过不同的策略和工具来实现的。然而,我们可以利用MySQL的一些特性来模拟或支持这两种锁的行为。
在这里插入图片描述

一、什么是乐观锁和悲观锁?

乐观锁(Optimistic Locking)和悲观锁(Pessimistic Locking)是两种在数据库管理和并发控制中常用的策略,它们以不同的方式处理数据访问和修改时可能发生的冲突。下面将详细描述这两种锁的工作机制。

1. 悲观锁(Pessimistic Locking)

悲观锁基于一种悲观的态度来处理并发问题,它假设数据冲突将会频繁发生,因此在数据被读取的同时就会被锁定,以防止其他事务对数据进行修改,直到当前事务完成。
在这里插入图片描述

工作机制

  1. 加锁:当事务需要读取或修改某个数据时,它首先会对该数据加锁。在MySQL中,这通常是通过SELECT ... FOR UPDATE语句实现的,它会锁定读取的行直到事务结束(提交或回滚)。

  2. 数据操作:事务在持有锁的情况下对数据进行读取或修改。

  3. 解锁:当事务提交时,锁会被释放,其他事务才能访问这些数据。如果事务回滚,锁也会被释放,但所做的修改不会保存到数据库中。

  4. 等待与冲突解决:如果有多个事务试图对同一数据进行加锁,那么后来的事务将会等待,直到前面的事务释放锁。这可能会导致事务的延迟或死锁(如果两个事务相互等待对方释放锁)。

2. 乐观锁(Optimistic Locking)

乐观锁则基于一种乐观的态度来处理并发问题,它假设数据冲突将不会频繁发生,因此在数据读取时不会加锁,而是在更新数据时检查数据是否被其他事务修改过。
在这里插入图片描述

工作机制

  1. 数据读取:事务首先读取需要修改的数据及其版本号(或时间戳)。这个版本号是在数据库中额外维护的一个字段,用于跟踪数据的更新情况。

  2. 数据操作:事务在本地对读取的数据进行修改,但不立即更新到数据库中。

  3. 提交前的检查:在提交事务之前,事务会再次查询数据库中对应数据的版本号,并将其与第一步读取的版本号进行比较。

  4. 数据更新

    • 如果版本号相同,说明数据在读取和提交之间没有被其他事务修改过,事务可以安全地更新数据,并将版本号增加(或更新时间戳)。
    • 如果版本号不同,说明数据在读取和提交之间已经被其他事务修改过,此时当前事务可以选择重试(重新读取数据并尝试更新)、回滚或向应用层报告错误。
  5. 提交事务:如果数据更新成功,事务将提交,所做的修改将被保存到数据库中。

优点与缺点

  • 悲观锁的优点是能够在很大程度上避免数据冲突,但缺点是可能会导致性能问题,因为事务在持有锁期间会阻塞其他事务对数据的访问。
  • 乐观锁的优点是避免了锁的开销,提高了系统的并发性能,但缺点是当冲突发生时,可能需要事务重试,这可能会增加事务的延迟和复杂性。

在选择使用哪种锁时,需要根据具体的应用场景和性能需求进行权衡。

二、应用实践

悲观锁(Pessimistic Locking)

前面我们说到它的工作机制,悲观锁是假定冲突将频繁发生,因此在操作数据之前先锁定数据。在MySQL中,悲观锁可以通过行级锁(InnoDB存储引擎提供)或表级锁(MyISAM或InnoDB在某些情况下)来实现。

应用实践
  1. 使用SELECT … FOR UPDATE

    这是最常用的悲观锁实现方式。当事务使用SELECT ... FOR UPDATE语句读取记录时,MySQL会对这些记录加锁,其他事务必须等待锁释放才能修改这些记录。

    START TRANSACTION;
    SELECT * FROM accounts WHERE id = 100 FOR UPDATE;
    -- 在这里进行更新操作
    UPDATE accounts SET balance = balance - 100 WHERE id = 100;
    COMMIT;
    

    注意:FOR UPDATE必须在一个事务中使用,否则会立即释放锁。

  2. 使用表锁

    虽然表锁不是悲观锁的最佳实践(因为它会锁定整个表),但在某些情况下仍然可以使用。通过LOCK TABLESUNLOCK TABLES命令可以显式地锁定和解锁表。

    LOCK TABLES accounts WRITE;
    -- 在这里进行更新操作
    UPDATE accounts SET balance = balance - 100 WHERE id = 100;
    UNLOCK TABLES;
    

乐观锁(Optimistic Locking)

乐观锁假定冲突不会经常发生,因此只在提交更新时检查数据是否被其他事务修改过。这通常通过版本号(version number)或时间戳(timestamp)来实现。

应用实践
  1. 使用版本号

    在数据库表中添加一个version字段,每次更新数据时增加版本号。在更新时,检查版本号是否匹配,如果不匹配则拒绝更新。

    -- 假设version是表中的一个字段
    UPDATE accounts SET balance = balance - 100, version = version + 1 WHERE id = 100 AND version = ?;
    

    在应用中,你需要先查询当前记录的版本号,然后在更新时提交这个版本号。如果更新影响的行数为0,则表示数据在查询和更新之间被其他事务修改了。

  2. 使用时间戳

    类似于版本号,但使用时间戳字段来跟踪记录的最后一次更新时间。

    UPDATE accounts SET balance = balance - 100, last_updated = NOW() WHERE id = 100 AND last_updated = ?;
    

    同样,你需要先查询记录的last_updated时间,然后在更新时提交这个时间戳。

应用场景

乐观锁和悲观锁在数据库管理和并发控制中各有其适用的应用场景。以下是两者之间的应用场景的详细列举:

乐观锁的应用场景

  1. 读多写少的场景

    • 在这种场景下,多个事务主要进行数据的读取操作,而写操作相对较少。使用乐观锁可以减少锁的开销,提高系统的并发性能。例如,新闻网站中用户同时浏览新闻的场景,新闻内容被修改的概率较低,适合使用乐观锁。
  2. 偶尔冲突且回滚成本较低的场景

    • 当数据冲突不频繁,且回滚事务的成本低于读取数据时锁定数据的成本时,使用乐观锁可以获得更高的吞吐量。例如,在电商网站的购物车操作中,虽然多个用户可能同时操作购物车,但购物车内容被同时修改的概率较低,即使发生冲突,回滚购物车操作的成本也相对较低。
  3. 数据版本控制

    • 在需要保证数据版本一致性的场景下,可以使用乐观锁来控制数据的更新操作。通过版本号或时间戳来跟踪数据的更新情况,确保在更新数据时数据的一致性。

悲观锁的应用场景

  1. 写多读少的场景

    • 在这种场景下,多个事务主要进行数据的修改操作,而读取操作相对较少。使用悲观锁可以确保数据在修改过程中不会被其他事务干扰,保证数据的一致性。例如,在电商网站的库存扣减操作中,由于库存数据需要频繁更新,且更新操作对数据的准确性要求极高,因此适合使用悲观锁。
  2. 并发冲突较高的场景

    • 当多个事务同时对同一数据进行读写操作时,使用悲观锁可以避免数据冲突和更新丢失的问题。通过锁定数据,确保在事务完成之前其他事务无法修改该数据。例如,在银行系统的账户转账操作中,由于涉及到多个账户的金额变动,且这些变动必须同时成功或同时失败,因此需要使用悲观锁来确保数据的一致性。
  3. 数据一致性要求极高的场景

    • 在对数据一致性要求极高的场景下,如金融交易、医疗记录等,使用悲观锁可以确保数据在处理过程中不会被其他事务干扰,从而避免数据不一致的问题。

综上所述,乐观锁和悲观锁各有其适用的应用场景。在选择使用哪种锁时,需要根据具体的应用场景、性能需求和数据一致性要求来进行权衡和选择。

总结

选择悲观锁还是乐观锁取决于你的应用场景。悲观锁适合写操作频繁的场景,因为它可以减少数据冲突,但可能会增加等待时间和锁的竞争。乐观锁适合读多写少的场景,它减少了锁的开销,但在高并发写的情况下可能需要处理更多的冲突。
在实际应用中,还需要考虑事务的隔离级别、锁的粒度(行级锁、表级锁)以及应用的具体需求来选择合适的锁策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1523212.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

泰克THDP0100(Tektronix)thdp0100高压差分探头详情资料

泰克 THDP0100 高压差分探头具有较大的差分动态范围功能,为用户提供了安全的高压测量探头解决方案。每个探头都配有两种尺寸的钩尖,并具有超范围视觉和声音指示器,当用户超出探头的线性范围时会发出警告。泰克 THDP0100 探头配备 TEkVPI 接口…

实训day42(9.3)

⼀、编排分类 单机容器编排: docker-compose 容器集群编排: docker swarm、mesosmarathon、kubernetes 应⽤编排: ansible(模块,剧本,⻆⾊) ⼆、系统管理进化史 1. 传统部署时代 早期,各个组织是在物理服务器上运⾏应⽤程序。 由于⽆法限…

【Linux】倒计时|进度条|git|gdb的实现

目录 一、缓冲区 1.缓冲区概念: 2.缓冲区作用: 3.缓冲区刷新策略 4.缓冲区位置 5.总结 二、实现倒计时 三、进度条版本1️⃣ 四、进度条版本2️⃣ 五、使用git命令行 六、Linux调试器-gdb使用 背景 开始使用 一、缓冲区 1.缓冲区概念&…

如何提升网站权重?

提升网站权重的方法有很多,常规的方法包括内容优化、关键词研究、页面结构调整、提高用户体验等。但这些方法往往需要时间来见效。如果你希望在短时间内看到显著的提升,发外链是一个非常有效的策略。 外链是提升网站权重的有效方法,但需要注…

【Transformer】Tokenization

文章目录 直观理解分词方式词粒度-Word字粒度-Character子词粒度-Subword(目前最常使用) 词表大小的影响参考资料 直观理解 在理解Transformer或者大模型对输入进行tokenize之前,需要理解什么是token? 理工科的兄弟姐妹们应该都…

无人机+应用综合实训室解决方案

随着无人机技术的飞速发展,其在航拍、农业、环境监测、物流运输等多个领域展现出巨大的应用潜力。为了满足职业院校及企业对无人机应用技术型人才的培养需求,唯众紧跟市场趋势,推出了全面且详尽的《无人机应用综合实训室解决方案》。本方案旨…

TeamTalk路由服务器

路由相关信令和协议设计 enum BuddyListCmdID {// ...... 暂时省略无关信令CID_BUDDY_LIST_USERS_STATUS_REQUEST 522,CID_BUDDY_LIST_USERS_STATUS_RESPONSE 523,// ...... 暂时省略无关信令 };message IMUsersStatReq{//cmd id: 0x020arequired uint32 user_id 1;repeat…

python 正则表达式“.*”和“.*? ”的区别

“.*”和“.*? ”的区别 点号表示任意非换行符的字符,星号表示匹配它前面的字符0次或者任意多次。所以“.*”表示匹配一串任意长度的字符串任意次。这个时候必须在“.*”的前后加其他的符号来限定范围,否则得到的结果就是原来的整个字符串。 “.*? &…

“软件即仪器”——全新架构 Xtreme Vision显微测量软件平台

“软件即仪器”,工业测量软件较为复杂,涵盖了软件架构、信号处理、图像处理、数值计算、空间几何、三维建模、3D渲染、并行计算、人机交互等多种交叉软学科,是测量仪器系统极为重要的组成部分,中图仪器一直致力于自主化工业测量软…

使用AI写WebSocket知识是一种怎么样的体验?

一、WebSocket基础知识 1. WebSocket概念 1.1 为什么会出现WebSocket 一般的Http请求我们只有主动去请求接口,才能获取到服务器的数据。例如前后端分离的开发场景,自嘲为切图仔的前端大佬找你要一个配置信息的接口,我们后端开发三下两下开…

使用 Spring Cloud 有什么优势?

使用 Spring Cloud 有什么优势? 1. 简化复杂性2. 服务发现与注册3. 负载均衡4. 冗余与容错5. 性能与部署6. 生态系统与社区 💖The Begin💖点点关注,收藏不迷路💖 在微服务架构的浪潮中,Spring Cloud凭借其简…

传统CV算法——基于Opencv的多目标追踪算法

基于 OpenCV 的跟踪算法有多种,每种算法都有其特定的应用场景和优缺点。以下是一些常见的基于 OpenCV 的目标跟踪算法: 1. BOOSTING 跟踪器 描述:基于 AdaBoost 算法的跟踪器。它是一种早期的跟踪算法,使用的是基于弱分类器的强…

【数据结构篇】~链表算法题2

链表算法题2 1.返回倒数第k个节点思路解析 2.链表的回文结构​思路解析1(空间复杂度不符合)解析2 3.相交链表​思路解析 1.返回倒数第k个节点 OJ链接 思路 有点像高中学的相对位移 利用快慢指针,开始时都指向头节点,然后让快指…

VMware虚拟机安装的Ubuntu,桥接方式静态ip,内网可以访问,ping外网不可用

1.环境说明 系统:Ubuntu 24.04 环境:VMware下桥接静态IP设置 2.问题:ping www.baidu.com报错 [~] ping www.baidu.com ping: www.baidu.com: Temporary failure in name resolutio…

php邮箱服务器怎么搭建?如何构建服务器?

php邮箱服务器配置教程指南?php邮件服务器如何搭建? 搭建一个稳定高效的php邮箱服务器,不仅可以提升邮件传输的效率,还能增强数据的安全性。那么,如何着手搭建这样一个服务器呢?AokSend将详细探讨php邮箱服…

【Go - 每日一小问 ,const 变量存储在哪里,堆还是栈上?】

答:都不是 , 在bss(未初始化数据区) 和 data(初始化数据区)上。 在内存布局上遵循一定规律,Go 进程的内存空间布局由高地址到低地址大致可分为以下几段: 栈(stack): 用户态的栈,栈的大小是固定的,其大小可以使用ulimi…

云服务器中查看Nginx报错日志及解决思路

目录 前言 一、查看nginx日志信息 二、我的解决思路 前言 线上报错不可怕,能找到对应日志,那这个报错就解决一大半了。 默认情况下,nginx日志文件存储在 /var/log/nginx/ 目录中,cd /var/log/nginx/ 一、查看nginx日志信息 …

【hot100篇-python刷题记录】【跳跃游戏 II】

R7-贪心算法 目录 方法1: 方法2: 很贪心啊,局部最优解就是全局最优解,要求到达nums[n-1]的最小步数,我们每一步都走最远。 方法1: class Solution:def jump(self, nums: List[int]) -> int:nlen(n…

畅游5G高速网络:联发科集成Wi-Fi6E与蓝牙5.2的系统级单芯片MT7922

这周末,除非外面下钞票,否则谁也拦不住我玩《黑神话悟空》(附:两款可以玩转悟空的显卡推荐) IPBrain平台君 集成电路大数据平台 2024年09月03日 17:28 北京 联发科一直以创新技术追赶市场需求…… “不努力向前游就会被海浪拍回岸边…” 芯片设计公司产品层出不穷,想要站…

vue3+ts 实现模板表格文件下载~

1、效果图&#xff1a; 2、创建点击事件&#xff0c;并发起请求&#xff0c;获取模板表格文件下载url地址。 //组件 <a-button class"btn btn_width" click"download"> 下载模板 </a-button>// 文件模板下载 import { getTemplate } from /ap…