详细介绍:MySQL进阶学习

news/2025/9/23 18:16:36/文章来源:https://www.cnblogs.com/yxysuanfa/p/19107683

前言:

介绍下MySQL的锁机制,事务原理,以及MVCC的实现原理。

1. 锁

1.1 介绍

锁是计算机多个进程或线程并发访问某一个线程的机制。MySQL的锁分为全局锁,表级锁,还有行级锁。

1.2 全局锁

全局锁就算对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的写语句。已经更新操作的事务提交语句都将被阻塞。

其典型的使用场景是做对全库的逻辑备份,对所有的表进行锁定,从而获得一致性视图,保证数据的完整性。

1.2.1 全局锁建立一致性数据备份

先使用flush命令进行加锁:

flush tables with read lock

进行读运行,发现可以正常进行:

随后进行写操作,发现系统报错:

说明在加上全局锁后,整个数据库处于只读状态。

进行数据备份:

查看文件夹,发现有备份文件,说明备份成功:

1.2.2 全局锁的问题

一个比较重的管理,存在以下问题:就是数据库中在全局锁,

1.若是在主库上进行备份,那么备份期间都不能执行更新,业务基本上停摆。

2.如果在从库上进行备份,那么备份期间就不能执行主库同步过来的二进制日志。

补充:

使用以下指令能够在不加全局锁的情况下搞定不加锁的一致性数据备份:

mysqldump --single-transaction -uroot -p123 itcast > itcast.sql

也就是在备份时加上参数 --single-transaction

1.3 表级锁

表级锁,每次运行锁定整张表,锁定粒度大,发生锁冲突的概率最高,并发度最低,应用在MyISAM,InnoDB,BDB等储存引擎中。

表级锁,分为以下三类:

1.表锁

2.元数据锁(meta data lock)

3.意向锁

1.3.1 表锁

对于表锁,分为以下两类:

1.表共享读锁(read lock)

2.表独占写锁(write lock)

会阻塞其他客户端的读写操作。就是表共享读锁会阻塞当前和其他客户端的一个写操作,但是不会阻塞读操作。表独占写锁不会阻塞当前客户端的写和读,但

语法

1.加锁

lock table [表名] read/write;

2.释放锁

unlock tables;

1.3.2 元数据锁(MDL)

MDL加锁过程是系统自动控制的,无需显式的去使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的一致性(即维护表结构),在表上有活动事务的时候,不允许对元数据进行写入操作。

通俗一点讲,即:

在有事务未提交的情况下,不能够对该表的表结构进行修改,避免DML和DDL发生冲突,保证读写的正确性。

在MySQL5.5引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享),当对表结构进行变更管理的时候,加MDL写锁(排他)。

1.3.3 意向锁

为了避免在DML在执行时,加的行锁和表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁减少表锁的检查。

意向锁分为以下两种:

1.意向共享锁(IS):由语句select ... lock in shares mode添加,与表锁共享锁兼容,与表锁排他锁互斥。

2.意向排他锁(IX):由insert,update,select...for update添加,与表锁共享锁和排他锁都互斥,意向锁之间不会互斥。

测试

需注意的是,意向锁是一个表级锁,它标志着'某个事务即将或正在对表中的某一行持有某种锁快速判断表级锁和行级锁之间的冲突。就是',它的作用

所以在测试与表锁的兼容性问题时,需要先启动事务,不然执行完成后锁就立即释放了。

首先在一个客户端加上意向共享锁

打开另一个客户端,加上读锁,发现是可以加锁成功的

接下来测试意向排他锁(IX):

同样先在一个客户端内添加意向排他锁:

在另一个客户端加入读锁,发现处于阻塞状态。

提交事务后,才能成功加锁。

1.4 行级锁

行级锁,每次操作都锁定对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高,应用在InnoDB存储引擎中。

InnoDB的数据基于索引组织的,行锁是依据对索引上的索引项加锁来实现的,而不是对记录加的锁,对于行级锁,核心分为以下三类:

1.行锁:锁定单个行记录的锁,防止其他事务对此进行update和delete,在RC,PR隔离级别下都支撑。

2.间隙锁:锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其事务在这个间隙进行insert,产生幻读,在RR隔离级别下都支持。

3.临键锁:行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙,在RR隔离级别下支持。

1.4.1 行锁

InnoDB实现了以下两种类型的行锁:

1.共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁

2.排他锁(X): 允许获取排它锁的事务更新数据,阻止其他事务获得相同内容集的共享锁和排它锁

