【MySQL】锁

一、并发事务访问相同记录的三种情况

  • 读-读情况
      并发事务相继读取相同的记录,不会产生什么问题。

  • 写-写情况
      这种情况下会发生脏写的问题。

  • 读-写或写-读情况
      会发生脏读、不可重复读、幻读的情况

并发问题的解决方案

  • 读操作利用多版本并发控制,写操作进行加锁
  • 读写操作都采用加锁的方式

二、锁的不同分类

2.1、从数据操作角度分:读锁、写锁

  • 读锁共享锁,用S表示,对于同一份数据的读操作可以同时进行不影响,相互不阻塞。
  • 写锁排他锁,用X表示,在当前写操作没有完成前,它会阻断其他写锁和读锁。

锁定读时对读取记录加S锁

SELECT ... LOCK IN SHARE MODE;
#或者
SELECT ... FOR SHARE;

锁定读时对读取记录加X锁

SELECT ... FOR UPDATE;

2.2、从数据操作粒度分:表级锁、页级锁、行锁

  锁粒度是由于数据库系统需要在高并发响应和系统性能两方面进行平衡所产生的概念。

2.2.1、表锁

  该锁会锁定整张表,开销最小且避免了死锁,但是并发效率大打折扣。

表级别的S锁、X锁

  • LOCK TABLES t READInnoDB引擎对表t添加表级别的S锁
  • LOCK TABLES t WRITEInnoDB引擎对表t添加表级别的X锁

  在InnoDB上使用这些语句只会降低并发能力,所以一般不使用。

意向锁
  在一个事务在设置行锁的时候其他事务就需要去遍历这张表的每行是否存在锁。所以通过在表上设置意向锁,从而避免其他事务的逐行检查。

  • 意向共享锁:如果事务想要获得数据表中某些记录的共享锁,就需要在数据表上添加意向共享锁
SELECT column FROM table ... LOCK IN SHARE MODE;
  • 意向共享锁:如果事务想要获得数据表中某些记录的排他锁,就需要在数据表上添加意向排他锁
SELECT column FROM table ... FOR UPDATE;

  总的来说,意向锁是一种不与行锁冲突的表级锁,它是为了协调行锁和表锁的关系。支持多粒度的锁并存。

自增锁
  自增锁时当向使用含有AUTO_INCREMENT列的表中插入数据时需要获取的一种特殊的表级锁。一个事务在持有自增锁的过程中,其他事务的插入语句都要被阻塞。

2.2.2、行锁

  • 优点:发生锁冲突概率低,并发度高。
  • 缺点:锁的开销比较大,加锁慢,容易出现死锁。

记录锁
  记录锁仅仅把一条数据锁上,其分为S型记录锁X型记录锁

  • 当一个事务获取了一条记录的S型记录锁后,其他事物可以继续获取该记录的S型记录锁,但不能获取X型记录锁
  • 当一个事务获取了一条记录的X型记录锁后,其他事务不能获取该记录的S型和X型记录锁

间隙锁
  在不可重复读的隔离级别下,MySQL可以采用加间隙锁的方式解决幻读问题。间隙锁仅仅是为了防止插入幻影记录而提出的。
请添加图片描述
  如果在id=8的记录上加上间隙锁,那么在该事务提交之前不允许id在(3,8)之间的记录被插入。使用方法为:

SELECT * FROM student WHERE id=5 LOCK IN SHARE MODE;
# 或者
SELECT * FROM student WHERE id=5 FOR UPDATE;

  因为表里没有id=5的记录,所以两条语句的间隙锁都加在id=8上,这里两条语句都是为了保护(3, 8)这个区间的间隙锁,这两条语句相互之间不会有冲突。

如果要对最前面的记录和最后面的记录加上间隙锁,则需要使用两条伪记录:

  • Infimum记录,表示该页面中最小的记录
  • Supremum记录,表示该页面中最大的记录

  在这两条记录上设置间隙锁就可以达到不允许id小于1或者大于20的记录被插入。如果要在(20, + ∞ \infty )上不允许记录插入,则需要

SELECT * FROM student WHERE id>20 LOCK IN SHARE MODE;

临键锁
  临键锁本质是一个记录锁间隙锁,相当于在间隙锁上加了一个等号。

SELECT * FROM student WHERE id <= 8 AND id > 3 FOR UPDATE;

插入意向锁
  插入意向锁是由INSERT操作产生的一种间隙锁,是由于INSERT操作获取锁失败而开始等待产生的,是行级锁并不是表级锁

  • 插入意向锁是一种特殊的间隙锁,可以锁定开区间内的部分记录。
  • 插入意向锁之间互不排斥。

2.2.3、页锁

  页锁开销介于表锁和行锁之间,会出现死锁。锁定粒度介于表锁和行锁之间,并发度一般。

2.3、从对待锁的态度划分:乐观锁、悲观锁

悲观锁
  悲观锁主要保证了数据的排他性,在事务查询数据的时候会认为该事务会修改数据从而上锁,从而影响阻塞别的事务。

  SELECT ... FOR UPDATE是MySQL的悲观锁,它在执行过程中所有扫描的行都会被锁上,因此在MySQL中用悲观锁必须确定使用索引,而不是全表扫描,否则整个表都会被锁上。

  悲观锁的不足在于其依靠数据库的锁机制来实现,对数据库性能开销较大。

