mysql中的行锁(代码片段)

程序员超时空 程序员超时空     2022-12-07     213

关键词:

1、行锁分类

  • 1、记录锁:即锁住记录本身

  • 2、间隙锁:锁住一段没有记录的间隙,可以是两条记录的中间部分,也可以是第一条记录的前置部分或最后一条记录的后续部分

    • 2.1 需要注意的是,间隙锁仅仅是阻塞对该间隙进行插入操作,而不阻塞对该间隙的查询操作;如有表tab,有索引idx,对(5,10)加入间隙锁,执行下面两条命令:
    • insert into tab (idx) values(7); 阻塞
    • select * from tab where idx = 7 for update; 不阻塞但无数据
  • 3、next-key锁:是记录锁与间隙锁的结合,特点为左开右闭,如(4,10],由间隙锁(4,10)和记录锁idx = 10组成

2、唯一索引的加锁规则

  1. 等值查询:
  • 若查询记录存在则将next-key锁退化成记录锁,只锁住查询的记录;
  • 若查询记录不存在,则next-key锁退化为间隙锁,锁住记录所在空隙,此处空隙是指与所查询记录(如果存在的话)相邻的两条记录之间的空隙,这两条记录除了可以是数据库表中实际存在的,也可以是其他记录拟插入的(执行了插入sql但是未提交或回滚事务,因为其他事务的插入操作加了记录锁,故而将间隙分为两半)
  • 第二种情况中,若其他事务拟插入的数据进行了提交,则间隙锁固定,若选择回滚,则间隙扩大至下一条记录之前
  1. 范围查询:有以下两种情况,以下的范围内指截至是最后一条符合条件的记录后的间隙
  • >和<:若起始索引记录不存在,则锁住起始索引所在间隙及后续记录和间隙;若存在,则从起始索引记录(不包含)开始,锁住范围内的记录和间隙

  • >=:若起始索引不存在,则锁住起始索引记录所在间隙以及后续记录和间隙,若存在,则从起始索引记录(包含)开始,锁住范围内所有的记录和间隙

  • <=:若起始索引不存在,则锁住起始索引所在间隙与后续的记录和间隙,若存在,则从起始索引记录开始,锁住范围内记录和间隙,并锁住起始索引另一侧的间隙,验证如下:

      如下表:表名为foo,uid为主键索引,也即唯一索引,idx为普通索引
      +-----+-----+------+
      | uid | age | idx  |
      +-----+-----+------+
      |   1 |   1 |    1 |
      |   3 |   3 |    3 |
      |   4 |   4 |    4 |
      |  10 |  10 |   10 |
      |  16 |  16 |   16 |
      +-----+-----+------+
      
      事务A:执行select * from foo where uid >= 10 and uid <= 16 for update;
      事务B:执行insert into foo values(9,9,9);
      事务C:执行update foo set age = 5 where uid = 4;
      事务D:执行insert into foo values(17,17,17);
      其中事务B和C成功执行,事务D阻塞,分析可得[16, 正无穷)被锁住,而[4,10)未被锁住
      
      若是事务A修改为:select * from foo where uid >= 10 and uid < 16 for update;
      则事务D不会被阻塞,也即(16,正无穷)未被锁住
    

3、普通索引的加锁规则

  • 等值查询:若查询记录存在,除了加上next-key锁(即锁住本记录和上一条记录之间的间隙)以外,还会对本记录到下一条记录之间的间隙加锁
  • 范围查询:与唯一索引的区别在于:
    1、>=会将另一侧的间隙也一起锁住;
    2、<会将锁住第一条不满足条件的记录
    如事务A执行:select * from foo where idx>= 10 and idx < 12 for update;
    其中idx为普通索引,按照上表,(4,10)之间会加上间隙锁,且16会被锁住,也即[10,16]锁住

4、行锁的加锁技巧

