• MySQL-事务的概念


    目录

    一、概述

    1.1 基本概念

    1.2 ACID特性

    1.3 事务的状态

     二、事务的使用

    2.1 显式事务

    2.2 隐式事务

    2.3 隐式提交数据的情况

    三、事务的隔离级别

    3.1 数据并发中的问题

    3.2 SQL中的隔离级别

    3.3 MySQL支持的隔离级别


          在 MySQL 中,只有InnoDB 是支持事务的。

    一、概述

    1.1 基本概念

            事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态

            事务处理的原则:保证所有事务都作为 一个工作单元 来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交( commit ),那么这些修改就 永久 地保 存下来;要么数据库管理系统将 放弃 所作的所有 修改 ,整个事务回滚( rollback )到最初状态

    1.2 ACID特性

            原子性atomicity): 原子性是指事务是一个不可分割的工作单位,要么全部提交,要么全部失败回滚

            最经典的例子就是转账问题,A给B转账,转的过程中系统出了问题:A的余额扣了但B的余额没有增加,就不满足原子性。

            一致性consistency):一致性是指事务执行前后,数据从一个 合法性状态 变换到另外一个 合法性状态 。这种状态 是 语义上 的而不是语法上的,跟具体的业务有关。满足预定约束的状态就叫做合法状态。通俗一点,这状态是由自己来定义的(比如满足现实世界中的约束)。满足这个状态,数据就是一致的,不满足这个状态,数据就是不一致的!如果事务中的某个操作失败了,系统就会自动撤销当前正在执行的事务,返回到事务操作之前状态

            对于上面的例子,A和B的总余额按规定应该是一样的,但现实却是变少了,就违背了一致性

            隔离性isolation): 事务的隔离性是指一个事务的执行 不能被其他事务干扰 ,即一个事务内部的操作使用的数据并发 的 其他事务是隔离的,并发执行的各个事务之间不能互相干扰

            持久性durability): 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是 永久性的 ,接下来的其他操作和数据库 故障不应该对其有任何影响。

            持久性是通过 事务日志 来保证的。日志包括了 重做日志回滚日志 。当我们通过事务对数据进行修改 的时候,首先会将数据库的变化信息记录到重做日志中,然后再对数据库中对应的行进行修改。这样做 的好处是,即使数据库系统崩溃,数据库重启后也能找到没有更新到数据库系统中的重做日志重新执行,从而使事务具有持久性

    1.3 事务的状态

            活动的(active) 事务对应的数据库操作正在执行过程中时,我们就说该事务处在 活动的 状态。

            部分提交的(partially committed) 当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并 没有刷新到磁盘 时,我们就说该事务处在 部分提交的 状态。

            失败的(failed) 当事务处在 活动的 或者 部分提交的 状态时,可能遇到了某些错误(数据库自身的错误、操作系统错误或者直接断电等)而无法继续执行,或者人为的停止当前事务的执行,我们就说该事务处在 失败的 状态。

            中止的(aborted) 如果事务执行了一部分而变为 失败的 状态,那么就需要把已经修改的事务中的操作还原到事务执行前的状态。换句话说,就是要撤销失败事务对当前数据库造成的影响。我们把这个撤销的过程称之为 回滚 。当 回滚 操作执行完毕时,也就是数据库恢复到了执行事务之前的状态,我们就说该事务处在了 中止的 状态。 

            提交的(committed) 当一个处在 部分提交的 状态的事务将修改过的数据都 同步到磁盘 上之后,我们就可以说该事务处在了 提交的 状态。

     二、事务的使用

    2.1 显式事务

            步骤:

            1..START TRANSACTION 或者 BEGIN ,作用是显式开启一个事务。

                    START TRANSACTION可跟修饰符

            ① READ ONLY :标识当前事务是一个 只读事务 ,也就是属于该事务的数据库操作只能读取数据,而不 能修改数据。

            ② READ WRITE :标识当前事务是一个 读写事务 ,也就是属于该事务的数据库操作既可以读取数据, 也可以修改数据。

            ③ WITH CONSISTENT SNAPSHOT :启动一致性读。

            2.一系列事务中的操作(主要是DML,不含DDL)

            3.提交事务 或 中止事务(即回滚事务)

    1. # 提交事务。当提交事务后,对数据库的修改是永久性的。
    2. COMMIT;
    3. # 回滚事务。即撤销正在进行的所有没有提交的修改
    4. ROLLBACK;
    5. # 将事务回滚到某个保存点。
    6. ROLLBACK TO [SAVEPOINT]

            关于savepoint的操作

    1. SAVEPOINT 保存点名称 #创建保存点,方便回滚,可存在多个
    2. RELEASE SAVEPOINT 保存点名称 #删除某个保存点

    2.2 隐式事务

            MySQL中有一个系统变量 autocommit ,默认打开的。

            如果想关闭这种 自动提交 的功能,可以使用下边两种方法之一:

                    1.显式使用 START TRANSACTION 或者 BEGIN 语句开启一个事务。这样在本次事务提交或者回滚前会暂时关闭掉自动提交的功能。

                    2.把系统变量 autocommit 的值设置为 OFF

    SET autocommit = OFF; #对DML有效,对DDL无效

    2.3 隐式提交数据的情况

            数据定义语言(Data definition language,缩写为:DDL)-CREATE、ALTER、DROP

            隐式使用或修改mysql数据库中的表

            事务控制或关于锁定的语句

             当我们在一个事务还没提交或者回滚时就又使用 START TRANSACTION 或者 BEGIN 语句开启了 另一个事务时,会 隐式的提交 上一个事务。即:

            ② 当前的 autocommit 系统变量的值为 OFF ,我们手动把它调为 ON 时,也会 隐式的提交 前边语句所属的事务。

            ③ 使用 LOCK TABLES 、 UNLOCK TABLES 等关于锁定的语句也会 隐式的提交 前边语句所属的事务。

            加载数据的语句 -LOAD DATA

            关于MySQL复制的一些语句-START SLAVE、STOP SLAVE、RESET SLAVE

            其它的一些语句...

    三、事务的隔离级别

            事务有 隔离性 的特性,理论上在某个事务 对某个数据进行访问 时,其他事务应该进行 排队 ,当该事务提交之后,其他事务才可以继续访问这个数据。但是这样对 性能影响太大 ,我们既想保持 事务的隔离性,又想让服务器在处理访问同一数据的多个事务时性能尽量高些 ,那就看二者如何权衡取舍了。

    3.1 数据并发中的问题

            访问相同数据的事务在不保证串行执行 (也 就是执行完一个再执行另一个)的情况下可能会出现的问题:

    1. 脏写( Dirty Write ) 对于两个事务 Session A、Session B,如果事务Session A 修改了 另一个 未提交 事务Session B 修改过 数据,那就意味着发生了 脏写

    2. 脏读( Dirty Read ) 对于两个事务 Session A、Session B,Session A 读取 了已经被 Session B 更新 但还 没有被提交 的字段。 之后若 Session B 回滚 ,Session A 读取 的内容就是 临时且无效 的。 

    3. 不可重复读( Non-Repeatable Read ) 对于两个事务Session A、Session B,Session A 读取 了一个字段,然后 Session B 更新 了该字段。 之后 Session A 再次读取 同一个字段, 值就不同了。那就意味着发生了不可重复读。

    4. 幻读( Phantom ) 对于两个事务Session A、Session B, Session A 从一个读取 了一个字段, 然后 Session B 在该表中 插入 了一些新的行。 之后, 如果 Session A 再次读取 同一个表, 就会多出几行。那就意味着发生了幻读。

    3.2 SQL中的隔离级别

             对于上面的问题,严重性排序;脏写 > 脏读 > 不可重复读 > 幻读

             我们愿意舍弃一部分隔离性来换取一部分性能在这里就体现在:设立一些隔离级别,隔离级别越低,并发问题发生的就越多。 SQL标准 中设立了4个 隔离级别 :

    READ UNCOMMITTED读未提交,在该隔离级别,所有事务都可以看到其他未提交事务执行结果。不能避免脏读、不可重复读、幻读

    READ COMMITTED :读已提交,它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。可以避免脏读,但不可重复读幻读问题仍然存在。

    REPEATABLE READ :可重复读,事务A在读到一条数据之后,此时事务B对该数据进行了修改提交,那么事务A再读该数据,读到的还是原来的内容。可以避免脏读、不可重复读,但幻读问题仍 然存在。这是MySQL的默认隔离级别。

    SERIALIZABLE可串行化,确保事务可以从一个表中读取相同的行。在这个事务持续期间,禁止其他事务对该表执行插入、更新删除操作。所有的并发问题都可以避免,但性能十分低下。能避免脏读、不可重复读幻读

             因为脏写的问题太严重了,不论是哪种隔离级别,都不允许脏写的情况发生。

    3.3 MySQL支持的隔离级别

            MySQL默认隔离级别REPEATABLE READ可重复读,我们可以手动修改事务隔离级别

    1. SHOW VARIABLES LIKE 'transaction_isolation'; #查看隔离级别
    2. #设置隔离级别
    3. SET [GLOBAL|SESSION] TRANSACTION_ISOLATION = '隔离级别'
    4. #其中,隔离级别格式:
    5. > READ-UNCOMMITTED
    6. > READ-COMMITTED
    7. > REPEATABLE-READ
    8. > SERIALIZABLE
    9. #GLOBAL关键字是在全局范围影响,SESSION是在会话范围影响

  • 相关阅读:
    【每日一题】 和为 K 的子数组
    【Leetcode】剑指Offer 21:调整数组顺序使奇数位于偶数前面
    【深度学习】用Pytorch完成MNIST手写数字数据集的训练和测试
    Llama3-8B+ LLaMA-Factory 中文微调
    取Dataset子集(pytorch)
    Android 性能优化之黑科技开道(二)
    工业智能网关BL110应用之三十三: 如何连接配置华为云服务器
    SpringBoot 整合 JustAuth 实现第三方登录 | gitee登录
    javascript复习之旅 9.1 从0到1认识`call apply`
    完成Zookeeper集群部署
  • 原文地址:https://blog.csdn.net/weixin_62427168/article/details/125612144