当前位置: 首页 > news >正文

面试八股文Mysql:(1)事务实现的原理

1. 什么是事务

事务就是一组数据库操作,这些操作是一个atomic(原子性的操作) ,不可分割,要么都执行,要么回滚(rollback)都不执行。这样就避免了某个操作成功某个操作失败,从而导致数据的不一致。

2. 事务的4大特性

原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durabilily),简称ACID。
在这里插入图片描述
事务的目标:
一致性是事务的最终目的,原子性、隔离性、持久性都是为了实现一致性。

2.1. 并发事务带来的问题 (隔离性带来的问题)

两个并发执行的事务,如果涉及到操作同一条记录的时候,可能会发生问题。因为并发操作会带来数据的不一致性,包括脏读、不可重复读、幻读等。数据库系统提供了隔离级别来让我们有针对性地选择事务的隔离级别,避免数据不一致的问题。

在这里插入图片描述

2.2. 事务隔离级别 (解决隔离性带来的问题)

事务的隔离性是有级别的,在某些级别下,在并发事务的情况下,不能保证一个事务的执行不被其它事务干扰。既然会被干扰,那么就会出现一些问题。

在这里插入图片描述
在MySQL中,如果使用InnoDB,默认的隔离级别是Repeatable Read。

3. 数据库日志

一、redo log 重做日志

内容:物理格式的日志,记录的是物理数据页面的修改的信息,其redo log是顺序写入redo log file的物理文件中去的。
该日志文件主要由两部分组成:重做日志缓冲(redo log buffer)和重做日志文件(redo log),前者存储在内存中,后者存储在磁盘中。mysql 为了提升性能,不会把每次的修改都实时同步到磁盘,而是会先存到 Buffer Pool(缓冲池) 里头,把这个当作缓存来用。然后使用后台线程去做缓冲池和磁盘之间的同步。

作用:确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。

二、undo log 回滚日志

内容:逻辑格式的日志,在执行undo的时候,仅仅是将数据从逻辑上恢复至事务之前的状态,而不是从物理页面上操作实现的,这一点是不同于redo log的。

作用:保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。

三、bin log 归档日志(二进制日志)

内容:逻辑格式的日志,可以简单认为就是执行过的事务中的sql语句。
但又不完全是sql语句这么简单,而是包括了执行的sql语句(增删改)反向的信息,也就意味着delete对应着delete本身和其反向的insert;update对应着update执行前后的版本的信息;insert对应着delete和insert本身的信息。

作用:用于复制,在主从复制中,从库利用主库上的binlog进行重播,实现主从同步。
用于数据库的基于时间点的还原。

binlog 有三种模式:Statement(基于 SQL 语句的复制)、Row(基于行的复制) 以及 Mixed(混合模式)

4. 如何实现事务

务的实现依靠的是innodb的redo log, undo log和锁。

4.1 原子性

原子性的实现主要依靠的是Undo log日志。原子性的体现主要是在sql在执行过程中发生错误而发生回滚上。回滚是要回到执行前的一个状态,那么怎么回到执行前的状态呢?我们是不是就得将执行前的状态记录下来。因此假如由于系统错误或者rollback操作而回滚的话,可以根据undo log的信息来进行回滚到没被修改前的状态。

4.2 持久性

我们需要先来了解下InnoDB是怎么来读写数据的。我们知道数据库的数据都是存放在磁盘中的,但是磁盘I/O的成本是很大的,如果每次读写数据都要访问磁盘,数据库的效率就会非常低。为了解决这个问题,InnoDB提供了 Buffer Pool 作为访问数据库数据的缓冲。

Buffer Pool 是位于内存的,包含了磁盘中部分数据页的映射。当需要读取数据时,InnoDB会首先尝试从Buffer Pool中读取,读取不到的话就会从磁盘读取后放入Buffer Pool;当写入数据时,会先写入Buffer Pool的页面,并把这样的页面标记为dirty,并放到专门的flush list上,这些修改的数据页会在后续某个时刻被刷新到磁盘中(这一过程称为刷脏,由其他后台线程负责) 。

