• MySQL事务(清晰易懂)


    简介:事务是一组操作的集合,它是不可分割的工作单位,这组操作要么同时成功,要么同时失败。常见的业务的就有银行转账,一方转账,余额减少,一方收款,余额增加。若在转账时,发生故障,就可能出现一方余额减少,另一方余额并未变化,利用事务,就可以很好地避免这个问题。



    一、事务四大特性📌

    事务主四大特性有: 原子性(Atomicity)、一致性(Consistenc)、隔离性(Isolation)、持久性(Durability)

    1.原子性(Atomicity):
      事务是不可分割的最小单元,事务其中的对数据修改的操作要么全部执行,要么完全不执行

    2.一致性(Consistency):
      事务完成时,数据库的所有数据都必须处于一致性状态。这里的一致性不是指操作后数据原封不动。可以这样来看:
      转账方余额2000,收款方余额2000,两方总金额4000,转账金额为1000。
      若转账中途出了故障,转账方余额减少了,变为1000,但收款方未收到钱,仍为2000,这时两方总金额只有3000,就不满足一致性,就需要回滚事务,回到两方转账前余额都为2000的状态。
      若转账完成,转账方金额为1000,收款方金额为3000,两方总金额4000,这时就满足了一致性,事务执行完成并提交。

    3.隔离性(Isolation):
      一个事务内部的操作及正在操作的数据必须封锁起来,不被其它企图进行修改的事务看到。数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行

    4.持久性(Durability):
      事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。事务完成后,它对数据库中数据的改变就会写入硬盘中,永久地保存。

    二、事务的操作📌

    1.查看事务提交方式
    SELECT @@autocommit;
    默认值为1,表示执行完SQL语句后自动提交,若在中间发生了错误,则会提交错误之前的所有SQL

    2.设置事务提交方式
    SET @@autocommit = 0;
    @@autocommit值为0表示手动提交事务。

    3.提交事务
    COMMIT;
    在开启事务的SQL语句执行后,手动COMMIT提交事务。注意,一旦COMMIT后就不能回滚事务,这也对应了事务特性的最后一点----持久性

    4.回滚事务
    ROLLBACK;
    在事务执行完毕,没有提交的时候,可以使用ROLLBACK进行回滚事务,撤销对数据的操作。

    5.开启事务
    START TRANSACTIONBEGIN
    开启事务后,后面对数据库的修改操作就需要手动提交(COMMIT)和回滚(ROLLBACK)。

    三、事务操作案例📌

    account表模拟转账
    在这里插入图片描述
      选中同时执行以下SQL语句,中间加了一行汉字模拟转帐中出现了错误(第三行SQL是正确的,只是工具识别到第二行有错,导致第三行也爆红),第一行是让张三余额减少,第三行是让李四余额增加
    在这里插入图片描述

       执行后:
    在这里插入图片描述
      这里可以看到只修改了张三的余额,这是为什么呢?
      因为MySQL默认事务提交方式为1(@@autocommit = 1),并且默认把每条SQL语句当成独立的一个事务,遇到错误时就终止执行。总的来说就是没把这三条语句当作一个事务,以至不能同时成功和同时失败

      要想解决,可以手动开启事务,并对事务进行提交和回滚:
    !![](https://img-blog.csdnimg.cn/c849e1a287504c39ba4c2a73f5c3e2a1.png
    注意:利用SQL开启事务后的回滚和提交都是手动的,MyBatis等框架开启事务后是自动提交和回滚

    四、并发事务问题📌

    并发事务问题就是多个事务同时执行的时候出现的问题

    1.脏读:一个事务读到另一个事务还没提交的数据。
      例如事务A中要查询“data”字段,事务B要对“data”字段进行修改,在事务B未提交前,事务A查询“data”就会出现脏读问题。简言之就是事务A查到的数据是修改前的数据。

    2.不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同。
      例如事务A中要查询两次“data”字段,事务B要对“data”字段进行修改,事务A查询第一次查询到“data”后,事务B对“data”进行修改并提交了,事务A第二次查询就会查到与第一次不同的结果。简言之就是多次查询同一字段出现不同的结果。

    3.幻读:一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在。
      例如事务A查询id(主键)为5的记录不存在,然后插入一条id为5的数据,事务B插入一条id为5的数据。在事务A刚查询到id为5的记录不存在的时候,事务B提交了,事务A再去插入就会失败。

    五、事务隔离级别📌

    事务隔离级别就是多个事务执行时,互不影响的程度,事务隔离级别不同,出现的事务并发问题就不一样。

    事务隔离级别主要分为四类:
    1.Read uncommitted(读未提交):
      如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。这样就避免了更新丢失,却可能出现脏读,也就是说事务B读取到了事务A未提交的数据
    2.Read committed(读提交):
      如果是一个读事务(线程),则允许其他事务读写,如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
    3.Repeatable read(可重复读取):
      可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。
    4.Serializable(可序化):
      提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读
    在这里插入图片描述
    隔离级别Serializable>Repeatable read>Read committed>Read uncommitted
    注意:隔离级别越高,数据越安全,但是性能越低,在开发时应根据实际情况选择合适的隔离级别。

    事务隔离级别操作:
    1.查看事务隔离级别:
    SELECT @@TRANSACTION_ISOLATION;
    默认级别为Repeatable read。

    2.设置事务隔离级别:
    SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL 隔离级别;
    SESSION表示当前设置的隔离级别只对当前会话有效,即当前建立的数据库连接。GLOBAL表示全局有效。

    如有不足之处,欢迎指正。

  • 相关阅读:
    服务器快速搭建AList集成网盘网站【宝塔面板一键部署AList】
    Qt-FFmpeg开发-回调函数读取数据(8)
    GeForce RTX 2080显卡驱动安装(linux系统)
    Linux系统权限和用户相关操作
    2023年AI生成音频研究报告
    朋友圈大佬都去读研了,这份备考书单我码住了(文末赠书)
    如何使用lxml判断网站公告是否更新
    Go 语言 context 都能做什么?
    数据库优化的记录
    在路径上没有找到 “java.lang.Math8 “类
  • 原文地址:https://blog.csdn.net/Easenyang/article/details/126787343