当前锁类型\请求锁类型S(共享锁)X(排它锁)
S(共享锁)兼容冲突
X(排它锁)冲突冲突

下图是各种SQL语句的行锁类型

默认情况下,InnoDB在RR的事务隔离级别运行,InnoDB使用next-key锁(记录锁+间隙锁)进行搜索和索引扫描,以防止幻读。

1.针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化成行锁;

这里解释下为什么这么优化:

  • 唯一索引,等值查询最多返回一条记录就是因为
  • 记录已存在的情况下,不需要通过间隙锁来防止其他事务插入相同的值(不可能有幻读)
  • 只要锁定已存在的这条记录即可保证一致性。

2.InnoDB的行锁是针对于索引加的锁,不通过索引条件检索数据,那么InnoDB将对表中的所有记录进行加锁,此时就会升级成表锁。

解释:

这句话的意思就是如果查询不走索引的话,那么就会走表锁(后面有测试)

测试1(兼容性)

首先开启一个事务,加共享锁

在另一个客户端也开启一个事务,加共享锁,发现是兼容的:

不兼容的:就是关闭该事务,另开启一个事务,这次加排他锁,发现

行看到陷入了阻塞。

测试2(针对行锁升级成表锁进行说明):

首先在一个客户端中开启事务,并且使用不走索引的方式更新数据;

在另一个客户端中也开启事务,进行id查询,发现即使查询的是不同的id,还是陷入了阻塞。

说明第一个客户端走的是表锁。

1.4.2 间隙锁/临键锁

默认情况下,InnoDB在RR的事务隔离级别运行,InnoDB使用next-key锁进行搜索和索引扫描,以防止幻读。但是

1. 索引的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁。

解释:

简单来说,就是倘若你锁住了id=5的数据(假设表中只存在3和8,不存在5),那么另开一个事务,会发现无法插入3和8之间的id数据,因为上了间隙锁。

------------------------------------------------------------------------------------------------------------------------------

2.索引的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock退化为间隙锁。

解释:

唯一的,有可能出现重复值的情况,如果加行锁的话,不能只对单一数字进行加锁,而是就是这个的意思是普通索引不从该数字之前开始一直到该数字没有重复值之后的这一段进行加锁。

-----------------------------------------------------------------------------------------------------------------------------

3.索引的范围查询(唯一索引)会访问到不满足的第一个值为止。

解释:

给选定的数字以及后面(前面)的值进行加锁。比如>=19,就算给19以及后面到正无穷的数字进行加锁。就是不作过多解释,就

-------------------------------------------------------------------------------------------------------------------------------

注意:间隙锁唯一的目的是防止其他事务插入间隙,间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁

2.InnoDB引擎

2.1 事务原理

2.1.1 什么是事务

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有操作作为一个整体一起向系统提交或者撤销操作请求,这些操作要么同时成功,要么同时失败。

2.1.2事务的四大特性

  • 不可分割的最小操作单元,要么全部成功,要么全部失败(undo log完成)就是原子性:事务
  • 一致性:事务结束时,必须使所有的材料都保持一致状态(redo log + undo log实现)
  • 隔离性:数据库系统提供的隔离机制,保证事务早不受外部影响的独立环境下运行。(锁+MVCC实现)
  • 持久性:事务一但提交或回滚,它对数据库的改变就是永久的。(redo log实现)

由锁机制和MVCC来控制的。就是这四个特性简称ACID。在这四个特性中原子性,一致性,持久性都是由read.log和undo.log这两个日志文档来控制的;隔离性

2.1.3 redo.log

用来就是redo.log是一个重做日志,记录的是事务提交时数据页的物理修改,实现事务的持久性

该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志档案(redo log file),前者在内存中,后者在磁盘中,当事务提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用。

原理大致如下

当用户执行update或者delete等写操作时,系统会先在buffer pool中缓存相应的数据(引擎的一部分,详情这里不展开叙述了,类似于操作系统的缓冲池,减少磁盘io所用),并在重做日志缓存(read log buffer)拷贝一份,当事务提交之后,就会将缓存日志中的信息持久化到日志文件中(磁盘结构)。如果buffer pool中的脏页(材料不一致的页)持久化到磁盘的过程中发生错误的话,日志恢复可用于数据恢复。

疑问:为什么buffer pool不能在事务提交的时候就将脏页持久化到磁盘中呢?

这个涉及到性能问题,Buffer Pool脏页刷盘时是随机I/O,数据页在磁盘上的位置是分散的,每次持久化到需要寻址,性能极差;而Read Log写入是顺序I/O,日志是追加写入的,只需顺序写文件,速度比随机写入快几个数量级。

