MySQL——深入数据库原理(事务及锁)

news2024/11/17 16:43:40

文章目录

    • 行级锁
      • 共享 (S) 锁
      • 排他 (X) 锁
      • 间隙锁
    • 表级锁
      • 意向锁
      • 自增锁
      • Lock Table/DDL
  • 事务
  • ACID 原则
    • 1. 原子性 A
    • 2. 一致性 C
    • 3. 隔离性 I
    • 4. 持久性 D
  • 隔离级别
    • 1. READ UNCOMMITTED(未提交读)
    • 2. READ COMMITTED(提交读)
    • 3. REPEATABLE READ(可重复读)
    • 4. SERIALIZABLE(可串行化)
  • MVCC原理
  • 小结

行级锁

InnoDB 实现标准的行级锁定,其中有两种类型的锁:共享(S)锁和排他(X)锁。

共享 (S) 锁

允许持有该锁的事务读取行。

如果事务 T1 持有 r 行上的共享 (S) 锁,则来自某个不同事务 T2 对 r 行上的锁的请求将按如下方式处理:

  • T2 对 S 锁的请求可以立即获得批准。结果,T1 和 T2 都持有 r 上的 S 锁。
  • T2 对 X 锁的请求无法立即获得批准。

排他 (X) 锁

允许持有该锁的事务更新或删除行。

如果事务 T1 持有行 r 上的独占 (X) 锁,则某个不同事务 T2 对 r 上任一类型的锁的请求不能立即被授予。相反,事务 T2 必须等待事务 T1 释放其对行 r 的锁定

间隙锁

是对索引记录之间间隙的锁定,或者对第一个索引记录之前或最后一个索引记录之后的间隙的锁定。在可重复读的事务级别中解决幻读的问题。

例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;防止其他事务将值 15 插入到列 t.c1 中,无论该列中是否已经存在任何此类值,因为范围中所有现有值之间的间隙已被锁定。

表级锁

意向锁

意向锁设置在表上,简化其他事务是否可以上锁,当某个操作需要拿某种锁的时候,先判断与表锁是否冲突,减少更细力度行上是否有冲突的锁。上锁之前先上意向锁,意向锁表明稍后要进行哪种类型的行锁

  1. 共享意向锁(IS): 表示事务打算在表中的各个行上设置共享锁。
  2. 排他意向锁(IX): 表示事务打算对表中的各个行上设置排它锁。

意向锁定协议如下:
在事务可以获取表中行的共享锁之前,它必须首先获取IS表上的锁或更强的锁。
在事务可以获取表中行的排他锁之前,它必须首先获取IX 表上的锁。

如果请求事务与现有锁兼容,则将锁授予该事务,但如果与现有锁冲突,则不会授予该锁。事务会等待,直到释放冲突的现有锁。如果锁请求与现有锁冲突并且由于会导致 死锁而无法被授予,则会发生错误。

意向锁不会阻止除全表请求之外的任何内容(例如,LOCK TABLES … WRITE)。意向锁的主要目的是表明有人正在锁定一行,或者将要锁定表中的一行
3. insert意向锁:insert操作设置间隙锁 (不重要)

自增锁

Lock Table/DDL

show engine innodb status;#判断当前数据库上边有哪些锁

在这里插入图片描述

事务

什么是事务? 事务就是将一组SQL语句作为一个工作单元以原子的进行处理,要么都成功,要么都失败。

银行应用是解释事务必要性的经典例子。假设一个银行的数据库有两张表:支票表(checking)和储蓄表(savings)。现在要从用户Jane的支票账户转移200美元到她的储蓄账户,那么需要至少三个步骤:
1.确保支票账户的余额高于200美元。
2.从支票账户的余额中减去200美元。
3.在储蓄账户的余额中增加200美元。
以上三步操作必须打包在一个事务中,以保证一旦其中任何一步失败,都能够回滚所有的操作。
·
下图为可能的事务相关的SQL语句:
在这里插入图片描述

ACID 原则

单纯的事务概念并不能保证我们业务的正常工作。试想一下,基于上面的银行应用如果数据库在执行第4条语句时崩溃了,会发生什么?天知道,客户可能会损失200美元。再假如,在执行到第3条语句和第4条语句之间时,另外一个进程要删除支票账户的所有余额会发生什么?结果可能是银行不知不觉白白给了Jane 200美元。在这一系列操作中,有更多的失败可能性。连接可能会断开、会超时,甚至数据库服务器在操作执行过程中会崩溃。这就是为什么存在高度复杂且缓慢的两阶段提交系统的典型原因:为了应对各种失败场景
除非系统通过严格的ACID测试,否则空谈事务的概念是不够的。ACID代表原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。一个确保数据安全的事务处理系统,必须满足这些密切相关的标准。

