第15章_锁: (表级锁、页级锁、行锁、悲观锁、乐观锁)

news2024/9/24 19:21:14

3.2 从数据操作的粒度划分:表级锁、页级锁、行锁

为了提高数据库并发度,每次锁定的数据范围越小越好,理论上每次只锁定当前操作的数据的方案会得到最大的并发度,但管理锁是很耗资源(涉及获取、检查、释放锁等动作)。因此数据库系统需要在高并发响应系统性能两方面进行平衡,这样就产生了“锁粒度(Lock granularity)”的概念。
对一条记录加锁影响的也只是这条记录而已,我们就说这个锁的粒度比较细;其实一个事务也可以在表级别进行加锁,自然就被称之为表级锁或者表锁,对一个表加锁影响整个表中的记录,我们就说这个锁的粒度比较粗。锁的粒度主要分为表级锁、页级锁和行锁。

1. 表锁(Table Lock

该锁会锁定整张表,它是MysQL中最基本的锁策略,并不依赖于存储引擎(不管你是MysQL的什么存储引擎对于表锁的策略都是一样的),并且表锁是开销最小的策略(因为粒度比较大)。由于表级锁一次会将整个表锁定,所以可以很好的避免死锁问题。当然,锁的粒度大所带来最大的负面影响就是出现锁资源争用的概率也会最高,导致并发率大打折扣

  ① 表级别的S锁、X锁 

在对某个表执行 SELECT INSERT DELETE UPDATE 语句时, InnoDB 存储引擎是不会为这个表添加表级别的 S 或者 X 的。在对某个表执行一些诸如 alter table drop table  这类的 DDL 语句时,其他事务对这个表并发执行诸如select insert delete update的语句会发生阻塞。同理,某个事务中对某个表执行select insert delete update 语句时,在其他会话中对这个表执行 DDL 语句也会发生阻塞。这个过程其实是通过在 server 使用一种称之为 元数据锁 (英文名: Metadata Locks ,简称 MDL )结构来实现的(总之就是宁可用元数据锁也不用表级别的S 锁、X锁)。
innodb只会在一些特殊情况下,比方说 崩溃恢复 过程中用到。在系统变量 autocommit=0 innodb_table_locks = 1 时, 手动 获取InnoDB存储引擎提供的表 t S 或者 X 可以这么写:
lock tables t read  InnoDB 会对表 t 加表级别的 S 锁 
lock tables t write  InnoDB 会对表 t 加表级别的 X 锁 
不过尽量避免在使用 InnoDB 存储引擎的表上使用 LOCK TABLES 这样的手动锁表语句,它们并不会提供什么额外的保护,只是会降低并发能力而已。InnoDB 的厉害之处还是实现了更细粒度的 行锁 ,关于 InnoDB表级别的 S X 大家了解一下就可以了。
总结 : 
MyISAM 在执行查询语句(select)前, 会给涉及的所有表加读锁, 在执行增删改操作前, 会给涉及的表加写锁, InnoDB 存储引擎是不会为这个表添加表级锁的 读锁 写锁 的(因为InnoDB实现了行锁)

  ② 意向锁 (intention lock

InnoDB 支持 多粒度锁( multiple granularity locking ,它允许 行级锁 表级锁 共存,而 意向
就是其中的一种 表锁
1. 意向锁的存在是为了协调行锁和表锁的关系, 支持多粒度(表锁与行锁)的锁并存
2. 意向锁是一种不与行级锁冲突的表级锁, 这点非常重要
3. 表明某个事务正在某些行持有了锁或该事务准备去持有锁 
意向锁分为两种:
     ① 意向共享锁 intention shared lock, IS ):事务有意向对表中的某些行加 共享锁 S 锁)
-- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。
SELECT column FROM table ... LOCK IN SHARE MODE;

     ②意向排他锁intention exclusive lock, IX):事务有意向对表中的某些行加排他锁X锁)