2.1.4 undo.log

逻辑日志,可以认为当执行一条delete操作时,undo log会记录用于插入这条数据的Insert操作(用于回滚);当执行一条update操作的时候,undo会记录一条用于更改回原来数据的update操作。这样做,当执行rollback时,就可以从undo.log中的逻辑记录读取到相应的内容进行回滚。就是undo.log是一个回滚日志,用于记录数据被修改前的信息,作用包含两个:提供回滚和MVCC(多版本并发控制)。undo.log和redo.log记录物理日志不一样,它记录的

Undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除这些undo log,因为可能还需要用于MVCC.

undo log储存:undo log采用段的方式进行管理和记录,存在在rollback segment回滚段中(InnoDB的结构一部分)。

2.2 MVCC原理

2.2.1 MVCC的基本概念

1.当前读

读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select...lock in share mode(共享锁),select...for update,update,insert ,delete(排它锁)都是一种当前读。

在可重复读(RR)的事务隔离级别环境中,在两个客户端同时开启事务,当一个客户端更新数据并提交了事务,另一个客户端查询数据是看不到已提交的更新数据的,因为在该事务隔离级别下解除了不可重复读的问题

想要解决这个情况,就要应用当前读,即查询后面加上in share mode:

就可以查询到最新的数据了。

2.快照读

简单的select(不加锁)就是快照读。快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。

  • Read Committed:每次select,都生成一个快照读
  • Repeatable Read:开启事务后第一个select才是快照读的地方(后面直接查询的时候查询的都是快照的数据)
  • Serializable:快照读会退化为当前读

3.MVCC

全称Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC给出了一个非阻塞读功能。MVCC的具体构建,还要求依赖于数据库记录中的三个隐式字段,undo log日志,readView.

2.2.2 MVCC的实现原理

1.隐式字段

MySQL中一个表中包含两个或者三个隐式字段,分别为DB_TRX_ID, DB_ROLL_PIR, DB_ROW_ID。

下面分别介绍这三个字段:

  • DB_TRX_ID: 最近修改事务ID,记录插入这条记录或最终一次修改该记录的事务。
  • DB_ROLL_PIR: 回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。
  • DB_ROW_ID: 隐藏主键,如果有表结构没有指定主键,将会生成该字段.

2.undolog版本链

不同事务或者相同事务对同一条记录进行修改时,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧纪录,链表尾部是最早的旧记录。

比如假设有事务2和事务3两个事务,当事务2进行修改操作时,会生成一个undo log日志,其中包含修改前的日志,并给予相应的地址,然后在当前的一个记录中生成最新的内容,DB_TRX_ID更新最新的事务ID,DB_ROLL_PIR储存最新的undo log日志的一个地址。操作事务3的时候亦然如此,形成一个链表。

注意:当事务提交后,undo log日志的内容不会立即删除,还必须用于MVCC.

3.readview

ReadView(读视图)是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃(即未提交)的事务id。ReadView包含了四个核心字段:

  • m_ids: 当前活跃的事务ID集合
  • min_trx_id: 最小活跃事务ID
  • max_trx_id: 预分配事务ID,当前最大事务ID+1(由于事务ID是自增的)
  • create_trx_id: ReadView创建者的事务ID

版本链数据访问规则(trx_id代表当前事务ID):

1. trx_id == create_trx_id 是可以访问该版本的,因为这说明素材是当前这个事务提交的。

2. trx_id < min_trx_id 也是可以访问该版本的,基于这说明数据已经被提交了

3.trx_id > max_trx_id 是不可以访问该版本的,说明事务是在ReadView生成后开启的

4.min_trx_id <= trx_id <= max_trx_id 如果trx_id不在m_ids中是可以访问该版本材料的,说明数据已经提交。

得注意的是,不同的隔离级别,生成ReadView的时机也不同:

  • 读已提交(RC):在事务中每一次执行快照读时生成ReadView
  • 可重复读(RR):仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView

2.2.3 原理分析(RC)

由readView和undo log去共同实现的。就是读已提交(RC)的事务隔离级别机制是可以读取已经提交后的数据,而这个机制

因为RC在事务中的每一次执行快照读的时候会生成ReadView,造成了它每一次查询的时候都会记录还未提交的事务ID作为m_ids, 而根据版本链数据访问规则:trx_id < min_trx_id 就决定了它在undo log中遍历版本链​时​通过 DB_TRX_IDDB_ROLL_PTR只能回溯到已提交事务的历史版本。