乐观锁
  乐观锁不采用数据库自身的锁机制,而是通过程序来实现。其适用于多读的应用类型来提高吞吐量。如果写操作过多则还是需要使用悲观锁。实现方式有版本号机制和CAS机制。

  • 版本号机制
      在表中设置版本字段version,第一次读的时候获取version字段,对数据进行更新和删除时,会执行UPDATE ... SET version=version+1 WHERE version=version。这就是通过对版本进行控制,从而避免了读写操作的相互干扰,即类似于git的思想。

  • 时间戳机制
      与版本号类似,把version换成了时间戳

  • CAS机制
      java中的java.util.concurrent.atomic包下的原子变量类就是使用了乐观锁的CAS机制实现的。

两种锁的适用场景

  • 乐观锁:适合读操作多,写操作少的场景。优点在于程序实现,不存在死锁的问题,但是阻止不了除了程序以外的数据库操作
  • 悲观锁:适合写操作多的场景。可以在数据库层面阻止其他事务对该数据的操作权限,防止读-写写-写的冲突。

2.4、按加锁的方式分:显式锁、隐式锁

隐式锁
  隐式锁的逻辑如下:

  • InnoDB的每条记录中都有一个隐含的trx_id字段,这个字段存在于聚簇索引的B+Tree中。
  • 在操作记录前,首先根据记录中的trx_id检查该事务是否是活动的事务。如果是活动的事务,首先将隐式锁转换为显式锁。
  • 检查是否有锁冲突,有冲突就创建锁并设置为waiting状态。如果没有冲突就不加锁,并且直接跳到下下步。
  • 等待加锁成功,被唤醒或者超时
  • 写数据,并将自己的trx_id写入trx_id字段。

显示锁
  即通过特定语句加锁。
  显式加共享锁:

SELECT ... LOCK IN SHARE MODE

  显式加排他锁

SELECT ... FOR UPDATE

2.5、全局锁

  全局锁是对整个数据库实例加锁,使得整个数据库处在只读状态。全局锁的典型使用场景是:做全库逻辑备份。

F1ush tables with read lock

2.6、死锁

  两个事务都持有对方需要的锁,并且在等待对方释放,并且双方都不会释放自己的锁。

2.6.1、死锁的必要条件

  死锁的关键在于两个事务的上锁顺序不一致

  • 存在两个及以上的事务
  • 每个事务都已经持有锁并且申请新的锁
  • 锁资源同时只能被一个事务持有或者不兼容
  • 事务之间因为持有锁和申请锁导致彼此循环等待。

2.6.2、死锁处理方法

  • 等待直到超时
      可以通过设置事务等待时间的阈值,但是缺点在于有可能会使得正常等待的事务由于超时而退出。

  • 使用死锁检测进行死锁处理
      innodb提供了wait-for graph算法来检测死锁。算法要求保存所得信息链表和事务等待链表两个信息,并基于这两个信息绘制等待图

在这里插入图片描述
  得到下图
在这里插入图片描述
  这里与操作系统的死锁检测方法类似。

2.6.3、死锁避免

  • 合理设置索引,使业务SQL尽可能通过索引定位更少的行,减少锁竞争
  • 调整业务逻辑SQL执行顺序,避免update/delete长时间持有锁的SQL在事务前面。
  • 避免大事务,将大事务拆分为小事务缩短锁定资源的时间,减少发生锁冲突的几率。
  • 在并发高的系统中,不要显式加锁,特别是在事务里显示加锁。
  • 降低隔离级别,避免掉由于gap锁导致的死锁。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java的ArrayList类

ArrayList<E>E是自定义数据类型 ArrayList类&#xff1a; 构造函数&#xff1a; 成员方法&#xff1a; public boolean add(E e)&#xff1a; 将指定元素加到集合末尾 Appends the specified element to the end of this list. public class Array {public static…

动听的洗牌游戏(Java篇ArrayList实操)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

LeetCode - 存在重复元素

219. 存在重复元素 II 这道题可以用两个方法解决。 哈希表 从左到右遍历数组&#xff0c;并将数组的下标存到hash中&#xff0c;在遍历数字的过程中&#xff0c;如果hash中不存在nums[i]&#xff0c;将nums[i]加入到hash当中&#xff0c;若存在&#xff0c;则判断下标之间的关…

C#事件实例详解

一、什么是事件&#xff1f; 在C#中,事件(event)是一种特殊的类成员,它允许类或对象通知其他类或对象发生了某些事情。 从语法上看,事件的声明类似于字段,但它们在功能和行为上有一些重要的区别。 从技术角度来说,事件实际上是一个封装了事件订阅和取消订阅功能的委托字段。…

Python中的数据类型有四类八种如何理解?

在Python中&#xff0c;数据类型大致可以分为四大类&#xff0c;包含了八种基本的数据类型&#xff0c;这些分类有助于理解和使用Python进行编程。这四大类分别是&#xff1a; 数字类型 (Numeric Types): 整型 (int): 表示没有小数部分的整数&#xff0c;可以是正数、负数或零。…

