MySQL经典面试题:谈一谈你对事务的理解

2024-06-17 00:04

本文主要是介绍MySQL经典面试题:谈一谈你对事务的理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 📑事务
    • 事务的基本概念
      • 回滚
      • 开启事务的sql语句
    • 事务的基本特性
      • 总结一下涉及到的三个问题
  • ☁️结语


📑事务

事务的基本概念

事务是用来解决一类特定场景的问题的,在有些场景中,完成某个操作,需要多个sql配合完成的。

比如说:1号给2号转账1000000元
在这里插入图片描述

转账的流程大概是这样的

  1. 给 1 号的账户余额减去1000000,update 账户余额表 set balance = balance - 1000000 where id = 1;
  2. 给 2 的账户余额加上1000000,update 账户余额表 set balance = balance + 1000000 where id = 2;

显然,以上的转账操作,涉及了2个sql语句,在实际开发中,我们一般都是通过C++/Java等这样的语言来实现的,这个时候就涉及到1个问题,我们必须确保两个sql都执行完毕,转账才算完成,如果第一个sql执行完,在执行第二个sql之前,出现严重问题了(程序崩溃,主机断电…),这时候就会使数据库中的内容出错。你的小钱钱可能就会不翼而飞了。

为了避免出现“转账转一半”这样的问题,于是就有了事务。
所谓事务,就相当于是把 多个要执行的sql,打包成一个“整体”,这个“整体”在执行过程中就能够做到,要么整个都执行完,要么就一个都不执行,就可以避免出现上述转账一半的中间状态。

回滚

以上的“一个都不执行”不是这些sql真的没执行,而是执行一半,发现出错的时候,数据库会自动进行“还原操作”,相当于把前面执行过的sql,给进行“撤销”,最终的效果看起来好像就是一个都没执行。 这样的机制,称为“回滚”(rollback)。

  • 举个例子方便理解:
    回滚类似于,我上淘宝买个东西,货拿到手后,我不满意,我就退货~
    商家就会把这个货,重新进行包装,做成好像从来没有卖出去一样,这样就可以继续卖给其他人了。
    重新进行包装的过程,就可以看成是回滚。

同时,也把事务支持的上述的“特性”称为“原子性”(过去人们认为“原子”就是不可拆分的最小单位)。

  1. 数据库是如何知道要怎么回滚呢,如何知道前面的sql做出了啥样的修改呢?

    • 其实,数据库内部存在一系列的“日志体系”,记录在文件中。(把记录存到文件中,既可以应对“程序崩溃”,也能够应对“主机掉电”)。当开启事务的时候,此时每一步执行的sql,都会记录在日志体系中,后续如果需要回滚,就可以参考之前记录的内容,来进行还原。
      在这里插入图片描述
  2. 那么问题来了,drop database这样的操作能不能回滚呢?

    • 不能的,回滚操作只是针对“事务来说的”,开启事务之后,就会记录回滚日志,事务执行过程中,如果出现问题,就会自动触发回滚…(开启事务之后,一个事务内,虽然是执行多个sql,但执行的内容也不能太多…)
      一方面,drop database这样的操作不能放到事务中去执行,
      另一方面,这个操作也不算执行出错,而算是“正确执行了sql”。

事务最核心的特性,就是“原子性”,能够解决的问题,就是批量执行sql的问题。

开启事务的sql语句

-- 开启事务
start transaction;-- 其他sql
...-- 提交事务(告诉服务器,over!!)
commit;

但是一般在实际开发中不会使用上述sql
实际开发都是通过“代码”的方式来开启事务,批量执行的…

事务的基本特性

关于事务,在面试中,除了问你基本的概念(上面的内容),还会考察到一个比较麻烦的东西:事务的基本特性。

事务涉及到4个核心特性

  1. 原子性(最重要的特性)
  2. 一致性(事务执行前和执行后,数据库中的数据一定都是合法的数据,不会出现非法的临时结果的状态)
  3. 持久性,事务执行完毕之后,就会修改硬盘上的数据,事务都是会持久生效的。
  4. 隔离性 (非常不好解释)隔离性,描述了 多个事务 并发执行 的时候,相互之间产生的影响是怎样的。如果这些同时执行的事务,恰好也是针对同一个表来进行一些增删改查,此时就可能会引入一些问题。
    1. 脏读
    2. 不可重复读
    3. 幻读问题