事务加锁时,其他事务进行写操作时会受到阻塞,这个阻塞时间当然是越短越好,那么对于一个事务当中不同需要加锁的语句,可以采用以下方式控制:

  • 对语句所需要锁住的记录条数进行预估,在不影响业务的情况下,将锁住记录多的语句排在锁住记录少的后面,锁粒度大的容易发生冲突,这样安排可以减少与其他事务冲突时间
  • 将热点记录的加锁操作排在事务后面执行
  • 批量操作分几次进行,减少锁冲突的概率和时间

举个两个简单例子,来自MySQL实战45讲
1、用户A、B要到影院C购票,需要进行以下操作:

  • 用户金额扣除,票数+1
  • 影院金额增加,票数-1

分析业务,容易得出影院的记录是热点记录,相较用户记录更改频繁,因此可以将影院操作语句放在事务后面,减少影院记录上锁时间

2、删除一个表中的前10000条数据,给出三种方案,那种最合适

  • delete from table limit 10000;
  • 开启20个连接,执行delete from table limit 500;
  • 同一连接连续开启20次事务,执行delete from table limit 500;

答案是第三种,原因如下

  • 第一个需要锁住一次性锁住10000记录,范围大,容易发生冲突,且删除期间这10000条记录会被锁住,其他事务被阻塞概率大;
  • 第二个多个连接之间可能发生冲突,互相阻塞,浪费资源;
  • 第三个只有一个连接,每次加锁的记录少,不容易发生冲突;

先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

day871.行锁-mysql实战(代码片段)

...c;我是阿昌,今天学习记录的是关于行锁的内容。MySQL的行锁是在引擎层由各个引擎自己实现的。但并不是所有的引擎都支持行锁,比如MyISAM引擎就不支持行锁。不支持行锁意味着并发控制只能使用表锁,对于这种引... 查看详情

mysql原理篇之锁--14(代码片段)

...ds)共享锁和独占锁锁定读的语句写操作多粒度锁MySQL中的行锁和表锁其他存储引擎中的锁InnoDB存储引擎中的锁InnoDB中的表级锁InnoDB中的行级锁InnoDB锁的内存结构解决并发事务带来问题的两种基本 查看详情

从头开始搞懂mysql(05)行锁表锁全局锁(代码片段)

1、行锁行锁是针对数据表中行记录的锁,MySQL的行锁是在引擎层实现的,并不是所有的引擎都支持行锁,比如MyISAM就不支持,InnoDB支持行锁,避免了并发控制时使用表锁1.1两阶段锁在InnoDB事务中,行锁是在... 查看详情

面试题2:mysql的行锁

mysql的锁是由具体的存储引擎实现的。InnoDB支持行锁和事务Mysql有三种级别的锁定:表级锁定、页级锁定、行级锁定  查看详情

跑了4个实验,实战讲解mysql的行锁间隙锁...(代码片段)

微信搜索【微观技术】,关注这个不喜欢内卷的程序员。精彩文章汇总GitHubhttps://github.com/aalansehaiyang/technology-talk,Star12K,汇总java生态圈常用技术框架、开源中间件,系统架构、数据库、大公司架构案例、常用三... 查看详情

mysql中的锁(表锁行锁)(代码片段)

 锁是计算机协调多个进程或纯线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有... 查看详情

mysql中的锁:表mdl意向锁行锁(代码片段)

元数据锁SHARE_READ/EXCLUSIVE:共享锁:在DQL/DML的时候给表加SHARE_READ/WRITE锁,与排它锁互斥作用:在A事务未提交的情况下,B事务不能修改表结构排他锁:在DDL的时候给表加EXCLUSIVE锁,与共享/排他锁都互斥。作用:修改表结构的时... 查看详情

mysql——锁(代码片段)