通过前面的介绍,我们知道InnoDB使用 Buffer Pool 来提高读写的性能。但是 Buffer Pool 是在内存的,是易失性的,如果一个事务提交了事务后,MySQL突然宕机,且此时Buffer Pool中修改的数据还没有刷新到磁盘中的话,就会导致数据的丢失,事务的持久性就无法保证。为了解决这个问题,InnoDB引入了 redo log来实现数据修改的持久化。根据我们在上面所介绍的WAL机制,先写日志,再写磁盘,有了redo log,InnoDB就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个 能力称为crash-safe。

4.3 隔离性

数据库的隔离性就是通过加锁和MVCC来实现的。
可重复读的隔离级别会出现幻读的问题,而MySQL的默认隔离级别是可重复读,并且解决了幻读的问题。简单来说,MySQL的默认隔离级别解决了脏读、幻读、不可重复读的问题。

数据库并发场景有三种:
读-读:不存在任何问题,也不需要并发控制
读-写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读
写-写:有线程安全问题,可能存在更新丢失问题,比如第一类更新丢失,第二类更新丢失

写-写操作的线程安全是通过加锁来实现的,但是加锁的操作会严重影响数据库的性能和并发量,因此出现了MVCC—多版本并发控制。MVCC是一种用来解决读-写冲突的无锁并发控制,MVCC在数据库中的实现,就是为了解决读(快照读)写冲突,它的实现原理主要是依赖记录中的 3个隐式字段,undo日志 ,Read View 来实现的。MVCC可以为数据库解决以下问题:

  • 在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
  • 同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题

5. 总结

重做日志,回滚日志以及锁技术就是实现事务的基础。

  • 事务的 原子性 是通过 undo log 来实现的;
  • 事务的 持久性 是通过 redo log 来实现的;
  • 事务的 隔离性 是通过 (读写锁+MVCC)来实现的;
  • 事务的 一致性 是通过原子性,持久性,隔离性来共同实现的。

总之,ACID只是个概念,原子性,持久性,隔离性都是为了实现数据的一致性,事务的最终目的就是要保障数据的一致性。

相关文章:

面试八股文Mysql:(1)事务实现的原理

1. 什么是事务 事务就是一组数据库操作,这些操作是一个atomic(原子性的操作) ,不可分割,要么都执行,要么回滚(rollback)都不执行。这样就避免了某个操作成功某个操作失败&#xff0…...

Linux学习之sed多行模式

N将下一行加入到模式空间 D删除模式空间中的第一个字符到第一个换行符 P打印模式空间中的第一个字符到第一个换行符 doubleSpace.txt里边的内容如下: goo d man使用下边的命令可以实现把上边对应的内容放到doubleSpace.txt。 echo goo >> doubleSpace.txt e…...

【刷题笔记8.15】【链表相关】LeetCode:合并两个有序链表、反转链表

LeetCode:【链表相关】合并两个有序链表 题目1:合并两个有序链表 题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3…...

神经网络基础-神经网络补充概念-11-向量化逻辑回归

概念 通过使用 NumPy 数组来进行矩阵运算,将循环操作向量化。 向量化的好处在于它可以同时处理多个样本,从而加速计算过程。在实际应用中,尤其是处理大规模数据集时,向量化可以显著提高代码的效率。 代码实现-以逻辑回归为例 i…...

openGauss学习笔记-40 openGauss 高级数据管理-锁

文章目录 openGauss学习笔记-40 openGauss 高级数据管理-锁40.1 语法格式40.2 参数说明40.3 示例 openGauss学习笔记-40 openGauss 高级数据管理-锁 如果需要保持数据库数据的一致性,可以使用LOCK TABLE来阻止其他用户修改表。 例如,一个应用需要保证表…...

勘探开发人工智能技术:机器学习(6)

