当前位置: 首页 > ops >正文

SQL中的锁机制

1. 锁

为什么要加锁:

加锁是为了保证数据的一致性,防止并发冲突。这个思想在程序开发领域中同样很重要。在程序开发中也会存在多线程同步的问题。当多个线程并发访问某个数据的时候,尤其是针对一些敏感的数据(比如订单、金额等),我们就需要保证这个数据在任何时刻最多只有一个线程在进行访问,保证数据的完整性和一致性。

1.1. 锁的分类方式

1. 按锁粒度划分

锁类型

粒度

并发性

开销

死锁可能性

特点

行锁

容易

锁单行记录

页锁

一般

可能

锁定一个页,页中多行

表锁

锁整个表

  • 附加粒度:区锁、数据库锁(不同引擎支持不同锁粒度)
  • 锁升级机制:当锁资源占用超过阈值,系统将小粒度锁升级为大粒度锁以节省资源(如行锁升级为表锁)

2. 按数据库管理角度划分

锁类型

别名

行为

共享锁(S锁)

读锁

允许并发读,不允许写

排它锁(X锁)

写锁

排他访问,其他事务不能读写

意向锁

 

提前声明下级资源有锁,辅助加锁判断

加锁命令:

  • 表级共享锁:LOCK TABLE table_name READ;
  • 表级排它锁:LOCK TABLE table_name WRITE;
  • 解锁:UNLOCK TABLE;
  • 行级共享锁:SELECT ... LOCK IN SHARE MODE
  • 行级排它锁:SELECT ... FOR UPDATE

意向锁的作用

  • 用于快速判断是否可以加表级锁,无需扫描所有记录
  • 类型包括:意向共享锁(IS锁)、意向排它锁(IX锁)

1.2. 死锁

死锁的概念:

死锁(Deadlock)是指在并发系统中,两个或多个事务因争夺资源而互相等待,导致所有事务都无法继续执行的现象。

死锁产生的四个必要条件(Coffman条件):

  1. 互斥条件:资源一次只能被一个事务占用。
  2. 请求与保持条件:一个事务已经持有资源,同时又申请其他资源。
  3. 不剥夺条件:事务持有的资源在使用完之前,不能被强制剥夺。
  4. 循环等待条件:两个或多个事务之间形成资源等待环路。

为什么共享锁也可能导致死锁?

多个事务同时持有共享锁时,尝试升级为排它锁可能发生资源互相等待,导致死锁

死锁处理机制:

  • 数据库检测循环等待
  • 选出牺牲事务,回滚重试

降低死锁概率的方式:

  1. 如果事务涉及多个表,操作比较复杂,那么可以尽量一次锁定所有的资源,而不是逐步来获取,这样可以减少死锁发生的概率;
  2. 如果事务需要更新数据表中的大部分数据,数据表又比较大,这时可以采用锁升级的方式,比如将行级锁升级为表级锁,从而减少死锁产生的概率;
  3. 不同事务并发读写多张数据表,可以约定访问表的顺序,采用相同的顺序降低死锁发生的概率。

1.3. 从程序员的角度对锁进行划分

乐观锁和悲观锁并不是锁,而是锁的设计思想

1. 悲观锁(Pessimistic Locking)

  • 特点:认为并发冲突可能发生,操作前加锁
  • 实现:直接使用数据库锁机制,如 SELECT ... FOR UPDATE
  • 适用场景:高冲突、高一致性要求

2. 乐观锁(Optimistic Locking)

  • 特点:认为冲突较少,不主动加锁,提交时校验
  • 实现方式:

版本号机制

    • 增加 version 字段
    • 更新语句中包含 WHERE version = ?
    • 若版本不一致则更新失败

时间戳机制

    • 使用 update_time 字段进行乐观校验
  • 适用场景:读多写少场景,性能优于悲观锁

两种锁的使用场景:

  1. 乐观锁适合读操作多的场景,相对来说写的操作比较少。它的优点在于程序实现,不存在死锁问题,不过适用场景也会相对乐观,因为它阻止不了除了程序以外的数据库操作。
  2. 悲观锁适合写操作多的场景,因为写的操作具有排它性。采用悲观锁的方式,可以在数据库层面阻止其他事务对该数据的操作权限,防止读 - 写和写 - 写的冲突。

 

http://www.xdnf.cn/news/9353.html

相关文章:

  • LabVIEW 中不同 VI 间图像传递方法解析
  • 数据结构-排序(1)
  • 基于seal密码库的格加密算法的原理、实现与应用
  • 6个月Python学习计划 Day 7 - 复盘 + 测试日
  • 压缩包方式在Linux和Windows下安装mongodb
  • zynq7020 shm共享内存和OCM
  • Rust 和 Python 如何混合使用
  • 面试题——计算机网络:HTTP和HTTPS的区别?
  • MySQL问题:MVCC是什么?
  • 从解决一个分享图片生成的历史bug出发,详解LayoutInflater和View.post的工作原理
  • java 递归地复制文件夹及其所有子文件夹和文件
  • LeetCode-栈-每日温度
  • 《Discuz! X3.5开发从入门到生态共建》第1章 Discuz! 的前世今生-优雅草卓伊凡
  • 界面控件DevExpress WinForms v24.2新版亮点:富文本编辑器功能全新升级
  • Java五种方法批量处理List元素全解
  • 【操作系统】内核态、用户态
  • [Python] 避免 PyPDF2 写入 PDF 出现黑框问题:基于语言自动匹配系统字体的解决方案
  • CS144 - LAB0
  • 文本编辑器vi的使用
  • SECS/GEM协议中Report ID、SV ID、CE ID与S2F33/S2F35/S2F37指令的关系及配置示例
  • 专业库室联管联控系统|门禁联管联控系统
  • Browser-use快速了解
  • 流光溢彩的数字长河:Linux基础IO,文件系统的诗意漫游
  • Google Play的最新安全变更可能会让一些高级用户无法使用App
  • 函数抓取图片microsoft excel与wps的区别
  • 【n-grams】基于统计方法的语言模型
  • 深入理解设计模式之中介者模式
  • 基于Springboot + vue3实现的图书管理系统
  • 【Mysql开启慢查询日志】
  • 泰迪杯特等奖案例深度解析:基于联邦时空图卷积网络的跨区域碳排放协同预测与优化系统