在上篇中,我们介绍了MySQL中的全局锁和表锁。

今天,我们专注于介绍一下行锁,这个在日常开发和面试中常常困扰我们的问题。

1.行锁基础

由于全局锁和表锁对增删改查的性能都会有较大影响,所以,我们自然会想到,

只需要对有修改的行加锁就行了,这就是行锁。

在事务中,事务1更新了一行主键为1的数据行,那么,在这个事务释放锁之前,事务2是不能操作的。

另外,有一个很多人容易混淆的概念,就是行锁什么时候释放?

搞清这个事情,需要了解什么叫作 两阶段锁。

什么是两阶段锁呢?举个例子你就明白了。

这里事务2执行后会是什么结果呢?

如果你明白了两阶段锁的含义,你就会知道,事务2的updat语句会阻塞,直到事务1提交以后才能继续执行。

所以,这里再次强调一下,两阶段锁的含义。

在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是语句执行完了了就立刻释放, 而是要等到事务结束时才释放。

注意,除了update语句能加写锁外,另外,还有一种对select语句加写锁的方式,就是

当前读:Select …. for update

2.行锁进阶

2.1 什么是幻读

面试的时候,面试官经常会喜欢问数据库的事务隔离级别。

大家要能回答出四种隔离级别,四种隔离级别的含义。

再多问一点,会问你什么是脏读,什么是幻读,哪个隔离级别会解决什么问题。

首先明确一下,什么是幻读?

同样是一个事务,在事务中前后两次查询,出现了不同的结果。

不同之处在于,脏读是针对update,也就是同一行的数据出现了不一致。

注意,幻读出现的场景

第一:事务的隔离级别为可重复读,且是当前读

第二:幻读仅专指新插入的行,在范围查询中,后一次查询出现了新的数据行。

2.2 怎么解决幻读

这些如果你都能答上,面试官可能会继续追问,幻读是怎么产生的,又是怎么被解决的。

即使我们给所有update涉及的行都加上了行锁,还是无法解决新插入的记录,因为这些记录原本不存在,自然无法加上行锁。

那怎么办呢?为了解决这个问题,innodb只好引入新的锁,间隙锁(Gap Lock)。

“间隙锁,锁的是两个值之间的空隙”。

举个例子:

在四条记录,ID=0,10,20,30中,会产生如下的五个间隙范围

间隙锁就是对这五个间隙范围加锁,防止新的记录插入。

注意,行锁的冲突是行与行之间的冲突,是行锁与行锁之间的。与间隙锁冲突的是往“间隙中插入数据”这个操作,间隙锁本身不会产生冲突。

间隙锁和行锁合称为next-key lock。

每个next-key lock是前开后闭的。间隙锁本身是前开后开的。

小tips

标准的事务隔离级别中,可重复读只解决脏读问题,无法解决幻读问题。但是在innodb中,用next-key lock解决了幻读的问题。

3.关于行锁的优化应用

3.1 两阶段锁的优化应用

上面的基础知识中,解释了什么是 两阶段锁。

那么,对我们业务开发中有什么借鉴意义呢?

既然我们知道了,行锁必须在整个事务完全提交后才会释放,那么,如果我们的事物中需要锁住多行,就要把最可能造成锁冲突,或者是锁住最多行的语句尽可能地往后放。

举个例子,小A在线上购买了商家B的一个产品,这个购买的动作可以简化为3个操作:

1)小A的银行账户余额扣款x;

2)商家B的银行账户余额增加x;

3)添加一条交易记录;

这里,涉及到两个update操作,和一个insert操作。为了保证交易的原子性,将三个动作放在了一个事务中。

那怎么安排三个语句的先后顺序呢?如果不仔细考虑,那么就可能是随意选个123或者213的顺序了。

仔细想想呢?

显然,这里最容易造成冲突的是步骤2),可能同时有多个用户购买商家B的产品,然后需要给商家B的余额做update操作。

另外,步骤3)是insert操作,最不容易出现锁冲突。

所以,最好的步骤顺序是3)-> 1) -> 2),将最容易产生冲突的操作放在最后执行,那么会比2)->1) ->3)的顺序,大大提高并发度。

3.2 间隙锁的问题与优化

间隙锁的引入也带来了一些新的问题,比如:降低并发度,可能导致死锁。

因为间隙锁的引入,可能会导致同样的语句锁住了更大的范围。

那怎么办呢?

注意,间隙锁在可重复读级别下才是有效的。

所以,只要我们的业务不需要可重复读的保证,我们就可以把隔离级别设置为读提交(也是阿里云rds数据库的默认隔离级别),就没有间隙锁了。

然后,为了解决可能的数据和日志不一致的问题,需要把binlog格式设置为row。

读提交级别 + binlog的row格式,也是一般公司数据库的标准配置。

现在,你知道原因了吧:)

参考:

丁奇《MySQL 实战45讲》

看到这里了,原创不易,点个关注、点个赞吧,你最好看了~

知识碎片重新梳理,构建Java知识图谱:https://github.com/saigu/JavaKnowledgeGraph(历史文章查阅非常方便)

扫码关注我的公众号“阿丸笔记”,第一时间获取最新更新。同时可以免费获取海量Java技术栈电子书、各个大厂面试题。