-- 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。
SELECT column FROM table ... FOR UPDATE;

即:意向锁是由存储引擎 自己维护的 ,用户无法手动操作意向锁,在为数据行加共享 / 排他锁之前, InooDB 会先获取该数据行 所在数据表的对应意向锁

1. 意向锁要解决的问题
现在有两个事务,分别是T1和T2,其中T2试图在该表级别上应用共享或排它锁,如果没有意向锁存在,那么T2就需要去检查各个页或行是否存在锁;如果存在意向锁,那么此时就会受到由T1控制的 表级别意向锁的阻塞 。T2在锁定该表前不必检查各个页或行锁,而只需检查表上的意向锁。简单来说就是给更大一级别的空间示意里面是否已经上过锁。

在数据表的场景中, 如果我们给某一行数据加上了排它锁,数据库会自动给更大一级的空间,比如数据页或数据表加上意向锁,告诉其他人这个数据页或数据表已经有人上过排它锁了 ,这样当其他人想要获取数据表排它锁的时候,只需要了解是否有人已经获取了这个数据表的意向排他锁即可。
 
如果事务想要获得数据表中某些记录的共享锁,就需要在数据表上添加 意向共享锁
如果事务想要获得数据表中某些记录的排他锁,就需要在数据表上添加 意向排他锁
这时,意向锁会告诉其他事务已经有人锁定了表中的某些记录。
举例:
 
因为共享锁与排他锁互斥,所以事务B在试图对teacher表加共享锁的时候,必须保证两个条件。
(1)当前没有其他事务持有teacher表的排他锁
(2)当前没有其他事务持有teacher表中任意一行的排他锁。

为了检测是否满足第二个条件,事务B必须在确保teacher表不存在任何排他锁的前提下,去检测表中的每一行是否存在排他锁。 很明显这是一个效率很差的做法,但是有了意向锁之后,情况就不一样了。
意向锁是怎么解决这个问题的呢?首先,我们需要知道意向锁之间的兼容互斥性,如下所示。

意向锁之间是互相兼容的(虽然是表级的,但描述的是行级上锁情况),虽然意向锁和自家兄弟互相兼容,但是它会与普通的排他/共享锁互斥。
注意这里的排他/共享锁指的都是表锁, 意向锁不会与行级的共享/排他锁互斥。回到刚才teacher 表的例子。
 
意向锁的并发性

意向锁不会与行级的共享 / 排他锁互斥!正因为如此,意向锁并不会影响到多个事务对不同数据行加排 他锁时的并发性。(不然我们直接用普通的表锁就行了)

我们扩展一下上面 teacher 表的例子来概括一下意向锁的作用(一条数据从被锁定到被释放的过程中,可 能存在多种不同锁,但是这里我们只着重表现意向锁)。
从上面的案例可以得到如下结论:
1. InnoDB 支持 多粒度锁 ,特定场景下,行级锁可以与表级锁共存
2. 意向锁之间互不排斥,但除了 IS S 兼容外, 意向锁会与 共享锁 / 排他锁 互斥
3. IX IS 是表级锁,不会和行级的 X S 锁发生冲突。只会和表级的 X S 发生冲突。
4. 意向锁在保证并发性的前提下,实现了 行锁和表锁共存 满足事务隔离性 的要求。

③ 元数据锁(MDL锁) 

MySQL5.5 引入了 meta data lock ,简称 MDL 锁,属于表锁范畴。 MDL 的作用是,保证读写的正确性。比 如,如果一个查询正在遍历一个表中的数据,而执行期间另一个线程对这个 表结构做变更 ,增加了一列,那么查询线程拿到的结果跟表结构对不上,肯定是不行的。
因此, 当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 锁。
读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性,解决了DML和DDL操作之间的一致性问题。 不需要显式使用 ,在访问一个表的时候会被自动加上。

2. InnoDB中的行锁 