1. 原子性 A

一个事务必须被视为一个不可分割的工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚。对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。

要么全部完成,要么全部不完成

2. 一致性 C

数据库总是从一个一致性状态转换到下一个一致性状态。在前面的例子中,一致性确保了,即使在执行第3、4条语句之间时系统崩溃,支票账户中也不会损失200美元。两个账户的总额总是合理的,如果事务最终没有提交,该事务所做的任何修改都不会被保存到数据库中。在处理一致性时,通常使用锁来保证。

事务前后数据完整性要一致

3. 隔离性 I

通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的,这就是隔离性带来的结果。在前面的例子中,当执行完第3条语句、第4条语句还未开始时,此时有另外一个账户汇总程序开始运行,其看到的支票账户的余额并没有被减去200美元。因此隔离性会带来相应的问题。

并发执行时,数据库为每个用户开启一个事务,各事物之间互相不可见,事物之间相互隔离

4. 持久性 D

一旦提交,事务所做的修改就会被永久保存到数据库中。此时即使系统崩溃,数据也不会丢失。持久性是一个有点模糊的概念,实际上持久性也分很多不同的级别。有些持久性策略能够提供非常强的安全保障,而有些则未必。而且不可能有100%的持久性保障(如果数据库本身就能做到真正的持久性,备份的策略就不会被提出)

事务一旦提交就不可逆

例如· 转账200
操作前 A :800 B:200
操作后 A: 600 B:400
如果在操作前 (事务还没有提交)服务器断电,那么重启后,数据状态为
A:800 B:200
如果在操作后 (事务已经提交) 服务器断电,那么重启数据库以后 ,数据状态为 A: 600 B : 400

隔离级别

隔离性在实际操作中比看起来复杂得多。ANSI SQL标准定义了4种隔离级别,每种存储引擎实现的隔离级别都不尽相同。这个通用标准的目标是定义在事务内外可见和不可见的更改的规则。较低的隔离级别通常允许更高的并发性,并且开销也更低。

1. READ UNCOMMITTED(未提交读)

在READ UNCOMMITTED级别,在事务中可以查看(获取)其他事务中还没有提交的修改。

以上面银行应用举例,如果当你在查看你的余额时期间(你这边网络比较慢),你妈妈给你转账200元,但由于某停电原因,转账动作并没有提交,ATM机并没有收取这200元,此时你读取了没提交的这个+200元的记录。这就叫读未提交

读未提交会有什么后果呢?

你读取了错误的+200的余额,导致你认为你有这些钱,当你在你女朋友面前给她买东西付款时,此时余额不足的大字明明白白清清楚楚的展示在你女朋友面前,尴尬了不哥们!!!哈哈哈哈嗝~~

专业术语来说,读未提交会产生脏读、不可重复读、幻读(不可重复读和幻读后续会讲解)。

脏读:读取并使用了失效的数据记录

2. READ COMMITTED(提交读)

大多数数据库系统的默认隔离级别是READ COMMITTED(但MySQL不是)。READ COMMITTED满足前面提到的隔离性的简单定义:一个事务可以看到其他事务在它开始之后提交的修改,但在该事务提交之前,其所做的任何修改对其他事务都是不可见的。

还是银行的例子来举例,你有两张建行的卡,建行一卡和建行二卡,建行一卡中有10元,建行二卡中有100万元,这两证卡都已经绑定在了建行APP上了。某一天,你女朋友想要确定一下你的潜(钱)力,想看看你的资产额度,你信誓旦旦的掏出手机,打开建行APP。(建行APP的资产计数是当时将两张银行卡的余额做相加实现的,也就是先查第一张卡,然后再查第二张卡,你查看余额的这个事务包含了查卡一和卡二两个步骤)在这个执行事务第一步拿到卡一的10元时,你妈妈突然把卡二的钱转到卡一,并且此你妈妈的这个事务已提交。当你的事务再去读卡二时读到的是0元,两卡相加10元。这就叫做读提交。

会导致什么后果呢?

你读取了第二张卡的余额并不是错误的,读取的是你妈妈那个事务规规矩矩提交了的,只是因为你读取了不同的快照导致的。10元余额再次清清楚楚明明白白呈现在你可爱的女朋友面前!!真是潜(钱)力满满!!分手!!当然你再次刷新,如果没有什么意外情况,余额会显示你真正的潜(钱)力。

专业术语上来说,读已提交会导致不可重复读和幻读。

不可重复读:两次读取的数据不一样。

3. REPEATABLE READ(可重复读)

REPEATABLE READ结合MVCC原理(下面会将讲解)解决了READ COMMITTED级别的不可重复读问题,保证了在同一个事务中多次读取相同行数据的结果是一样的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读的问题。

