视频+图文串讲:MySQL 行锁、间隙锁、Next-Key-Lock、以及实现记录存在的话就更新,如果记录不存在的话就插入如何保证并发安全
导读
Hi,大家好!我是白日梦!本文是MySQL专题的第 27 篇。
下文还是白日梦以自导自演的方式,围绕“如何实现记录存在的话就更新,如果记录不存在的话就插入。”展开本话题。看看你能抗到第几问吧
换一种写作风格,自导自演面试现场!感觉这样还是比较有趣的,欢迎大家订阅我的MySQL专题,公众号首发!持续更新中~
点击阅读原文,有视频串讲、视频实战各种案例、格式也会好看一点哦~
点击阅读原文,有视频串讲、视频实战各种案例、格式也会好看一点哦~
点击阅读原文,有视频串讲、视频实战各种案例、格式也会好看一点哦~
欢迎关注白日梦,公众号首发!持续连载中
推荐阅读原文,可以看视频教程!
推荐阅读原文,可以看视频教程!
推荐阅读原文,可以看视频教程!
那我们继续,还是这道场景题:现在我的业务中有这样的需求:如果目标记录存在的话我就更新它,如果记录不存在的话我就插入。说说看你知道哪些实现方式吧!
这种方式。
// 伪代码user=User.FindById(1)if user == null{ user.Insert()}else{ user.Update()}
比如这样的例子:商品有上线和下线的状态,然后管理员可以在后台页面中修改商品的状态,比如代码这样写的:
// 伪代码,如果将状态置反if product.Status == “online”{ product.Status = "offline";}else{ product.Status = "online"; }
这时管理员A、B并发的去操作商品状态:
嗯,确实存在这种情况,不过我可以自定义FindById()中的sql语句,通过 select for update的方式,规避你在图画出来的风险。
比如自定义SQL,让 user = User.FindByID(1)函数执行的SQL为
select * from user where id = 1 for update;
直接select时会给id = 1的行添加一把读锁,现在我通过select for update检索,在读select时给id = 的行添加写锁。
那么当我在读取使用这行数据时,其他的人select for update
就会被阻塞,因为写锁之间彼此是互
斥的。最终也不会出现Update彼此覆盖的情况
哦?那你画一个时序图出来瞧瞧
嗯嗯,时序图大概长下面这样
嗯,乍一看你上面画的这个图是没问题的,但我有个问题:如果id = xx的行不存在呢?
嗯,所以我们不如分不同情况讨论一下。下面我列举不同场景,你画时序图怎样?
嗯嗯,好的!
嗯!首先我们知道了,select for update会尝试添加X锁,也就是写锁。
常见的写锁有这么几种:
1、record lock 给指定行记录添加锁
2、gap lock 间隙锁
3、next key lock
下面通过在不同条件下执行select for update sql,再观察实验结果,就能八九不离十的推测出for update的加锁情况。
实验一已知条件如下:
create table t(a int,b int,primary key(a),key(b));insert into t select 1,1;insert into t select 3,1;insert into t select 5,3;insert into t select 7,6;insert into t select 10,8;
select for update sql为:
select * from t where a= 5 for update;
提示:注意id=5的行已经存在了。
下面你画一下时序图吧
嗯嗯,时序图加锁情况如下:
嗯,那如果我们需要执行的sql如下:
select * from t where b = 3 for update;
注意b并不是唯一键,它只是一个普通索引哦!
你能画一下它的加锁时序图吗?
嗯嗯,时序图如下:
(最后一条Sql条件是 where a = 5,不是a=3)
还是使用这些数据
create table t(a int,b int,primary key(a),key(b));insert into t select 1,1;insert into t select 3,1;insert into t select 5,3;insert into t select 7,6;insert into t select 10,8;
假如我执行的sql是:
select * from t where a = 13 for update;
注意:
1、a=13的行并不存在哦!
2、a是唯一索引
你画一下它的时序图吧!
嗯呢,时序图如下:
还是使用这些数据
create table t(a int,b int,primary key(a),key(b));insert into t select 1,1;insert into t select 3,1;insert into t select 5,3;insert into t select 7,6;insert into t select 10,8;
假如我执行的sql是:
select * from t where a = 8 for update;
注意:
1、a=8的行并不存在哦!
2、a是唯一索引
你画一下它的时序图吧!
嗯嗯、如下:
对唯一索引来说,gap的上下都锁不住!
还是使用这些数据
create table t(a int,b int,primary key(a),key(b));insert into t select 1,1;insert into t select 3,1;insert into t select 5,3;insert into t select 7,6;insert into t select 10,8;
假如我执行的sql是:
select * from t where b = 5 for update;
注意:
1、b=5的行并不存在哦!
2、b是普通索引
你画一下它的时序图吧!
嗯嗯、如下。
对普通索引来说,gap锁会 锁上不锁下!
嗯,对的。回到我们一开始的主题:如果数据存在我们就update
数据不存在我们就insert的话题来看的话。
通过如下方案:
begin;select for update;# insert or update;commit;
是可以保证并发修改的安全性的....
嗯嗯、其实通过实验来看,确实是安全的。
小伙子可以的!整体感觉还不错。
欢迎关注我。不久会给你安排下一面
。
我没有问题了,你有什么想问我的吗?
暂时没有了,感谢大佬!
视频+图文串讲:MySQL 行锁、间隙锁、Next-Key-Lock、以及实现记录存在的话就更新,如果记录不存在的话就插入如何保证并发安全的更多相关文章
- 死锁问题分析(个人认为重点讲到了gap间隙锁,解决了我一些不明报死锁的问题)
线上某服务时不时报出如下异常(大约一天二十多次):“Deadlock found when trying to get lock;”. Oh, My God! 是死锁问题.尽管报错不多,对性能目前看来 ...
- (10)MySQL进阶篇SQL优化(InnoDB锁-间隙锁)
1.概述 当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁:对于键值在条件范围内但并不存在的记录,叫做"间隙(GAP)&quo ...
- 【Mysql】表锁 行锁 记录锁 间隙锁
Mysql中的锁 基于锁的属性分类:共享锁.排他锁. 基于锁的状态分类:意向共享锁.意向排它锁 根据锁的粒度分类:全局锁.页锁.表级锁.行锁(记录锁.间隙锁.和临键锁),实际上的锁就这些,上面两种分类 ...
- mysql 隔离级别与间隙锁等
数据库隔离级 SQL标准中DB隔离级别有: read uncommitted:可以读到其它transaction 未提交数据 read committed:可以读到其它transaction 已提交数 ...
- Mysql加锁过程详解(9)-innodb下的记录锁,间隙锁,next-key锁
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)
Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...
- 推荐:mysql锁 innodb下的记录锁,间隙锁,next-key锁
你需要知道的 之前我们介绍了排他锁,其实innodb下的记录锁(也叫行锁),间隙锁,next-key锁统统属于排他锁. 行锁 记录锁其实很好理解,对表中的记录加锁,叫做记录锁,简称行锁. 生活中的间隙 ...
- mysql间隙锁
什么是间隙锁(gap lock)? 间隙锁是一个在索引记录之间的间隙上的锁. 间隙锁的作用? 保证某个间隙内的数据在锁定情况下不会发生任何变化.比如我mysql默认隔离级别下的可重复读(RR). 当使 ...
- mysql幻读、MVCC、间隙锁、意向锁(IX\IS)
IO即性能 顺序主键写性能很高,由于B+树的结构,主键如果是顺序的,则磁盘页的数据会按顺序填充,减少数据移动,随机主键则可能由于记录移动产生很多io 查询二级索引时,会再根据主键id获取数据页,产生一 ...
随机推荐
- 设计模式(九)——装饰者模式(io源码分析)
1 星巴克咖啡订单项目(咖啡馆): 1) 咖啡种类/单品咖啡:Espresso(意大利浓咖啡).ShortBlack.LongBlack(美式咖啡).Decaf(无因咖啡) 2) 调料:Milk.So ...
- Codeforces Round #657 (Div. 2) B. Dubious Cyrpto(数论)
题目链接:https://codeforces.com/contest/1379/problem/B 题意 给出三个正整数 $l,r,m$,判断在区间 $[l,r]$ 内是否有 $a,b,c$ 满足存 ...
- Array Transformer UVA - 12003
题目:传送门 题意: 给你n个数,要进行m次操作 对于每次操作(l,r,v,p)代表:在区间[l,r]中有x(这个x是需要你自己找出来的)个数小于v,你需要把序列的第p个位置的值改成u∗k/(r−l ...
- OpenStack Train版-14.安装块存储服务cinder(存储节点)
安装cindoer块存储服务节点(存储节点192.168.0.40)使用默认的LVM卷方法,之后改为ceph存储 安装LVM软件包 [root@cinder01 ~]# yum install lvm ...
- OpenStack Train版-2.安装keystone身份认证服务
安装 keystone 认证 mysql -uroot create database keystone; grant all privileges on keystone.* to 'keyston ...
- Shell 元字符 & 变量
Shell 介绍 ## 什么是程序 程序就是一组数据和代码逻辑集合的文件 ## 什么是进程 进程是程序的运行过程,也可以说是操作系统干活的过程,因为是操作系统负责控制硬件来运行应用程序 ps:进程与进 ...
- codeforces 1076E Vasya and a Tree 【dfs+树状数组】
题目:戳这里 题意:给定有n个点的一棵树,顶点1为根.m次操作,每次都把以v为根,深度dep以内的子树中所有的顶点(包括v本身)加x.求出最后每个点的值为多少. 解题思路:考虑到每次都只对点及其子树操 ...
- Leetcode(4)-两个排序数组的中位数
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个有序数组的中位数.要求算法的时间复杂度为 O(log (m+n)) . 示例 1: nums1 = [1, 3] ...
- HDU 3681 Prison Break(状压DP + BFS)题解
题意:一张图,F是起点,Y是必须要到的点,D不能走,G可以充电.可以往四个方向走,每走一步花费一个电,走到G可以选择充满电或者不充,每个G只能充一次.问你走遍Y的最小初始点亮.number(G) + ...
- Vue3(四)从jQuery 转到 Vue工程化 的捷径
不会 webpack 还想学 vue 工程化开发 的福音 熟悉jQuery开发的,学习vue的简单使用是没用啥问题的,但是学习vue的工程化开发方式,往往会遇到各种问题,比如: webpack.nod ...