....1、行级锁/行锁2.2、表级锁/表锁2.3、表锁的划分三、MySQL中的行锁和表锁3.1、其他存储引擎中的锁3.2、InnoDB存储引擎中的锁3.2.1、InnoDB中的表级锁3.2.1.1、S锁、X锁3.2.1.2、IS锁、IX锁3.2.1.3、AUTO-INC锁3.2.2、InnoDB中的行级锁3.2.2.1、Recor... 查看详情

mysql——锁(代码片段)

....1、行级锁/行锁2.2、表级锁/表锁2.3、表锁的划分三、MySQL中的行锁和表锁3.1、其他存储引擎中的锁3.2、InnoDB存储引擎中的锁3.2.1、InnoDB中的表级锁3.2.1.1、S锁、X锁3.2.1.2、IS锁、IX锁3.2.1.3、AUTO-INC锁3.2.2、InnoDB中的行级锁3.2.2.1、Recor... 查看详情

mysql行锁等待异常

...含性能较差的查询SQL事务中存在慢查询,导致同一个事务中的其他DML无法及时释放占用的行锁,引起行锁等待。3.单个事务中包含大量SQL通常是由于在事务代码中加入for循环导致,虽然单个SQL运行很快,但是SQL数量一大,事务就... 查看详情

mysql的行锁

...时看完了MySQL的全局锁、表级锁还有行锁和间隙锁。其中的行锁和间隙锁迟迟无法理解,最近趁着有空再次阅读了一遍,并且对照了《深入浅出MySQL》,发现对MySQL锁的理解又上了一个台阶,今天就来分享一下MySQL... 查看详情

关于数据库行锁与表锁的认识(代码片段)

...查询这一条记录却是可以的也就是说虽然这一条记录所在的行被锁定了,但是并不影响我们正常的查询,当然了针对这一行的DML操作也是无效的那如果我们对除了cardid=‘1’的其他行操作会怎样呢?对于其他的行DML是完全... 查看详情

java如何实现对mysql数据库的行锁

场景如下:  用户账户有余额,当发生交易时,需要实时更新余额。这里如果发生并发问题,那么会造成用户余额和实际交易的不一致,这对公司和客户来说都是很危险的。那么如何避免:  网上查了下,有以下两... 查看详情

mysql锁--02---行锁(记录锁(recordlocks))(代码片段)

...leslike'tx_isolation';MySQL-行锁InnoDB实现了以下两种类型的行锁。**共享锁(S)**:**排他锁(X)**:InnoDB加锁规则==对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加写锁(排它锁x锁)&... 查看详情

mysql死锁(代码片段)

MySql死锁一、什么是死锁InnoDB存储引擎定义了四种类型的行锁隔离等级对加锁的影响当前数据对加锁的影响二、为什么会形成死锁两阶段锁协议产生死锁的四个必要条件三、MySQL如何处理死锁?杀死进程MySQL表间隙锁排他锁共... 查看详情

mysql死锁(代码片段)

MySql死锁一、什么是死锁InnoDB存储引擎定义了四种类型的行锁隔离等级对加锁的影响当前数据对加锁的影响二、为什么会形成死锁两阶段锁协议产生死锁的四个必要条件三、MySQL如何处理死锁?杀死进程MySQL表间隙锁排他锁共... 查看详情

解释 AWR 报告中的行锁争用

】解释AWR报告中的行锁争用【英文标题】:InterpretingRowLockContentioninAWRReport【发布时间】:2018-11-2819:03:45【问题描述】:我的AWR报告显示如下:EventWaitsTotalWaitTime(s)enq:TX-rowlockcontention3010,69410,694代表时钟时间吗?或者它是否代表在A... 查看详情

mysql中innodb引擎的行锁是通过加在啥上完成

...ert一条主键值为1的数据,由于事务A首先获取了主键值为1的行锁,导致事务B因无法获取行锁而产生等待,等到事务A提交后,事务B才获取该行锁,完成提交。这里强调的是行锁的概念,虽然事务B重复插入了主键,但是在获取行... 查看详情