• 数据库事务到底是什么?


    目录

    场景(两个用户之间进行转账操作):

     需要的操作步骤:

    事务

    事务的四大特性:

    一、原子性

    (1)什么是回滚操作

    (2)数据库恢复操作,如何知道数据恢复如初?(如何知道数据回滚正确)

     二、一致性

     三、持久性 

     四、隔离性(重点)

    1. 脏读

     解决脏读:

    2. 不可重复读

     解决不可重复读:

    3. 幻读

     解决幻读:

    4. 区分不可重复读和幻读

    总结并发处理事务的三个典型问题:

    MySQL内置的机制(对应上述几种隔离级别)


    前言

        数据库事务的相关知识也是面试常考的问题,这篇文章介绍为什么要有事务以及事务的概念,事务的特性,以及数据库基于隔离性(特性)产生并发执行所引出的问题,如何解决这个问题。

    场景(两个用户之间进行转账操作):

        用户A要给用户B进行转账,就要操作数据库中的数据表;如下图:

     需要的操作步骤:

    (1)update acccount set balance = balance - 500 where id = 1;

    (2)update account set balance = balance + 500 where id = 2;

         假设在执行转账的过程中,执行完sql语句(1)之后,数据库崩溃了/主机宕机了,此时用户1的钱扣了,但是2的钱没到账。

        那针对这样的问题数据库该如何解决?

    事务

        事务就是为了解决上述问题,事务的本质就是把多个sql语句给打包成一个整体,要么全部执行成功,要么就一个都不执行,而不会出现 ”执行一半“ 这样的中间状态。(这就是事务出现的初心)

    事务的四大特性:

    1. 原子性(回滚)上述 ”一点都补执行“ 不是真正的没有执行,而是在中间状态进行了 ”回滚“ 操作
    2. 一致性

    数据进行修改之后,要和之前的数据能够对应上。

    3. 持久性数据持久保存
    4.隔离性(重点介绍)这个特性是为了解决事务 ”并发执行“ 引起的问题

    一、原子性

        原子性是数据库设计事务的初心,这点要清楚,上述场景出现后,事务就是为了解决这个问题,

    事务的本质就是把多个要执行的sql语句打包成一个整体,使事务变成要执行的一个基本单位,不能再分。(要么就不执行这个事务,要么就一次执行完事务)

    (1)什么是回滚操作

        当一个事务执行到一半时,此时数据库崩溃了,数据库在下一次启动时就要把未执行完的数据恢复到之前的状态,这个恢复数据的操作,称为 ”回滚“。

      注:上述 ”事务要么一点都不执行“,不是真正的没有执行,而是说看起来好像没有执行一样,事务执行一半,数据库崩溃,数据库再次启动后,此时选择恢复数据,就是把未执行完的数据还原成了未执行之前的状态了。

     (2)数据库恢复操作,如何知道数据恢复如初?(如何知道数据回滚正确)

        数据库中有专门记录事务的日志,用日志来记录事务的操作步骤。日志就是写到磁盘上的文件,断电之后,日志也不会消失,所以数据库重新启动后,就把数据进行正确的恢复。

        注:正因如此,使用事务后,执行sql语句的开销也就更大了,效率也更低了。

     二、一致性

             执行sql语句前后的数据要能够保证正确性。

        数据执行的前后,数据时靠谱的,也就是能够和正确的操作数据能够对应上,如:用户1给用户2转账500,此时2的账户上就多了500,不能多出来5000,50000。

        没有引入事务的时候,这个 特性就是要必须保证的,有了事务之后,这个特性也不能丢失。

     三、持久性 

        事务修改的内容是写到硬盘上的,持久存在的,数据库重启之后,也能保证数据没有丢失。

        还是转账这个场景,此时如果数据库崩溃之后,所有的用户的余额都是保存在数据库中的,此时不能说数据库崩了,用户的钱也跟着一起没了,这是不靠谱的,所以说数据库中的数据是持久保存的。

     四、隔离性重点

        解决事务 “ 并发”执行引起的问题。

        注:数据库是客户端服务器这样的一个结构,数据库也是服务器;就有可能出现多个客户端同时提交给数据库多个事务,此时数据库就需要并发处理多个事务。

        如果是修改的同一张表中的同一个数据,此时就有可能出现问题,如:多个客户尝试对同一个账户进行转账操作,就有可能把这个数据搞乱。

        并发执行事务可能产生的问题:

    (1)脏读问题
    (2)不可重复读问题
    (3)幻读问题

    1. 脏读

        一个事务 正在对数据进行修改的过程中,还没有提交数据之前,另外一个事务B也对同一个数据进行读取,此时B的读数据操作称为 “脏读”,读到的数据也是称为 “脏数据”,(脏的意思是无效,就是读到的数据是无效的数据)

     解决脏读:

        mysql引入“给读操作加锁” 的机制   

    (多线程中同步锁问题,详解可以看这篇文章:锁策略和 cas 优化过程_良月初十♧的博客  )

    加锁之后写操作和读操作就不能并发执行了(不能同时进行),给写操作加锁,就降低了并发的程度(也降低了效率),提高了隔离性(提高了数据的准确性)。

    2. 不可重复读

        事务1已经提交了数据,此时事务2开始去读数据,在读的过程中,事务3又提交了新的数据,此时意味着同一个事务2之内,多次读数据读出来的结果是不一样的(预期是一个事务中,多次读取的结果是一样的),此时就称为 “不可重复读”。

     解决不可重复读:

        给读操作也进行加锁,通过给读加锁,又进一步降低了事务的并发处理能力(处理效率也降低),提高事务的隔离性(数据的准确性又提高了)。

    3. 幻读

        在给读和写数据加锁的前提下,一个事务两次读取同一个数据,发现读取的数据内容是一样的,但是结果集不一样,此时称为 “幻读”。

     解决幻读:

        数据库使用串行化的方式来解决幻读,彻底放弃并发执行,一个接着一个的串行的处理事务,此时并发程度是最低的(效率是最慢的),隔离性是最高的(数据的准确性也是最高的)。

    4. 区分不可重复读和幻读

        不可重复读是指事务多次读取数据,预期读到的数据内容是一样的,但是结果是多次读取数据,数据的内容是不一样的。

        而幻读是指一个事务多次读取数据,预期是读到的数据是一样多的,没有新数据集的产生,但是结果是一个事务多次读取数据,内容虽然是一样的,但是在原有的基础上多了一部分结果集。

    总结并发处理事务的三个典型问题:

    1. 脏读问题给读加锁
    2. 不可重复读问题给写加锁
    3. 幻读彻底执行串行化

    MySQL内置的机制(对应上述几种隔离级别)

    1. read uncommitted读未提交,没有进行任何话锁限制并发最高(效率最高),隔离性最低(数据的准确性最低)在处理并发事务时,同时有脏读,不可重复读,幻读问题。
    2. read committed读已提交,给写加锁了,并发程度 降低,隔离性提高了(数据准确性提高)解决了脏读问题,但是不可重复读和幻读问题还存在。

    3. repeatable read

    可重复读,给读进行加锁,并发程度进一步降低,隔离性进一步提高(这也是Mysql 默认事务隔离级别)解决了不可重复读问题,但是幻读问题还存在。
    4. serializable事务串行化,并发程度最低,隔离性最高此时不存在上述三个问题,数据的准确性也是最高的

        可以通过修改MySQL的配置文件来设置当前MySQL是工作在哪种情况下。

  • 相关阅读:
    mysql中添加字段
    SpringMVC之WEB-INF下页面跳转&@ModelAttribute&IDEA tomcat控制台中文乱码问题处理
    37-5 基于时间的盲注 SQL 注入 PoC 的 Python 编写
    java的stream让我灵光一现
    浏览器窗口尺寸相关的 API 整理图
    【OpenCV】角点检测、特征点提取(Harris、Shi-Tomas、SIFT、SURF、FAST、ORB)学习笔记
    短剧出海火爆,Flat Ads独家流量助泛娱乐赛道App迅速获客增长
    java毕业生设计药房药品采购集中管理系统计算机源码+系统+mysql+调试部署+lw
    JVM指令手册
    java程序员必会-远程debug
  • 原文地址:https://blog.csdn.net/weixin_64874291/article/details/130910762