为什么解决了不可重复读的问题?
基于MVCC原理,在事务开启之前,innodb会记录一个当前事务的ID,通过当前只能读取比自己事务id小于或等于的数据值的原则,相当于建立了一个视图,这样每次读取的数据都是不变的,从而解决了不可重复的的问题。

幻读:同一个事务中,读取的数据个数不一样;

REPEATABLE READ是MySQL默认的事务隔离级别,

4. SERIALIZABLE(可串行化)

SERIALIZABLE是最高的隔离级别。该级别通过强制事务按序执行,使不同事务之间不可能产生冲突,从而解决了前面说的幻读问题。简单来说,SERIALIZABLE会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题。实际应用中很少用到这个隔离级别,除非需要严格确保数据安全且可以接受并发性能下降的结果。

也就是说无论什么事务,都要进行排队,可能造成系统卡顿问题

MVCC原理

MVCC的工作原理是使用数据在一个事务中看到的数据是一致的,他通过快照来实现的。这意味着,无论事务运行多长时间,只要这个事务没结束,都可以看到数据的一致视图,也意味着不同的事务可以在同一时间看到同一张表中的不同数据。

为了实现这个机制,innodb在表中添加了一些隐藏列,其中一列记录最新改动此条数据的事务的id,当出现一个早期事务读取此条记录时,发现自己的事务id比这条数据的事务ID要小,那么这个事务就知道这个值被改动过,从而去通过undolog日志去读取此条数据小于等于自己事务ID的数据值。通过这样一个机制相当于维护了一张专属于这个事务的视图,从始至终都不会发生不可重复读的情况。

也就是说,基于MVCC原理,innodb引擎在事务开始是会记录此此事务的事务id,在读取数据时,通过比较事务id来判断当前要读的数据是否发生过变动,说白了,当前事务只能读取小于等于自己事务ID的数据值。

小结

在事务并发控制的内容中,但是依赖事务、ACID原则、隔离原则等这些概念单独使用不能保证并发事务的执行正确的结果,需要各种概念原则相互贯通核融合。

无论天气如何,无论白天黑夜,我都想要改善每个此刻,也把它刻在我的拐杖上 ——《瓦尔登湖》

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

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

相关文章

强化学习应用(五):基于Q-learning的物流配送路径规划研究(提供Python代码)

一、Q-learning算法简介 Q-learning是一种强化学习算法,用于解决基于马尔可夫决策过程(MDP)的问题。它通过学习一个值函数来指导智能体在环境中做出决策,以最大化累积奖励。 Q-learning算法的核心思想是使用一个Q值函数来估计每…

《计算思维导论》笔记:10.2 什么是数据库与数据库系统?

《大学计算机—计算思维导论》(战德臣 哈尔滨工业大学) 《10.2 什么是数据库与数据库系统?》 数据库 简单来讲,数据库就是相互有关联关系的数据的集合。 一个表聚集了具有相同结构类型的若干个对象一行数据反映了某一对象的相关…

【Python数据分析系列】实现txt文件与列表(list)相互读写转换(源码+案例)

这是Python数据分析系列原创文章,我的第199篇原创文章。 一、问题 平时在做数据分析或者程序开发的时候,需要将中间的一些结果或最后的处理结果保存下来,比如保存为txt格式的文本文件,这就涉及列表与txt之间的一种读取和写入操作…

【python】11.文件和异常

文件和异常 实际开发中常常会遇到对数据进行持久化操作的场景,而实现数据持久化最直接简单的方式就是将数据保存到文件中。说到“文件”这个词,可能需要先科普一下关于文件系统的知识,但是这里我们并不浪费笔墨介绍这个概念,请大…

《WebKit 技术内幕》之一: 浏览器和浏览器内核

第一章 浏览器和浏览器内核 浏览器的内核是浏览器的最核心的部件。 1.浏览器 1.1 浏览器发展简介 80年代后期90年代初期:由Berners-Lee 发明,诞生了世界上第一个浏览器 WorldWideWeb,后改名为 Nexus;并于1991年公布源代码&…

《2023年终总结》

笔者来回顾一下2023年的个人成长。 2023年总的来说,工作和生活都相对比较顺利。 工作上领导给予了肯定的评价,升职加薪,对我的鼓舞很大; 生活上和女朋友的感情越来越好,生气频率降低,也能相互理解&#xf…

【编码魔法师系列_构建型4】原型模式(Prototype Pattern)

学会设计模式,你就可以像拥有魔法一样,在开发过程中解决一些复杂的问题。设计模式是由经验丰富的开发者们(GoF)凝聚出来的最佳实践,可以提高代码的可读性、可维护性和可重用性,从而让我们的开发效率更高。通…

