数据库(三):行锁和表锁,共享锁和排他锁,数据库引擎MyISAM和InnoDB,乐观锁和悲观锁

news2024/11/16 22:22:49

文章目录

  • 前言
  • 零、数据库引擎
  • 一、封锁粒度
  • 二、行锁
  • 三、表锁
  • 四、数据库中的属性锁
    • 4.2. 意向锁
  • 五、乐观锁和悲观锁
  • 总结


前言

之前我们提到了数据库的隔离性可能会出现的若干问题,以及数据库为了解决这些问题而提出来的若干种隔离级别。实际上,数据库底层实现这些隔离级别的原理本质上就是通过各种封锁。今天我们在这里总结一下两种封锁粒度。

零、数据库引擎

其实mysql中的引擎有很多种类,其中InnoDB和MyISAM引擎最常用

在mysql5.5版本前默认使用MyISAM引擎,之后使用InnoDB引擎

MyISAM 操作数据都是使用的表锁,你更新一条记录就要锁整个表,导致性能较低,并发不高。当然同时它也不会存在死锁问题。

而 InnoDB 与 MyISAM 的最大不同有两点:一是 InnoDB 支持事务;二是 InnoDB 采用了行级锁。

在 Mysql 中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql 语句操作了主键索引,Mysql 就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。

InnoDB 行锁是通过给索引项加锁实现的,如果没有索引,InnoDB 会通过隐藏的聚簇索引来对记录加锁。也就是说:如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。因为没有了索引,找到某一条记录就得扫描全表,要扫描全表,就得锁定表。

一、封锁粒度

mysql中提供了两种封锁粒度:行级锁和表级锁。

我们在使用的过程中应该尽量只锁定需要修改的那部分数据,而不是所有的资源。锁定的数据量越少,发生锁争用的可能性就越小,系统的并发程度就越好。

但是加锁需要消耗资源,锁的各种操作(包括获取锁,释放锁以及检查锁状态)都会增加系统开销。因此封锁粒度越小,系统开销越大。 在选择封锁粒度的时候需要在锁开销和并发程度之间做出一个权衡。

两者之间的区别如下:

  • 表级锁: 粒度最大 的一种锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。但触发锁冲突的概率最高,并发度最低

  • 行级锁: 粒度最小 的一种锁,只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。并发度高,但加锁的开销也最大,加锁慢,会出现死锁。

其实除了可以分为表级锁和行级锁,锁还可以被划分为其他类型,具体如下图所示:

请添加图片描述
请添加图片描述

二、行锁

行锁就是一锁锁一行或者多行,mysql的行锁是基于索引家在的,所以行锁是要加载在索引响应的行上(比如当你更新表中的索引字段的时候会自动响应行锁)。当我们使用行锁锁定了数据库中某个表的某些记录的时候,当其他事务访问数据库中的该表,被锁定的记录不能被访问,其他的记录都可以访问到。

行锁的特点是锁冲突概率低,并发性高,但是会出现死锁的情况。

三、表锁

顾名思义,表锁就是一锁锁一整张表,在表被锁定的期间,其他事务不能对该表进行任何操作,必须等当前表的表锁被释放后才能进行操作。表锁响应的是非索引字段(比如你在更新表中的非索引字段的时候会自动调用表锁),即全表扫描,全表扫描时锁定整张表。

由于表锁每次都是锁一整张表,所以表锁的锁冲突几率特别高,表锁大大降低了出现死锁的情况

四、数据库中的属性锁

属性锁可以分为两类,共享锁和排他锁。

  • 排他锁(互斥锁),简写为X锁,又称之为写锁,简称X锁,当事务对数据加上写锁后,其他事务既不能对该数据添加读写,也不能对该数据添加写锁,写锁与其他锁都是互斥的。只有当前数据写锁被释放后,其他事务才能对其添加写锁或者是读锁。写锁主要是为了解决在修改数据时,不允许其他事务对当前数据进行修改和读取操作,从而可以有效避免”脏读”问题和“丢失修改”问题的产生。

  • 共享锁,简写为S锁,又称为读锁,简称S锁,当事务对数据加上读锁后,其他事务只能对该数据加读锁,不能做任何修改操作,也就是不能添加写锁。只有当数据上的读锁被释放后,其他事务才能对其添加写锁。共享锁主要是为了支持并发的读取数据而出现的,读取数据时,不允许其他事务对当前数据进行修改操作,从而避免”不可重读”的问题的出现。

