• 〖Python 数据库开发实战 - MySQL篇㉛〗- 事务机制的概念与特性


    万叶集
    🎉 隐约雷鸣,阴霾天空。 🎉
    🎉 但盼风雨来,能留你在此。 🎉


    前言
    ✌ 作者简介:渴望力量的哈士奇 ✌,大家可以叫我 🐶哈士奇🐶 ,一位致力于 TFS - 全栈 赋能的博主 ✌
    🏆 CSDN博客专家认证、新星计划第三季全栈赛道 MVP 、华为云享专家、阿里云专家博主 🏆
    📫 如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
    💬 人生格言:优于别人,并不高贵,真正的高贵应该是优于过去的自己。💬
    🔥 如果感觉博主的文章还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主哦


    专栏系列(点击解锁)学习路线(点击解锁)知识定位
    🔥Python全栈白皮书🔥 零基础入门篇 以浅显易懂的方式轻松入门,让你彻底爱上Python的魅力。
    语法进阶篇 主要围绕多线程编程、正则表达式学习、含贴近实战的项目练习 。
    自动化办公篇 实现日常办公软件的自动化操作,节省时间、提高办公效率。
    自动化测试实战篇 从实战的角度出发,先人一步,快速转型测试开发工程师。
    数据库开发实战篇 掌握关系型与非关系数据库知识,提升数据库实战开发能力。
    爬虫入门与实战 更新中
    数据分析篇 更新中
    前端入门+flask 全栈篇 更新中
    django+vue全栈篇 更新中
    拓展-人工智能入门 更新中
    网络安全之路 踩坑篇 记录学习及演练过程中遇到的坑,便于后来居上者
    网安知识扫盲篇 三天打鱼,不深入了解原理,只会让你成为脚本小子。
    vulhub靶场漏洞复现 让漏洞复现变得简单,让安全研究者更加专注于漏洞原理本身。
    shell编程篇 不涉及linux基础,最终案例会偏向于安全加固方向。 [待完结]
    WEB漏洞攻防篇 2021年9月3日停止更新,转战先知社区等安全社区及小密圈
    渗透工具使用集锦 2021年9月3日停止更新,转战先知社区等安全社区及小密圈
    点点点工程师 测试神器 - Charles 软件测试数据包抓包分析神器
    测试神器 - Fiddler 一文学会 fiddle ,学不会倒立吃翔,稀得!
    测试神器 - Jmeter 不仅是性能测试神器,更可用于搭建轻量级接口自动化测试框架。
    RobotFrameWork Python实现的自动化测试利器,该篇章仅介绍UI自动化部分。
    Java实现UI自动化 文档写于2016年,Java实现的UI自动化,仍有借鉴意义。
    MonkeyRunner 该工具目前的应用场景已不多,文档已删,为了排版好看才留着。

    在这里插入图片描述


    该章节开始我们将学习一个非常重要的知识点,那就是 “数据库的事务机制” 。在之前的章节介绍 MySQL 历史的时候提到过,MySQL 是在 5.0 版本之后引入的事务机制 才正式的打开了企业市场的。接下来就了解一下 “事务机制” 对于一个数据库产品来说,到底有多重要。



    🐳 事务机制所解决的问题


    在学习 "事务机制" 之前,我们先来看一下 "事务机制" 解决了哪些问题?


    • 避免写入的行为直接操作数据文件。
      • 以现实场景为例:当我们在修改一份非常重要的文件时,通常是先备份一下,然后在副本里面去修改文件;数据库领域亦是如此,如果 SQL 语句直接操作数据文件,这本身也是一件非常危险的事情。
      • 就比如说,当我们在执行 “UPDATE” 语句的时候,突然停电、或者服务器突然重启了,我们就无法知道有哪些记录被修改了,哪些记录没有被修改。如此的 “UPDATE” 语句执行的结果,与初衷是完全不一致的,那可就相当危险了(尤其是这种类似的突发事件)

    • 如果说使用的 “UPDATE、DELETE” 等 SQL 语句不是直接修改 数据文件 的话,那么又是如何实现 “修改、删除” 数据的呢?如何实现就和事务机制有关系了。
      • MySQL 共有 5种 日志文件,其中的 undo日志redo日志 与事务机制有关。
      • 这里的日志文件其实就相当于是数据文件 的副本,SQL 语句操作什么样的记录,MySQL 的数据库就会将这些记录拷贝到 undo日志 里面,然后 增、删、改、查 这些操作会记录在 redo日志 里面 。
      • 如果这些 SQL 语句的操作没有问题,最后会将 redo日志数据文件 进行同步,即使在同步过程中出现停电、死机、重启等问题,由于 redo日志 的存在,重启了 MySQL 数据库以后,继续完成这个同步就可以了。同步完成之后,修改的记录就会真正的写到 数据文件 里面了。

    MySQL 有了日志文件之后,对数据的修改不再是直接修改数据文件,而是在日志文件尝试去操作,没有问题的情况下在执行同步。就算是同步的时候遇到问题也没关系。重新启动数据库服务,继续完成同步就可以了。

    其实理解了 "undo" 与 "redo" 日志的作用,事务机制也就搞明白了一半了。



    🐳 事务机制(Transaction)


    • 事务机制也叫做 “Transaction”
    • 在数据库的使用者眼里, RDBMS(关系数据库管理系统)的核心就是 "SQL语句" + "事务"(ACID)。SQL 语句我们掌握的差不多了,接下来只剩下 "事务机制" 来攻破了。
    • 从宏观上来理解 "事务机制" :在 “事务机制” 下,所有的 SQL 语句 都被当做是一个整体,要么这些 SQL 语句全部执行成功,要么就全部执行失败。决不能出现,部分 SQL 语句成功,另一部分 SQL 语句失败的情况。
    • 在实际业务当中,“事务的这个特性是非常重要的”。

    以真实场景,网络购物为例。在正常的网上购物的一次交易中,其付款过程至少包括以下几步数据库操作:

    更新客户所购商品的库存信息
    
    保存客户付款信息--可能包括与银行系统的交互
    
    生成订单并且保存到数据库中
    
    更新用户相关信息,例如购物数量等等
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    正常的情况下,这些操作将顺利进行,最终交易成功,与交易相关的所有数据库信息也成功地更新。

    但是,如果在这一系列过程中任何一个环节出了差错,例如在更新商品库存信息时发生异常、该顾客银行帐户存款不足等,都将导致交易失败。

    一旦交易失败,数据库中所有信息都必须保持交易前的状态不变,比如最后一步更新用户信息时失败而导致交易失败,那么必须保证这笔失败的交易不影响数据库的状态--库存信息没有被更新、用户也没有付款,订单也没有生成。

    否则,数据库的信息将会一片混乱而不可预测。

    数据库的事务机制正是用来保证这种情况下交易的平稳性和可预测性的技术。因为它满足业务过程中每一个步骤必须成功,或者因为一个步骤的失败撤销流程里的全部操作。



    🐳 通过事务案例理解事务的原理


    • 将属于 10 部门中职位为 “MANGER” 的员工调往 20 部门,其他岗位的员工调往 30 部门,然后删除 10 部门 。
      • 分析:最终目的是删除 "10" 部门。
      • 分析:先将 10 部门中职位为 "MANGER" 的员工调往 20 部门; ---> 这是 "UPDATE" 语句
      • 分析:再将其他岗位的员工调往 30 部门; ---> 这也是 "UPDATE" 语句
      • 分析:最后再 删除 10 部门; ---> 这是 "DELETE" 语句

    在前面的章节,觉得在没有使用 "事务" 的情况下,也能够执行 "增、删、改、查" 这样的操作。这是因为 MySQL 默认情况下,执行一条 SQL 语句之前都会开启 "事务" 。等该 SQL 语句执行结束,就会提交事务,也就是让 "redo" 日志文件与数据文件做同步。

    继续执行下一条 SQL 语句,同样如此。先开启 "事务",执行 SQL,然后再提交 "事务" 。

    在面对一条 SQL 语句,这种自动提交 "事务" 的模式是没有问题的。

    但是我们现在所需要实现的这个案例,它并不是一条SQL语句能够完成。他需要先执行 "UPDATE" 语句,再执行 "DELETE" 语句。这两条语句必须要在同一个 "事务" 之下运行才行,这就需要手动的管理 "事务" 了。

    1、利用 SQL 语句 手动的开启事务
    
    2、执行 "UPDATE" 语句;执行 "UPDATE" 语句之前 MySQL 数据会将要修改的数据拷贝到 "undo" 日志,执行的修改会被记录在 "redo" 日志
    
    3、执行 "DELETE" 语句;执行 "DELETE" 语句之前 MySQL 数据会将要修改的数据拷贝到 "undo" 日志,执行的修改会被记录在 "redo" 日志
    
    4、提交事务;当提交 "事务" 后,MySQL 会让 "redo" 日志的将数据同步到数据文件,即使出现意外也没有关系。
    
    5、如果说出现意外的情况并结束之后,仍然希望让 MySQL 继续执行事务,就会让 "redo" 日志的继续就爱那个数据同步到数据文件;
    
    6、如果不想继续同步,可以将 "undo" 日志的数据同步到数据文件,如此,数据文件就恢复到了 事务 提交之前的一个状态了。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    从上文介绍来看,"undo" 与 "redo" 这两个日志文件真的很重要。当一些特殊原因造成 "事务" 不能提交的时候,就应该将 "事务" 进行回滚。

    例如我们在抢购 "秒杀" 商品的时候,虽然抢到了商品,但是支付晚了,这事务就必须得回滚,而不能提交。 "事务的回滚" 对 MySQL 来说是非常的简单的,只需要将 "undo" 与 "redo" 这两个日志文件的数据做一个标记即可,这些被标记过得数据就不会被同步到 "数据文件" 了。由此看来, "事务原子性的全部成功或者全部失败的重要性就体现出来了。"



    🐳 SQL 语句的事务管理


    • 上文我们提过,默认情况下,MySQL 执行的每一条 SQL 都会自动开启和提交事务。
    • 多条 SQL 语句被纳入到一个事务之下的时候, 是可以通过手动的方式 “管理事务” 的。

    • 手动 “管理事务” 语法如下:
    START TRANSACTION;
    
    SQL 语句;
    
    ......;
    
    [COMMIT | ROLLBACK];
    
    -- COMMIT : 提交事务
    -- ROLLBACK : 回滚事务
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    事务管理案例:

    START TRANSACTION;
    
    DELETE FROM t_emp;
    DELETE FROM t_dept;
    
    SELECT * FROM t_emp;
    SELECT * FROM t_dept;
    
    -- COMMIT;
    -- 暂时不提交事务
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10


    START TRANSACTION;		-- 手动开启事务
    
    DELETE FROM t_emp;
    DELETE FROM t_dept;
    
    SELECT * FROM t_emp;
    SELECT * FROM t_dept;
    
    COMMIT;					-- 提交事务(需要注意的是 "COMMIT" 提交的是一个最终结果状态,而不是删除这个动作的中间状态)
    
    -- 此时提交了事务,则完成了删除数据表的操作,"t_emp" 与 "t_dept" 表中的记录则被删除。
    -- 只有提交了事务之后,"redo" 日志才会与数据文件同步数据,否则真正的数据文件是不会发生变化的。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    START TRANSACTION;		-- 手动开启事务
    
    DELETE FROM t_emp;
    DELETE FROM t_dept;
    
    SELECT * FROM t_emp;
    SELECT * FROM t_dept;
    
    ROLLBACK;				-- 回滚事务
    
    -- 此时未提交事务,而是回滚了事务,删除数据表的操作被回滚,"t_emp" 与 "t_dept" 表中的记录未被删除。
    -- "redo" 日志因为回滚的操作,未与数据文件同步数据,真正的数据文件没有发生变化。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12


    🐳 事务的ACID属性


    • 事务的四个特性分别是:原子性、一致性、隔离性、持久性;这四个特性被统称为事务的 "ACID" 属性。

    • 事务的原子性:一个事务的所有操作要么全部成功,要么全部失败。事务执行后,不允许停留在中间某个状态。
    • 事务的一致性:不管在任何给定的时间、并发事务有多少,事务必须保证运行结果的一致性。(PS:事务的一致性这个特点真的很重要,它要求事务在并发的清情况下不会出现数据的 "歧义" ;事务如何实现 "一致性" 呢?其实很简单,取值事务相互之间读取临时数据即可。)
    • 事务的隔离性:隔离性对于事务的一致性来说至关重要,隔离性要求事务不受其他并发事务的影响,如同在给定的时间内,该事物是数据库唯一运行的事务。也就是说,每个事务只能看到自己事务内的相关数据,别的事务的临时数据在当前事务里是看不到的。
    • 事务的持久性:持久性的意思就是实物一旦提交,结果便是永久性的。即使发生了宕机、断电等突发状况,仍然可以依靠事务的日志完成数据的持久化。


  • 相关阅读:
    SpringBoot中post请求报405错误排坑
    unordered_map和unordered_set模拟实现
    windows安装jenkins2.346.1
    Springboot结合Netty对接硬件,实现主动发送报文和接受硬件报文(ModbusRTU或者TCP以及DTU)
    MYSQL练习题:访问日期之间最大的空档期
    使用BitLocker实现磁盘加密、u盘加密、移动硬盘加密
    VEX —— Functions|Math
    C语言中获得结构体成员的相对偏移量(Linux内核源码解读)
    商用工程运输车辆智能交通精细数字化管理中的大数据应用
    vulnhub BTRSys: v2.1
  • 原文地址:https://blog.csdn.net/weixin_42250835/article/details/126338570