Meproc:简单高效的跨平台进程/任务管理工具

最近使用 Melang 语言写了一个 supervisor 相似服务Meproc来管理进程。 Meproc 有如下特性: 使用 HTTP API 管理控制 Meproc 来管理进程跨平台,支持 UNIX/Linux 、Mac 、Windows 等平台支持 cron 类定时调度任务支持简单的任务间依赖关系支持原生的协…

基于51单片机的模拟量输入输出通道实验

实验一 模拟量输入输出通道实验(C51) 一、实验目的: 1、了解A/D、D/A转换的基本原理。 2、了解A/D转换芯片ADC0809、D/A转换芯片DAC0832的性能及编程方法。 3、掌握过程通道中A/D转换与D/A转换与计算机的接口方法。 4、了解计算机如何进…

第二证券:利空因素影响成本端 豆粕期现价偏弱运行

上个买卖周,受利空要素影响,内盘豆粕期价刷新2021年12月14日以来收盘价新低。到上周五收盘,豆粕主力合约MO2405最低下探至3075元/吨,收报3078元/吨,周内累计跌幅近4%。业内人士以为,美国农业部超预期调高20…

pinyin-pro库使用方式

pinyin-pro 是一个专业的 JavaScript 中文转拼音的库,具备多音字识别准确、体积轻量、性能优异、功能丰富等特点。 pinyin-pro官网链接:介绍 | pinyin-pro 运行展示 pinyin-pro安装命令: # 选择一个你使用的包管理器进行安装即可# NPM $ n…

学网络必懂的华为CSS堆叠技术

知识改变命运,技术就是要分享,有问题随时联系,免费答疑,欢迎联系! 厦门微思网络​​​​​​https://www.xmws.cn 华为认证\华为HCIA-Datacom\华为HCIP-Datacom\华为HCIE-Datacom Linux\RHCE\RHCE 9.0\RHCA\ Oracle OC…

2024多系统萎缩最新全球特效药治疗进展

多系统萎缩是一种罕见的神经退行性疾病,由于缺乏有效的治疗方法,患者经常面临症状无法缓解和生活品质下降的困扰。然而,近期刘家峰大夫基于中医理论研究和临床实践,采用中药治疗多系统萎缩取得了显著疗效,给患者带来了…

mysql原理--undo日志2

1.概述 上一章我们主要唠叨了为什么需要 undo日志 ,以及 INSERT 、 DELETE 、 UPDATE 这些会对数据做改动的语句都会产生什么类型的 undo日志 ,还有不同类型的 undo日志 的具体格式是什么。本章会继续唠叨这些 undo日志 会被具体写到什么地方&#xff0c…

RMI简介

RMI 介绍 RMI (Remote Method Invocation) 模型是一种分布式对象应用,使用 RMI 技术可以使一个 JVM 中的对象,调用另一个 JVM 中的对象方法并获取调用结果。这里的另一个 JVM 可以在同一台计算机也可以是远程计算机。因此,RMI 意味着需要一个…

Spring MVC中的一些常用注解

目录 RequestMapping 实现路由映射 限制请求方式 PathVariable 从url中获取变量的值 更改绑定参数的名字 RequestParam 可以传递集合 更改绑定参数的名字 可修改是否为必传参数 RequestBody 获取请求正文的内容 可修改是否为必传参数 RequestPart 可以支持上传…

Android中的SPI实现

Android中的SPI实现 SPI是JVM世界中的标准API,但在Android应用程序中并不常用。然而,它可以非常有用地实现插件架构。让我们探讨一下如何在Android中利用SPI。 问题 在Android中,不同的提供者为推送功能提供服务,而在大型项目中…

python入门,数据容器:字典dict

字典作用就和它的名字一样,我们可以通过某个关键字找到它对应的信息,或者讲的高级一点,就是key与value的对应关系 举例: 一场考试小明考了80分,小红考了90分,小东考了95分,在字典里&#xff0…

使用JDK自带的jvisualvm工具查看堆dump文件【回顾】

JDK自带的jvisualvm的使用 打开方式: 直接命令行输入:jvisualvm ,然后回车​​​​​​​ ​​ 或者去jdk的bin目录下找到打开 安装visual GC插件 检测死锁 再点击“死锁 dump”就可以看到死锁的线程信息了;

C++每日一练(16):数组逆序

题目描述 给你m个整数&#xff0c;将其逆序输出 输入 第一行一个整数m&#xff08;3 < m < 100 )&#xff1a;数的个数 第二行m个整数&#xff08;空格隔开&#xff09;&#xff08;这些数在0-9999999之间) 输出 m个整数&#xff08;空格隔开&#xff09; 输入样例 3 1 7…