行锁(Row Lock)也称为记录锁,顾名思义,就是锁住某一行(某条记录row)。需要的注意的是,MySQL服务器层并没有实现行锁机制,行级锁只在存储引擎层实现。
优点:锁定力度小,发生锁冲突概率低,可以实现的并发度高。

缺点:对于锁的开销比较大,加锁会比较慢,容易出现死锁情况。


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

先建立student表

① 记录锁(Record Locks

记录锁也就是仅仅把一条记录锁上,官方的类型名称为: LOCK_REC_NOT_GAP 。比如我们把 id 值为 8 的那条记录加一个记录锁的示意图如图所示。仅仅是锁住了id 值为8的记录,对周围的数据没有影响。
举例如下:
记录锁是有 S 锁和 X 锁之分的,称之为 S 型记录锁 X 型记录锁
  • 当一个事务获取了一条记录的S型记录锁后,其他事务也可以继续获取该记录的S型记录锁,但不可 以继续获取X型记录锁;
  • 当一个事务获取了一条记录的X型记录锁后,其他事务既不可以继续获取该记录的S型记录锁,也不可以继续获取X型记录锁。

② 间隙锁(Gap Locks

MySQL REPEATABLE READ 隔离级别下是可以解决幻读问题的,解决方案有两种,可以使用 MVCC 方案解决,也可以采用 加锁 方案解决。但是在使用加锁方案解决时有个大问题,就是事务在第一次执行读取操作时,那些幻影记录尚不存在,我们无法给这些 幻影记录 加上 记录锁 InnoDB 提出了一种称之为 Gap Locks 的锁,官方的类型名称为: LOCK_GAP ,我们可以简称为 gap 。比如,把 id 值为 8 的那条记录加一个gap 锁的示意图如下。

 

图中 id 值为 8 的记录加了 gap 锁,意味着 不允许别的事务在 id 值为 8 的记录前边的间隙插入新记录 ,其实就是id列的值 (3, 8) 这个区间的新记录是不允许立即插入的。比如,有另外一个事务再想插入一条 id 值为 4 的新记录,它定位到该条新记录的下一条记录的id 值为 8 ,而这条记录上又有一个 gap 锁,所以就会阻塞插入操作,直到拥有这个gap 锁的事务提交了之后, id 列的值在区间 (3, 8) 中的新记录才可以被插入。
gap 锁的提出仅仅是为了防止插入幻影记录而提出的
间隙锁的引入,可能会导致同样的语句锁住更大的范围, 这其实是影响了并发度的, 下面的例子会产生死锁
  1. session 1 执行select ... for update 语句, 由于id = 5 这一行并不存在, 因此会加上间隙锁(3,8) 
  2. session 2 执行select ... for update 语句, 同样加上间隙锁(3,8), 间隙锁之间不会冲突, 因此这个语句可以执行成功
  3. session 2 试图插入一行, 被session 1 的间隙锁挡住,进入等待
  4. session 1 视图插入一行, 被session 2 的间隙锁挡住, 两个session进入死锁

③ 临键锁(Next-Key Locks

记录锁 + 间隙锁

④ 插入意向锁(Insert Intention Locks

我们说一个事务在 插入 一条记录时需要判断一下插入位置是不是被别的事务加了 gap next - key 也包含 gap ),如果有的话,插入操作需要等待,直到拥有 gap 的那个事务提交。但是 InnoDB 定事务在等待的时候也需要在内存中生成一个锁结构 ,表明有事务想在某个 间隙 插入 新记录,但是 现在在等待。InnoDB 就把这种类型的锁命名为 Insert Intention Locks ,官方的类型名称为: LOCK_INSERT_INTENTION ,我们称为 插入意向锁 。插入意向锁是一种 Gap ,不是意向锁,在 insert操作时产生。

插入意向锁是在插入一条记录行前,由INSERT操作产生的一种间隙锁。该锁用以表示插入意向,
当多个事务在同一区间(gap)插入位置不同的多条数据时,事务之间不需要互相等待。假设存在两条值分别为4和7的记录,两个不同的事务分别试图插入值为5和6的两条记录,每个事务在获取插入行上独占的(排他)锁前,都会获取(4,7)之间的间隙锁,但是因为数据行之间并
不冲突,所以两个事务之间并不会产生冲突(阻塞等待)。
总结来说,插入意向锁的特性可以分成两部分:

  1. 插入意向锁是一种特殊的间隙锁—―间隙锁可以锁定开区间内的部分记录。
  2. 插入意向锁之间互不排斥,所以即使多个事务在同一区间插入多条记录,只要记录本身(主键、唯一索引)不冲突,那么事务之间就不会出现冲突等待。

注意,虽然插入意向锁中含有意向锁三个字,但是它并不属于意向锁而属于间隙锁,因为意向锁是表锁而插入意向锁是行锁
比如,把id值为8的那条记录加一个插入意向锁的示意图如下:
比如, 现在T1为id值为8 的记录加了一个gap锁, 然后T2 和 T3 分别想向student表中插入id值分别为4,5的两条记录, 所以现在为id值为8的记录加的锁的示意图就如下所示:

从图中可以看到,由于T1持有gap锁,所以T2和T3需要生成一个插入意向锁的锁结构并且处于等待状态。当T1提交后会把它获取到的锁都释放掉,这样T2和T3就能获取到对应的插入意向锁了(本质上就是把插入意向锁对应锁结构的is_waiting属性改为false),T2和T3之间也并不会相互阻塞,它们可以同时获取到id值为8的插入意向锁,然后执行插入操作。事实上插入意向锁并不会阻止别的事务继续获取该记录上任何类型的锁。

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

从对待锁的态度来看锁的话,可以将锁分成乐观锁和悲观锁,从名字中也可以看出这两种锁是两种看待
数据并发的思维方式 。需要注意的是,乐观锁和悲观锁并不是锁,而是锁的 设计思想

1. 悲观锁(Pessimistic Locking

悲观锁是一种思想,顾名思义,就是很悲观,对数据被其他事务的修改持保守态度,会通过数据库自身的锁机制来实现,从而保证数据操作的排它性。
悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 阻塞 直到它拿到锁( 共享资源每次只给一个线程使用,其它线程阻塞, 用完后再把资源转让给其它线程 )。比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁,当其他线程想要访问数据时,都需要阻塞挂起。Java synchronized ReentrantLock 等独占锁就是悲观锁思想的实现。

2. 乐观锁(Optimistic Locking

乐观锁认为对同一数据的并发操作不会总发生,属于小概率事件,不用每次都对数据上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,也就是 不采用数据库自身的锁机制,而是通过 程序来实现 。在程序上,我们可以采用 版本号机制 或者 CAS 机制 实现。 乐观锁适用于多读的应用类型, 这样可以提高吞吐量 。在 Java java.util.concurrent.atomic 包下的原子变量类就是使用了乐观锁 的一种实现方式: CAS 实现的。

1. 乐观锁的版本号机制

在表中设计一个 版本字段 version ,第一次读的时候,会获取 version 字段的取值。然后对数据进行更新或删除操作时,会执行 UPDATE ... SET version=version+1 WHERE version=version 。此时如果已经有事务对这条数据进行了更改,修改就不会成功。

2. 乐观锁的时间戳机制

时间戳和版本号机制一样,也是在更新提交的时候,将当前数据的时间戳和更新之前取得的时间戳进行比较,如果两者一致则更新成功,否则就是版本冲突。
你能看到乐观锁就是程序员自己控制数据并发操作的权限,基本是通过给数据行增加一个戳(版本号或者时间戳),从而证明当前拿到的数据是否最新。

3. 两种锁的适用场景

从这两种锁的设计思想中,我们总结一下乐观锁和悲观锁的适用场景:
  1. 乐观锁 适合 读操作多 的场景,相对来说写的操作比较少。它的优点在于 程序实现 不存在死锁 问题,不过适用场景也会相对乐观,因为它阻止不了除了程序以外的数据库操作。
  2. 悲观锁 适合 写操作多 的场景,因为写的操作具有 排它性 。采用悲观锁的方式,可以在数据库层面阻止其他事务对该数据的操作权限,防止 - - 的冲突。

 

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

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

相关文章

服务器数据恢复-Xen server虚拟机数据恢复案例

服务器数据恢复环境: 一台某品牌服务器通过一张同品牌某型号RAID卡将4块STAT硬盘组建为一组RAID10阵列。上层部署Xen Server虚拟化平台,虚拟机上安装的是Windows Server操作系统,包括系统盘 数据盘两个虚拟机磁盘,作为Web服务器使…

JavaScript个人笔记

1.常用数据布尔值判断 const data [,0,-1,null,undefined,[],{},()>{}]data.forEach(item>{if(item){console.log(item,结果)} 打印结果:、0、null、undefined这四个值的布尔值都是false,其余都是true

没钱,没人,没经验?传统制造型企业如何用无代码实现转型

2023年,国家市场监督管理总局发布了三项重要标准,包括《工业互联网平台选型要求》、《工业互联网平台微服务参考框架》和《工业互联网平台开放应用编程接口功能要求》。这些标准的发布对于完善工业互联网平台标准体系,提升多样化工业互联网平…

如何查找遥感卫星相关参数

背景介绍 做遥感卫星筛选和数据处理时,我们经常需要查询遥感卫星的参数,比如说传感器类型、分辨率、轨道参数和幅宽等。 但如果只用百度,搜索的结果要不没有卫星参数,要不就是卫星相关的新闻,有用的一部分是技术博客&…

JS中call方法是什么,call()的原理是什么?如何手写一个call()?Symbol是什么,怎么用Symbol调优?含详细解析

🎉call() 💕call()的参数 thisArg:在调用 func 时要使用的 this 值 arg1, …, argN (可选) 函数的参数 ✨call()的描述: 首先声明 func是一个函数,person是一个对象 针对这段代码:f…

SSL证书系列--DV、OV、EV三种证书类型的区别

原文网址:SSL证书系列--DV、OV、EV三种证书类型的区别_IT利刃出鞘的博客-CSDN博客 简介 本文介绍DV、OV、EV这三种SSL证书的区别。 DV、OV、EV的区别 项 DV OV EV 英文全称 Domain Validation (域名验证型证书) Organization Valida…

前端的规范

假如团队中的小伙伴在提交代码时没有遵循规范要求,只写了一个"fix"或"update,这会给其他小伙伴造成困扰,不得不花时间查看代码和推测逻辑。 不仅会浪费了时间和精力,可能会导致项目以下问题: 可读性差…

知网被网信办罚款5000万

我是卢松松,点点上面的头像,欢迎关注我哦! 9月6日,知网被网信办罚款5000万,对此,知网称,诚恳接受,坚决服从。 去年(2022年)知网被市场监管总局以垄断行为对其开出了8760万元的罚单…

zabbix监控网络设备和zabbix proxy代理

使用snmp监控linux主机 #在被监控端安装SNMP协议 [rootrocky8 conf]# yum -y install net-snmp 修改配置 vim /etc/snmp/snmpd.conf com2sec notConfigUser default 123456 ##修改此行,设置团体密码,默认为public,此处 改为123456 view systemview included .1. ##添加此行,自…

微信小程序中识别html标签的方法

rich-text组件 在微信小程序中有一个组件rich-text可以识别文本节点或是元素节点 具体入下: //需要识别的数据放在data中,然后放在nodes属性中即可 <rich-text nodes"{{data}}"></rich-text>详情可以参考官方文档:https://developers.weixin.qq.com/mi…

软件测试/测试开发丨跨平台 api 对接 学习笔记

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27139 跨平台 api 对接 测试平台需求 稳定 功能 调用脚本报告获取分布式支持 API 调用 开源 Jenkins 环境准备 Jenkins 满足所有调度平台的需求 需…

如何让自己的精力集中 Maven自学笔记 马云演讲观看

目录 如何让自己的精力集中 Avoid having multiple tasks and objects in your line of sight 人的脑袋是给自己思考用的 晚上床上想千条路&#xff0c;早上起床还是走原路 参与才会变得更好 共度灾难&#xff0c;是需要互相鼓励的 CFO Capital 上海各区都有哪些大学?…

晨启,MSP430开发板,51开发板,原理图,PCB图

下载&#xff1a;https://github.com/xddun/blog_code_search

纯手工总结超详细关于计算机网络的五层知识点,看看你都掌握了没

纯手工总结超详细关于计算机网络的五层知识点&#xff0c;看看你都掌握了没 文章目录 纯手工总结超详细关于计算机网络的五层知识点&#xff0c;看看你都掌握了没1.应用层1.1 HTTP协议1.1.1 URL1.1.2 HTTP方法1.1.3 HTTP请求1.1.4 HTTP状态码1.1.5 HTTP会话保持 1.2 HTTPS协议 …

软考高级之系统架构师之计算机硬件基础与嵌入式系统

今日&#xff1a;2023年09月07日&#xff0c;离软考高级仅剩57天。 计算机硬件基础 计算机系统中的存储部件通常组织成层次结构&#xff0c;越接近CPU的存储部件访问速度越快。存储速度从快到慢分别是&#xff1a;寄存器组、Cache、内存、Flash。 计算机执行程序时&#xff…

【AI理论学习】语言模型:从Word Embedding到ELMo

语言模型&#xff1a;从Word Embedding到ELMo ELMo原理Bi-LM总结参考资料 本文主要介绍一种建立在LSTM基础上的ELMo预训练模型。2013年的Word2Vec及2014年的GloVe的工作中&#xff0c;每个词对应一个vector&#xff0c;对于多义词无能为力。ELMo的工作对于此&#xff0c;提出了…

视频讲解|3014 含分布式电源的配电网优化重构

目录 1 主要内容 2 讲解视频链接 3 部分程序 1 主要内容 该视频为程序目录中编号1034的讲解内容&#xff0c;该程序的链接为配电网优化重构matlab智能算法&#xff0c;本次重点讲解了基本环矩阵原理以及代码两步实现过程、如何利用基本环向量去创造可行解、粒子群优化过程、…

GeoNet: Unsupervised Learning of Dense Depth, Optical Flow and Camera Pose 论文阅读

论文信息 题目&#xff1a;GeoNet: Unsupervised Learning of Dense Depth, Optical Flow and Camera Pose 作者&#xff1a;Zhichao Yin and Jianping Shi 来源&#xff1a;CVPR 时间&#xff1a;2018 Abstract 我们提出了 GeoNet&#xff0c;这是一种联合无监督学习框架&a…

Kafka3.0.0版本——消费者(消费者组案例)

目录 一、消费者组案例1.1、案例需求1.2、案例代码1.2.1、消费者1代码1.2.2、消费者2代码1.2.3、消费者3代码1.2.4、生产者代码 1.3、测试 一、消费者组案例 1.1、案例需求 测试同一个主题的分区数据&#xff0c;只能由一个消费者组中的一个消费。如下图所示&#xff1a; 1…

[CISCN 2019华北Day1]Web1

文章目录 涉及知识点解题过程 涉及知识点 phar反序列化文件读取 解题过程 打开题目&#xff0c;注册用户为admin 进去发现有文件上传的功能&#xff0c;我们随便上传个图片 然后就有下载和删除两个功能 我们尝试抓包下载文件的功能 发现参数可控&#xff0c;我们尝试读取一下…