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

相关文章

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

[MySQL表的增删改查-进阶]

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 💻💻💻数据库约束 🔭🔭🔭约束类型 not null: 指示某列不能存储 NULL 值unique: 保证某列的每行必须有唯一的值default: 规定没有给列赋值时的默认值.primary key:

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