用更专业的术语说就是:

  1. 每次 SELECT生成 ReadView​:捕获当前活跃事务列表。

  2. ​遍历版本链​​:从最新数据开始,通过 DB_TRX_IDDB_ROLL_PTR回溯历史版本。

  3. ​可见性判断​​:

    • 若数据版本的 trx_id不在 m_ids中且已提交(trx_id < max_trx_id)→ 可见。

    • 否则继续回溯版本链,直到找到可见版本或返回空。

  4. ​返回结果​​:读取第一个可见的版本。

2.2.4 原理分析(RR)

在RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView.

这也解释了为什么明明一个事务已经提交,另一个活跃的事务还是只能读到之前的信息,因为他们的readView是相同的,根据版本链查询到的资料也自然是相同的。

2.2..5 总结

总的来说,MVCC是通过隐藏字段,undo log版本链,ReadView三个共同作用实现。隐藏字段的值作为版本链的连接和指导方向组合成为一个历史数据链表,不同隔离级别下的快照读生成ReadView,根据版本链路访问规则,选择对应的历史数据进行返回。

最后:

今天的分享就到这里。要是我的内容对你有帮助,请点赞评论收藏我坚持下去的动力!(๑`・ᴗ・´๑)就是。创作不易,大家的协助就

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

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

相关文章

时序数据库 TimechoDB V2.0.6 发布 | 新增查询写回、黑白名单等功能

表模型查询写回、访问控制黑白名单、位操作函数、可下推的时间函数等重要功能更新!TimechoDB V2.0.6 版本正式发布! TimechoDB 是由 IoTDB 原厂团队开发的企业级时序数据库产品。V2.0.6 版本新增表模型查询写回功能,…

icp网站备案流程视频网站弹幕怎么做

0 CS224W概况 斯坦福大学CS224W课程&#xff1a;http://cs224w.stanford.edu/ 图机器学习的库&#xff1a; 为什么是图&#xff1f;图是描述和分析具有关系/交互的实体的通用语言。 1 图数据举例 复杂域具有丰富的关系结构&#xff0c;可以表示为关系图。 通过显式地建模关…

南宁seo网站排名优化表白网页生成

目录 广播接收器 BroadcastReceiver实现原理使用流程广播的类型(1) 普通广播(2) 系统广播(3) 有序广播(4) App应用内广播 Local Broadcast粘性广播 面试问题 广播接收器 BroadcastReceiver 实现原理 Android 中的广播使用了设计模式中的观察者模式&#xff1a; 基于消息的发布…

自己做网站接广告网站推广哪个平台最好

package 内部类异常包装器;public class 异常 {/*** 1.异常:* 有Error和Exception两个基本子类* 2.Error:* Error表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。* 3.Exception:* 表示一种设计或实现问题。也就是说&…

千图网免费设计图片素材网seo整站优化服务教程

1. 用Record接口&#xff0c;要注意 Packed的区别 2. cdecl和stdcall的区别 3. C导出的函数建议用C格式stdcall导出&#xff0c;使用Def文件定义名称 4. 用VS写的API dll要注意是否引用了MFC的DLL&#xff0c;否则会使LoadLibrary失败&#xff0c;并GetLastError后返回14001 Ap…

东莞网站建设属于什么专业优化营商环境 提升服务效能

ICCV&#xff0c;被誉为计算机视觉领域三大顶级会议之一。作为计算机视觉领域最高级别的会议之一&#xff0c;其论文集代表了计算机视觉领域最新的发展方向和水平。阿里巴巴在今年的大会上有多篇论文入选&#xff0c;本篇所解读的论文是阿里iDST与多家机构合作的入选论文之一&a…

杭州富阳建设局网站首页推广普通话征文

根据近日工业和信息化部发布的《工业和信息化部关于开展移动互联网应用程序备案工作的通知》要求&#xff0c;在中华人民共和国境内从事互联网信息服务的APP主办者&#xff0c;应当依照《中华人民共和国反电信网络诈骗法》《互联网信息服务管理办法》&#xff08;国务院令第292…

备案个人网站 淘宝客兰州网站建设cheng

Win10专业版如何激活 Win10专业版如何激活 - 知乎 使用这方法成功了。 win10连上wifi却不能上网的问题解决方法&#xff1a;https://jingyan.baidu.com/article/c85b7a644c2996003bac958a.html 一&#xff1a;先改ipv4自动手动的&#xff0c;不行 二&#xff1a;把无线网卡…

母婴网站模板访问量大的网站

Leetcode 2786. 访问数组中的位置使分数最大 DP 以每个位置为结尾的序列的分数取决于前方的分数&#xff0c;根据奇偶性计算&#xff0c;取最大值 超时 class Solution {public long maxScore(int[] nums, int x) {int n nums.length;long dp[] new long[n];Arrays.fill(dp…

NLP:驱动人工智能迈向 “理解” 与 “对话” 的核心引擎 - 教程

NLP:驱动人工智能迈向 “理解” 与 “对话” 的核心引擎 - 教程2025-09-23 18:06 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !imp…

Python精品任务-基于python的个性化音乐推荐架构的设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)

Python精品任务-基于python的个性化音乐推荐架构的设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; displa…

旧手机改服务器-旧Android手机改Linux服务器Termux方案

旧手机改服务器-旧Android手机改Linux服务器Termux方案确切的说, 应该是: 旧Android手机改Linux服务器^-^ 0. 本文选用Termux+OpenSSH方案.简单-直接安装app即可, 兼容性高-手上的OPPO R9s 手机实在过于老旧1. 安装Ter…

长沙网站建设排名计算机做网站

在使用过去20天的数据预测未来7天时&#xff0c;时间步的设置通常取决于你对问题的理解以及模型的设计。时间步定义了每个样本中包含多少个时间步的数据。 在使用循环神经网络 (RNN) 或长短时记忆网络 (LSTM) 这样的模型时&#xff0c;你可以将时间步的选择视为一个超参数。这…

软件自学网站手表网站十大品牌

前言 本篇博客介绍在查看日志的场景中&#xff0c;grep管道命令的使用&#xff0c;并给出了具体的案例。 以下为Linux相关的博客文章列表&#xff1a; Linux——认识Linux的目录结构 & 常用命令 & vim命令 & 权限及其控制 & 防火墙命令 & 自定义命令 &a…

菏泽网站获客网站建设公司wordpress文章外链缩略图

谷歌guava番石榴 这是我尝试解释和探索Google很棒的Guava java库的系列文章中的第一篇。 我在搜索Apache Commons Collections的通用版本时遇到了番石榴&#xff08;Guava&#xff09;–我需要一个Bimap并且厌倦了必须使用强制类型转换来填充我的代码–但是我发现要好得多。 …

网站建设有些什么流程能看完整舆情报告的软件

微软终于发布了.Net Code RC2了&#xff0c;作为一个软粉当然是第一时间升级了。《升级.Net Core RC2的那些事》系列文章主要是记录本人升级RC2的相关步骤以及遇到过的坑。 第一篇先写类库项目&#xff08;Nuget包项目&#xff09;的升级 升级VS工具 这里只提供一个下载地址&am…

南昌网站建设渠道django网站开发实例源码

假设目标机器openeuler的IP是192.168.0.100 1.先检查网络是否连通&#xff1a; 在本地 telnet 192.168.0.100 22 (通常连接成功后&#xff0c;会显示类似SSH-2.0-OpenSSH_8.2版本信息&#xff09; 以上需要sshd服务进程存在&#xff0c;以及防火墙是通的。 2. 查看&#xff1…

自己电脑做网站服务器深圳装修公司前十强

南开大学20春学期(1709、1803、1809、1903、1909、2003)《Python编程基础》在线作业试卷总分:100 得分:98一、单选题(共20 道试题,共40 分)1.已知“stra\rb\r\nc\n”,则“str.splitlines()”的返回结果是( )。A.[a,b,c]B.[a\r,b\r\n,c\n]C.[a\r,b\r,c]D.[a\r,b,c]答案:A2.已知“…

什么类型网站国外设计素材网站

软件工程项目管理是一个系统工程&#xff0c;软件工程项目管理的主要目标是保证项目在规定时间内高质量地完成。项目管理包括了项目组开发各阶段的人员结构的配置&#xff0c;质量控制的实施方略&#xff0c;内部文档和产品文档的组织编写等多项工作&#xff0c;其中质量控制方…

咨询企业网站模板数据分析师课程

前言—在 web 开发场景&#xff0c;减少代码体积虽然是性能优化的一个方向&#xff0c;还没到锱铢必较的程度。但是在小程序场景&#xff0c;由于代码包上传阶段限制了主包 2M 和总包 16M&#xff08;近期微信官方正在内测将总包上限调整至 20M &#xff09;的尺寸&#xff0c;…