前阿里数据库专家总结的MySQL里的各种锁(下篇)的更多相关文章

  1. 前阿里数据库专家总结的MySQL里的各种锁(上篇)

    0.前言 MySQL按照加锁的范围,分为全局锁.表级锁.行级锁. 本文作为上篇,主要介绍MySQL的全局锁 和 表级锁. 重要的实战总结为,如何安全地变更一个表的表结构. 1.全局锁 定义: 全局锁就 ...

  2. 数据库性能测试---前阿里数据库团队资深DBA杨奇龙

    杨奇龙 前阿里数据库团队资深DBA 主要负责淘宝业务线,经历多次11.11,有海量业务访问DB架构设计经验. 目前就职于有赞科技DBA,负责数据库运维工作,熟悉MySQL 性能优化,故障诊断,性能压测 ...

  3. MySQL里面的锁

    MySQL里面的锁可以分为:全局锁,表级锁,行级锁. 一.全局锁:对整个数据库实例加锁.MySQL提供加全局读锁的方法:Flush tables with read lock(FTWRL)这个命令可以 ...

  4. 重新定义数据库的时刻,阿里云数据库专家带你了解POLARDB

    摘要:POLARDB是阿里云ApsaraDB数据库团队研发的基于云计算架构的下一代关系型数据库,其最大的特色是计算节点与存储节点分离,借助优秀的RDMA网络以及最新的块存储技术.POLARDB不但满足 ...

  5. 重新学习MySQL数据库10:MySQL里的那些日志们

    重新学习MySQL数据库10:MySQL里的那些日志们 同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分.MySQL有几种不同的日志文件,通常包括错误日志文件,二进制日志,通用日志, ...

  6. jdbc连接阿里云服务器上的MySQL数据库 及 数据库IP限制

    问题1:Jdbc 如何连接阿里云服务器上的MySQL数据库? 解决: 上截图: 其中IP是阿里云服务器的公网IP地址. 问题2:   刚开始接手开发的时候,使用Navicat连接阿里云服务器上的数据后 ...

  7. mysql里的数据库引擎, 编码格式

    针对数据库里即使设置了varchar类型的字段, 值输入中文报错的情况,是因为数据库的默认编码类型不支持汉字输入. utf-8 可以编译全球通用的所有语言符号. 由1-6个可变字节组成,有非常严格的排 ...

  8. 使用Navicat连接阿里云服务器上的MySQL数据库=======Linux 开放 /etc/hosts.allow

    使用Navicat连接阿里云服务器上的MySQL数据库   1.首先打开Navicat,文件>新建连接> 2,两张连接方法 1>常规中输入数据库的主机名,端口,用户名,密码 这种直接 ...

  9. 云栖神侠传—阿里云数据库专家德歌告诉你PostgreSQL的那些事

    什么是云栖神侠传: 云栖社区(http://yq.aliyun.com/?utm_source=yqdg),是阿里云面向开发者群体的开放型社区.在云栖社区中,活跃着许多阿里技术大牛,他们在自己的技术领 ...

随机推荐

  1. Java复习(三)类中的方法

    3.1方法的控制流程 与C/C++类似 3.2异常处理 Java处理错误的方法 抛出(throw)异常 在方法的运行过程中,如果发生了异常,则该方法生成一个代表该异常的代码并把它交给运行时系统,运行时 ...

  2. PyTorch基础——预测共享单车的使用量

    预处理实验数据 读取数据 下载数据 网盘链接:https://pan.baidu.com/s/1n_FtZjAswWR9rfuI6GtDhA 提取码:y4fb #导入需要使用的库 import num ...

  3. LootCode-链表排序-Java

    链表排序 0.来源 来源:力扣(LeetCode) 题目链接:https://leetcode-cn.com/problems/sort-list 1.题目描述 在 O(n log n) 时间复杂度和 ...

  4. surprise库使用

    自动交叉使用法 #-*- coding:utf-8 -*- from surprise import SVD from surprise import Dataset from surprise.mo ...

  5. 初试vue

    Vue了解 """ vue框架 vue是前台框架:Angular.React.Vue vue:结合其他框架优点.轻量级.中文API.数据驱动.双向绑定.MVVM设计模式. ...

  6. android翻译应用、地图轨迹、视频广告、React Native知乎日报、网络请求框架等源码

    Android精选源码 android实现高德地图轨迹效果源码 使用React Native(Android和iOS)实现的 知乎日报效果源码 一款整合百度翻译api跟有道翻译api的翻译君 RxEa ...

  7. java实现银行管理系统

    Bank类 package First; import java.util.TreeSet; //银行类public class Bank {        private String Bankna ...

  8. 吴裕雄--天生自然python学习笔记:Python3 命名空间和作用域

    命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的. 命名空间提供了在项目中避免名字冲突的一种方法.各个命名空间是独立的,没有任何关系的,所以一个 ...

  9. linux系统下rpm包的安装、删除、效验、查询

    详细课程 使用 RPM RPM 有五个基本的操作 模式(不包括包的编译): 安装,卸载,升级,查询,校验.本节将对它们一一介绍.要了解完整的细节和选项,可以使用 rpm --help, 或转到 the ...

  10. Java 原子类 java.util.concurrent.atomic

    Java 原子类 java.util.concurrent.atomic 1.i++为什么是非线程安全的 i++其实是分为3个步骤:获取i的值, 把i+1, 把i+1的结果赋给i 如果多线程执行i++ ...