数据库的增删改操作默认都会加排他锁,而查询不会加任何锁

当然,我们也可以手动使用共享锁和排他锁,如下列代码所示:


//共享锁
select * from 表名 lock in share mode
 
//排他锁
select * from 表名 for update

锁的兼容关系如下:
请添加图片描述

4.2. 意向锁

使用意向锁可以更容易地支持多粒度封锁。

在存在行级锁和表级锁的情况下,事务T如果想要对表A加上锁,就需要先检测是否有其他事务对表A或者表A中的任意一行加锁,如果一行一行去检查就显得非常沙雕且耗时,且效率极低,这个时候我们只需要检测意向锁是否被占用就行。

意向锁在原来的X/S锁的基础上引入了IX/IS,IX/IS都是表锁。有以下两个规定:

  • 一个事务在获得某一个数据行对象的S锁之前,必须先获得表的IS锁或者更强的锁
  • 一个事务在获得某一个数据行对象的X锁之前,必须首先获得表的IX锁。

通过引入意向锁,事务T想要对表A加X锁,只需要先检验是否有其他事务对表A加上了X/IX/S/IS锁,如果有就表示有其它事务正在使用这个表或者表中某一行的锁,因此事务 T 加 X 锁失败。

各种锁的兼容关系如下:

请添加图片描述

五、乐观锁和悲观锁

  • 乐观锁和悲观锁都是针对select而言的
    比如在商品抢购中,用户购买后库存需要减1,而很多用户同时购买时,读出来的库存数量一样,然后多个用户同时用该库存去减1。

  • 这种做法必然会出现很大的漏洞,如果向在淘宝,京东出现这种情况,你就可以打包回家种地了

  • 这种情况如何解决呢,其实可以使用悲观锁进行解决,说白了也就是排他锁。用户进来查库存的时候,就加上排他锁,等他所有操作完成后,再释放排他锁,让其他人进来
    不让用户等待,就可以使用乐观锁方式解决,乐观锁一般靠表的设计和时间戳来实现
    一般是在表中添加version或者timestamp时间戳字段

  • 这样就会保证如果更新失败,就表示有其他程序更新了数据库,就可以通过重试解决
    update table set num=num-1 where id=10 and version=12


总结

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

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

相关文章

代码随想录算法训练营第二十七天|● 39. 组合总和 ● 40.组合总和II ● 131.分割回文串

39. 组合总和 看完题后的思路 本题本质上还是一个传统排列题,不同之处在于每个元素可以重复选取。void f(【】,startIndex,sum)递归终止 if(和target){ 加入; 返回; }递…

HTTPS为什么就安全了?我们做了什么?

目录 一 安全概念 二 HTTPS的安全措施 三 总结 一 安全概念 网络安全是一个比较笼统的概念。我们说网络安全的时候,往往会包含很多安全问题,包括网络设备层面、通信过程、数据本身等多方面引入的安全问题。比如设备被有意无意的破坏,链路…

微搭低代码从入门到精通-03 创建模型应用

我们在进行低代码开发的时候,第一个需要建立的概念就是应用。不管你开发的是小程序还是管理系统,最终的承载物就是应用。 而我们创建应用是一共可以创建两种类型的应用,自定义应用和模型应用。自定义应用对应着一页多端,你开发一…

【Hello Linux】 Linux的权限以及Shell原理

作者:小萌新 专栏:Linux 作者简介:大二学生 希望能和大家一起进步! 本篇博客简介:介绍Linux的基础命令 Linux的权限以及Shell原理Shell的运行原理权限Linux中权限的概念如何切换用户如何提升当前操作的权限如何添加信任…

【C++:STL之栈和队列 | 模拟实现 | 优先级队列 】

目录 1. stack的介绍和使用 1.1 stack的介绍 1.2 stack的使用 2 栈的模拟实现 3 queue的介绍和使用 3.1 queue的介绍 3.2 queue的使用 4 queue的模拟实现 5 deque的介绍 5.1deque的原理介绍 5.2 deque的缺陷 5.3 为什么选择deque作为stack和queue的底层默认容器 6 p…

nodejs+vue+elementui在线求助系统vscode

目 录 摘 要 1 前 言 3 第1章 概述 4 1.1 研究背景 4 1.2 研究目的 4 1.3 研究内容 4 第二章 开发技术介绍 5 前端技术:nodejsvueelementui,视图层其实质就是vue页面,通过编写vue页面从而展示在浏览器中,编写完成的vue页面要能够和控制器类进…