并发执行介绍:MySQL是一个“客户端-服务器”结构的程序,一个服务器,通常会给多个客户端同时提供服务,因此很可能,这多个客户端,就同时给这个服务器提交事务来执行,与之相对,服务器就需要同时执行这多个事务,此时就是“并发执行”。

我们来一个一个介绍,可能会有一些烧脑。

  1. 脏读
    在这里插入图片描述

    • 有两个事务 A 和 B 并发执行,其中事务 B 在针对某个表的数据进行修改,B 执行过程中,A也去读取这个表的数据,当A读完之后,B把表里的数据又改成别的,这就导致A读到的数据,就不是最终的“正确数据”,而是读到了临时性的“脏数据”。
    • 举个例子方便理解,假设我是一个老师,我在准备下节课要讲的内容,于是我就准备一个代码 class Student{ … } 。此时,有一个同学,暗中观察,看到了,我这里写了一个class Student,里面有一个id,有一个name,有score…看了一会,就溜了~
    • 当同学走了之后,我想了一下,又对代码做出来修改,把id 改成 studentId,name 改成 studentName,score 改成 studentScore,当后续上课的时候,这个之前看我屏幕的同学,就发现,老师不讲武德,讲的代码和之前他看到的怎么就不一样了呢?

如何解决上述问题呢?

  • 很简单,我和同学们,约定好,我写代码的时候,你们不要看我的屏幕,如果你们想预习下节课的内容,可以来看我的“码云”,我会把修改好的代码,最终提交到码云上。我在修改的时候,同学们不能读,称为“给写操作加锁”。
  1. 不可重复读
    接着上个例子,我已经和同学们约定好,同学们不会看我的屏幕了,而是去我的码云上看代码。

    有一天,我写了一些代码,提交到码云上了,此时有一些同学正在码云上看我的代码,就在他们看的过程中,我发现了,我刚才的提交的代码中有问题,于是我就修改了一下代码,重新提交一次

    此时,以同学们的视角看,代码看着看着,突然就变样了~

    这个问题,就是“不可重复读”

    此时有三个事务ABC,首先事务A执行一个修改操作,A执行完毕的时候,提交数据,接下来事务B执行,事务B读取刚才A提交的数据…在B读取的过程中,又来了一个事务C,C又对刚才A修改的数据再次做出了修改,此时对于B来说,后续再读取这个数据,读到的结果就和第一次读到的结果是不一样的。
    以上过程就叫做“不可重复读”。

如何解决不可重复读?

  • 和上面的解决方法类似,再与同学们进行约定~~
    同学们通过码云看我的代码的时候,我不能修改。(给读操作加锁,一个事务在读取数据的过程中,其他的事务不能修改它正在读的数据)
  1. 幻读
    相当于不可重复读的“特殊情况”
    我与同学们已经约定好了,我在写代码的时候,同学们不能读,同学读代码的时候,我不能去修改(针对同一个代码才有这样的限制)。
    同学们在读studen的时候,此时我创建了另一个代码,Teacher进行编写。此时,站在同学的角度,看到的情况就是,虽然studen没变,但读着读着突然冒出来一个Teacher。
    有一个事务A在读取数据,读的过程中,另外一个事务B,新增了\删除了一些其他的数据…此时站在A的视角,多次读取的数据内容虽然一样,但是“结果集”不同。结果集不同,是否算是问题,需要根据情况来定。

如何解决幻读问题?

  • 还是继续和同学们约定,如果有同学正在读代码,我就不做任何操作。
    这样的操作我们称为“串行化”
    比如多个客户端,同时提交了多个事务过来,但是服务器一个一个的执行事务(执行完第一个事务,再执行第二个,再执行第三个…)

总结一下涉及到的三个问题