海外媒体发稿:9种高效的媒体套餐内容发稿策略分析-华媒舍

海外媒体发稿&#xff1a;9种高效的媒体套餐内容发稿策略分析高效的媒体发布和营销推广策略对公司、本人的成就尤为重要。下面我们就对于媒体套餐内容发稿营销推广策略开展全面解析&#xff0c;帮助读者掌握并应用这9种合理的思路&#xff0c;进而获得更好的媒体营销效果。 1.媒…

Retelling|Facebook2

录音 Facebook 2 Retelling|Facebook2 复述转写 Hi, Im Helen Campbell, from DJ interpretation, European Commission, Im going to talk about Facebook. You Im sure that you are more familiar with Facebook, a lot, a lot more familiar than I than me. But Ive read…

C语言例4-19:求一元二次方程的解

求一元二次方程的解。 代码如下&#xff1a; //求一元二次方程的解 #include<stdio.h> #include<math.h> int main(void) {float a,b,c,d,x1,x2,p,q;printf("a,b,c?\n");scanf("%f,%f,%f",&a,&b,&c);printf("方程 ");…

智能楼宇3D可视化解决方案

什么是智能楼宇? 智能楼宇是为提高楼宇的使用合理性与效率,配置合适的建筑环境系统与楼宇自动化系统、办公自动化与管理信息系统以及先进的通信系统,并通过结构化综合布线系统集成为智能化系统的大楼。 面临的问题 信息孤岛,无法统一管理 各个子系统独立工作、独立管理,…

每天上万简历,录取不到1%!阿里腾讯的 offer 都给了哪些人?

三月天杨柳醉春烟~正是求职好时节~ 与去年秋招的冷淡不同&#xff0c;今年春招市场放宽了许多&#xff0c;不少企业纷纷抛出橄榄枝&#xff0c;各大厂的只差把“缺人”两个字写在脸上了。 字节跳动技术方向开放数10个类型岗位&#xff0c;研发需求占比60%&#xff0c;非研发新增…

redis关联和非关联

1.1.2.关联和非关联 传统数据库的表与表之间往往存在关联&#xff0c;例如外键&#xff1a; 而非关系型数据库不存在关联关系&#xff0c;要维护关系要么靠代码中的业务逻辑&#xff0c;要么靠数据之间的耦合&#xff1a; {id: 1,name: "张三",orders: [{id: 1,ite…

算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1)

&#x1f495;"我们好像在池塘的水底&#xff0c;从一个月亮走向另一个月亮。"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;算法系列–动态规划–⼦数组、⼦串系列&#xff08;数组中连续的⼀段&#xff09;(1) 大家好,今天为大家带来的是算法系…

PPP实验

PPP实验 一.实验思路 1.对接口进行配置IP 2.将R2上面的两个serial接口与R3的两个接口进行链路聚合&#xff0c;然后配置IP 3.在R2&#xff08;验证方&#xff09;上配置PPP chap协议 4.在R1上配置验证用户名 5.要使R3和R2能进行双向chap验证&#xff0c;要在R3上配置ppp chap协…

软件设计师19--文件管理

软件设计师19--文件管理 考点1&#xff1a;文件相关概念例题&#xff1a; 考点2&#xff1a;树形目录结构&#xff08;绝对路径与相对路径&#xff09;例题&#xff1a; 考点3&#xff1a;位示图例题&#xff1a; 考点4&#xff1a;索引文件索引文件结构例题&#xff1a; 考点1…

背包DP模板

01背包 01背包-1 #include <bits/stdc.h> using namespace std;const int N 1e5 10; int n, m, f[N][N], v[N], w[N];int main() {cin >> n >> m;for (int i 1; i < n; i) {cin >> v[i] >> w[i];}for (int i 1; i < n; i) {for (int…

安装element ui失败,解决版本冲突问题

解决方法 降低npm的版本 npm install -g npm6.14.8 不用回退 命令&#xff1a;npm install --legacy-peer-deps element-ui --save

【C++】手撕哈希表的闭散列和开散列

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;手撕哈希表的闭散列和开散列 > 毒鸡汤&#xff1a;谁不是一边受伤&#xff0c;一边学会坚强。 > 专栏选自&#xff1a;C嘎嘎进阶 > 望小伙伴们…

后端代码1

// 新增 public JsonResultVo<?> create(ApiIgnore RequestAttribute(ConstVal.REQ_USER) BaseUser baseUser,RequestBody IUTradeBuyPreserveVo iuTradeBuyPreserveVo) {//权限判断if (!baseCompanyService.dataPermission(baseUser, iuTradeBuyPreserveVo.getCompanyi…

wma怎么转换成mp3?无损转换!

WMA&#xff08;Windows Media Audio&#xff09;文件格式诞生于微软公司的数字音频技术研发。由于其高压缩性能和较好的音质&#xff0c;在推出初期主要用于Windows Media Player等微软产品。然而&#xff0c;随着MP3格式的盛行&#xff0c;WMA的使用范围逐渐受到限制。 MP3文…