加载sklearn covtype数据集出错 fetch_covtype() HTTPError: HTTP Error 403: Forbidden解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…

微搭低代码从入门到精通07-基础布局组件

低码开发不同于传统开发,传统开发我们通常需要编写前端代码和后端代码。前端代码由HTML、CSS和JavaScript组成,后端代码我们通常要用后端语言比如Java来编写接口。 低码开发的特点是可视化开发,在编辑器中通过组件的拖拽来完成页面的编制。如…

莽村李青都看得懂的Vue响应式原理

Vue响应式原理八股文序违背老祖宗的决定将Vue响应式原理公众于世响应式数据(Observe篇)dom更新(Wacther篇)依赖收集八股文序 开篇来一段大家都会背诵的八股文。 某面试官: 请你简要介绍一下Vue的响应式原理。 答&am…

leaflet 读取上传的wkt文件,转换为geojson文件(示例代码056)

第056个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中上传WKT文件,解析wtk文件并转换为geojson,并在地图上显示图片。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式本示例所用的a.wkt示例源代码(共139行)…

AirServer在哪下载?如何免费使用教程

苹果手机投屏到电脑mac是怎么弄?你知道多少?相信大家对苹果手机投屏到电脑mac能在电脑上操作不是很了解,下面就让coco玛奇朵带大家一起了解一下教程。AIrServer是一款ios投屏到mac的专用软件,可将iOS上的音频,视频&…

make的使用及Makefile万能模板

make的使用及Makefile万能模板前言为什么用makemake的使用Makefile万能模板前言 gcc 的编译,是将源码生成可执行程序。 例如: gcc hello.c -o hello源码到可执行程序需要四步处理 硬件——》机器语言——》汇编语言——》 高级语言 1)预处理…

【openGauss实战8】Schema的图文解读

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…

Session与Cookie的区别(三)

中场休息 让我们先从比喻回到网络世界里,HTTP 是无状态的,所以每一个 Request 都是不相关的,就像是对小明来说每一位客人都是新的客人一样,他根本不知道谁是谁。 既然你没办法把他们关联,就代表状态这件事情也不存在。…

微搭低代码从入门到精通08-轮播容器

我们上一篇讲解了基础布局组件,讲解了普通容器和文本组件的用法,本篇我们继续介绍布局组件。 小程序中经常会有个功能是轮播图展示的功能,多张图片可以顺序进行切换。我们学习使用轮播容器的时候,先考虑切换的图片从哪来&#xf…

视频连载09 - 这个为生信学习和生信作图打造的开源R教程真香!!!

点击阅读原文跳转完整教案。1 思考题2 R基础2.1 R安装2.2 Rstudio基础2.2.1 Rstudio版本2.2.2 Rstudio安装2.2.3 Rstudio 使用2.3 R基本语法2.3.1 获取帮助文档,查看命令或函数的使用方法、事例或适用范围2.3.2 R中的变量及其初始化2.3.3 变量类型和转换2.3.4 R中矩…

Python-项目实战--贪吃蛇小游戏(1)

1.贪吃蛇游戏规则贪吃蛇游戏规则如下:1.1开始和结束贪吃蛇初始出现在游戏窗口的左上角位置,体长共有3节游戏过程中,一旦蛇头撞到了窗口的边缘或者身体的其他部位,游戏结束游戏过程中,点击游戏窗口的关闭按钮,或者按下ESC键可以直接退出游戏一…

Java高级-常用类-String、Date、Compare、Other

本篇讲解java常用类 String类 String:字符串,使用一对""引起来表示。 String类被声明为final的,不可被继承。 String实现了Serializable接口:表示字符串是支持序列化的。 ​ 实现了Comparable接口:表示String可以比较…

微搭低代码从入门到精通09-数据容器

我们已经用了两篇的篇幅介绍了微搭的布局组件,包括普通容器、文本、图片、轮播容器。 微搭中还有粗粒度的组件,今天介绍的数据容器就是粗粒度的组件。所谓粗粒度的组件,一般包括基础组件、样式还有默认的事件。数据容器一共包含三种分别是数…

vscode sftp从linux服务器下载文件至本地:No such file or dictionary【已解决】

在服务器跑完程序需要下载数据的时候报错: [warn] ENOENT: no such file or directory, open /home/LIST_2080Ti/.ssh/config load /home/LIST_2080Ti/.ssh/config failed 完整报错内容如下: [02-10 08:38:47] [info] config at /home/LIST_2080Ti {&q…