0 提纲 7.1 循环神经网络RNN 7.2 LSTM 7.3 Transformer 7.4 U-Net 1 循环神经网络RNN 把上一时刻的输出作为下一时刻的输入之一. 1.1 全连接神经网络的缺点 现在的任务是要利用如下语料来给apple打标签: 第一句话:I like eating apple!(我喜欢吃苹…...

代理类型中的 HTTP、HTTPS 和 SOCKS 有什么区别?

HTTP、HTTPS 和 SOCKS 都是代理(Proxy)协议,用于在网络通信中转发请求和响应,但它们在工作原理和用途上有一些区别。下面是它们之间的主要区别: HTTP代理: 工作原理: HTTP 代理主要用于转发 HTT…...

【STM32RT-Thread零基础入门】 3. PIN设备(GPIO)的使用

硬件:STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 文章目录 前言一、PIN设备介绍1. 引脚编号获取2. 设置引脚的输入/输出模式3. 设置引脚的电平值4. 读取引脚的电平值5. 绑定引脚中断回调函数6. 脱离引脚中断…...

fiddler抓包工具的用法以及抓取手机报文定位bug

前言: fiddler抓包工具是日常测试中常用的一种bug定位工具 一 抓取https报文步骤 使用方法: 1 首先打开fiddler工具将证书导出 点击TOOLS------Options------Https-----Actions---选中第二个选项 2 把证书导出到桌面后 打开谷歌浏览器 设置---高级…...

spring中时间格式化的两种方式

方法一:自己格式化 自己写一个格式化的类,把date类型的时间传进去: public class DateUtil {public static String formatDate(Date date){SimpleDateFormat simpleDateFormatnew SimpleDateFormat("yyyy-MM-dd HH:mm:ss");retur…...

【设计模式】原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。 这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接…...

Matlab的Filter Designer工具设计二阶低通滤波器

Matlab版本:2018b 本文要求:设计一个二阶巴特沃斯低通滤波器用于嵌入式软件滤波,传感器采样频率是20KHz,截止频率是333Hz,获取滤波系数,本文不包括二阶滤波推导和代码编写。 打开Matlab->APP->Filt…...

软件测试基础篇——LAMP环境搭建

LAMP 1、Linux系统的其他命令 find命令:在目录下查找文件 ​ 格式一:find 路径 参数 文件名 ​ 路径:如果没有指定路径,默认是在当前目录下 ​ 参数:-name 根据文件名来查找,区分大小写; -…...

使用dom4j将xml转为String并去掉所有格式

文章目录 功能描述实现代码 功能描述 有以下xml内容&#xff0c;需要转成String字符串。同时&#xff0c;要去掉文中所有格式。 <root><student><name>张三</name><sex>男</sex><age>16</age><class>1班</class>…...

wsl2安装docker引擎(Install Docker Engine on Debian)

安装 1.卸载旧版本 在安装 Docker 引擎之前&#xff0c;您必须首先确保卸载任何冲突的软件包。 发行版维护者在他们的存储库。必须先卸载这些软件包&#xff0c;然后才能安装 Docker 引擎的正式版本。 要卸载的非官方软件包是&#xff1a; docker.iodocker-composedocker-…...

百日筑基篇——python爬虫学习(一)

百日筑基篇——python爬虫学习&#xff08;一&#xff09; 文章目录 前言一、python爬虫介绍二、URL管理器三、所需基础模块的介绍1. requests2. BeautifulSoup1. HTML介绍2. 网页解析器 四、实操1. 代码展示2. 代码解释1. 将大文件划分为小的文件&#xff08;根据AA的ID数量划…...

【Spring专题】Spring之底层架构核心概念解析

目录 前言前置知识课程内容一、BeanDefinition&#xff1a;图纸二、BeanDefinitionReader&#xff1a;图纸注册器——Spring工厂基础设施之一2.1 AnnotatedBeanDefinitionReader2.2 XmlBeanDefinitionReader2.3 ClassPathBeanDefinitionScanner基本介绍总结使用示例 三、BeanFa…...

electron 使用node C++插件 node-gyp

node C插件使用&#xff0c;在我们常规使用中&#xff0c;需要使用node-gyp指定对饮的node版本即可 在electron的使用中&#xff0c;我们需要指定的是electron版本要不然会报错使用的v8内核版本不一致导致C扩展无法正常引入 electron官方文档-node原生模块 package.json {&quo…...

学习Vue:使用条件渲染指令(v-if,v-else,v-show)

在 Vue.js 中&#xff0c;条件与循环是实现动态交互界面的关键要素。通过使用条件渲染指令&#xff0c;您可以根据不同的条件决定是否显示或隐藏特定的内容。在本文中&#xff0c;我们将介绍三个常用的条件渲染指令&#xff1a;v-if、v-else 和 v-show&#xff0c;以及它们的用…...

【图像去噪的滤波器】非局部均值滤波器的实现,用于鲁棒的图像去噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

给网站添加live2d看板娘

给网站添加live2d看板娘 参考文献&#xff1a; stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下&#xff0c;文章也主…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...