在并发执行事务的过程中,涉及到了三个问题:

  1. 脏读
  2. 不可重复读
  3. 幻读
    这三个问题与隔离性有啥关系呢?
    在MySQL中提供了四个隔离级别,可以通过配置文件来设置当前服务器的隔离级别是哪个级别。设置不同的隔离级别,就会使事务之间的并发执行的影响产生不同的差别,从而会影响到上述三个问题是否会发生~
    1. read uncommitted读未提交
      这种情况下,一个事务可以读取另一个事务未提交的数据
      此时,就可能会产生脏读,不可重复读,幻读三种问题
      但是此时,多个事务并发执行程度是最高的,执行速度也是最快的(并发程度越高,速度就越快,并发程度越低,速度就越慢)
    2. read committed 读已提交
      这种情况下,一个事务只能读取另一个事务提交之后的数据(给写操作加锁了)
      此时,可能会产生不可重复读,幻读问题(脏读问题解决了)
      此时并发程度降低,执行速度会变慢,但是事务之间的隔离性提高了(事务之间的相互影响变小了,得到的数据更准了~)
    3. repeatable read 可重复读 (MySQL默认的隔离级别)
      这个情况下,相当于是给写操作和读操作都加锁了
      此时,可能产生幻读问题,解决了脏读和不可重复读问题
      并发程度进一步降低,执行速度进一步变慢,事务之间的隔离性,进一步提高了
    4. serializable 串行化
      此时,所有的事务都是在服务器上一个接一个的执行的
      此时,解决了脏读,不可重复读,幻读问题
      并发程度最低,执行速度最慢,隔离性最高,数据最准确~

在这里插入图片描述

在写代码时我们该如何选哪个隔离级别呢?

  • 答:根据需要,看是需要执行速度快,还是需要数据比较准,从而选择合适的隔离级别,快和准无法兼得。

☁️结语

请给自己些耐心,不要急于求成。
山外青山楼外楼,莫把百尺当尽头。
保持空杯心态加油努力吧!


都看到这里啦!真棒(*^▽^*)

可以给作者一个免费的赞赞吗,这将会鼓励我继续创作,谢谢大家

如有纰漏或错误,欢迎指正


这篇关于MySQL经典面试题:谈一谈你对事务的理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1067926

相关文章

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

mysql8.0.43使用InnoDB Cluster配置主从复制

《mysql8.0.43使用InnoDBCluster配置主从复制》本文主要介绍了mysql8.0.43使用InnoDBCluster配置主从复制,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录1、配置Hosts解析(所有服务器都要执行)2、安装mysql shell(所有服务器都要执行)3、

k8s中实现mysql主备过程详解

《k8s中实现mysql主备过程详解》文章讲解了在K8s中使用StatefulSet部署MySQL主备架构,包含NFS安装、storageClass配置、MySQL部署及同步检查步骤,确保主备数据一致... 目录一、k8s中实现mysql主备1.1 环境信息1.2 部署nfs-provisioner1.2.

MySQL中VARCHAR和TEXT的区别小结

《MySQL中VARCHAR和TEXT的区别小结》MySQL中VARCHAR和TEXT用于存储字符串,VARCHAR可变长度存储在行内,适合短文本;TEXT存储在溢出页,适合大文本,下面就来具体的了解... 目录一、VARCHAR 和 TEXT 基本介绍1. VARCHAR2. TEXT二、VARCHAR

MySQL中C接口的实现

《MySQL中C接口的实现》本节内容介绍使用C/C++访问数据库,包括对数据库的增删查改操作,主要是学习一些接口的调用,具有一定的参考价值,感兴趣的可以了解一下... 目录准备mysql库使用mysql库编译文件官方API文档对象的创建和关闭链接数据库下达sql指令select语句前言:本节内容介绍使用C/

mybatis直接执行完整sql及踩坑解决

《mybatis直接执行完整sql及踩坑解决》MyBatis可通过select标签执行动态SQL,DQL用ListLinkedHashMap接收结果,DML用int处理,注意防御SQL注入,优先使用#... 目录myBATiFBNZQs直接执行完整sql及踩坑select语句采用count、insert、u

MySQL之搜索引擎使用解读

《MySQL之搜索引擎使用解读》MySQL存储引擎是数据存储和管理的核心组件,不同引擎(如InnoDB、MyISAM)采用不同机制,InnoDB支持事务与行锁,适合高并发场景;MyISAM不支持事务,... 目录mysql的存储引擎是什么MySQL存储引擎的功能MySQL的存储引擎的分类查看存储引擎1.命令

Spring的基础事务注解@Transactional作用解读

《Spring的基础事务注解@Transactional作用解读》文章介绍了Spring框架中的事务管理,核心注解@Transactional用于声明事务,支持传播机制、隔离级别等配置,结合@Tran... 目录一、事务管理基础1.1 Spring事务的核心注解1.2 注解属性详解1.3 实现原理二、事务事

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe