【MySQL】事务(上)
作者:mmseoamin日期:2023-12-11

文章目录

  • 事务概念
  • 什么是事务?
  • 为什么要有事务?
  • 事务的版本支持
  • 事务的提交方式
  • 事务常见操作方式
  • 基本操作

    事务概念

    mysql 本身内部采用 多线程的方式,来实现数据存储 相关的工作 就注定对数据 有并发访问的场景

    为了解决这类问题,就提供了 事务 的概念


    火车票售票系统中 存在一张tickets表,包含 id 、name 和 nums(票数)

    mysql是一个网络服务,被一个人访问时,也有可能被其他人访问

    当客户端A和客户端B 同时向火车票售票系统 购买票时

    假设只有一张票,当客户端A想要买票时,经过if判断时,发现票数为1

    但可能由于mysql内部的多线程 被调度了,负责给客户端A买票的线程被挂起了

    当客户端B想要买票时,经过if判断,发现票数依旧为1

    就会出现 仅有的一张票被卖了两次


    增删查改 满足 以下情况,即可解决上述问题

    买票的过程需要 是原子的

    ( 要不就别买票,要买 就将票买完)

    买票互相不能影响

    ( 不能发生 A正在买票,B也过来买票的情况,A和B两者买票不能互相影响)

    买完票要永久有效

    (不能发生买完票后,不承认该票存在的情况)

    买前和买后的状态是确定的

    (买前就是没买票,买后就是买了票,不能出现中间状态的情况)


    什么是事务?

    编写sql语句时,有可能一条sql语句是解决不掉问题的,需要一批sql语句共同组合才能完成

    如:从银行卡A中提钱,向银行卡B转账,将银行卡A中的钱减100,再将银行卡B中的钱加100

    使用两条sql 语句 才能完成,单独一条语句是完不成操作的

    事务 是由 一条或者多条事务 构成的集合体,这个集合体 需要共同完成某种任务

    构成这个集合体的语句,要么全部失败,要么全部成功

    同样事务规定不同的客户端 看到的数据是不同的


    事务主要处理 操作量大、复杂度高的数据

    如:你毕业了,学校的教务系统中要删除你的全部数据,除了删除姓名、电话等基本信息,还要删除你的其他有关信息


    mysql为了保证事务的正确运行,就需要维护四大属性

    原子性: 一个事务的所有操作,要么就全部都完成,要么就全部都不完成,不会出现结束在中间某个环节

    隔离性: 数据库允许多个并发事务 同时对其数据进行 读写和修改的能力

    隔离性可以防止多个事务 并发执行时由于交叉执行而导致数据的不一致

    其中隔离级别 分为 未提交(Read uncommitted) 、读提交(read committed)、可重复读(repeatable read)以及 串行化( Serializable)

    持久性: 事务处理结束后,对数据的修改 就是永久的, 即便系统故障也不会丢失

    一致性: 在事务开始之前和事务结束过程之后,数据库的完整性没有被破坏

    ( 在操作之前 对操作之后 所发生的事情 进行预期,并且在操作后,其发生的事情与预期相同)


    四大属性 简称为ACID

    原子性(Atomicity)

    一致性(Consistency)

    隔离性(Isolation)

    持久性(Durability)


    为什么要有事务?

    事务 被 MySQL 编写者设计出来

    本质是为了当应用程序访问数据库时,事务能简化编程模型,不需要去考虑潜在错误和并发问题

    事务本质上是为应用层服务的, 而不是随着数据库天然就有的

    事务的版本支持

    输入 show engines \G 查询mysql支持的存储引擎


    发现是支持 innodb储存引擎的,并且默认是 innodb

    在comment描述中,说明支持事务

    myisam 是不支持事务的


    事务的提交方式

    事务共有两种提交方式: 手动提交 自动提交


    输入 show variables like ‘autocommit’ 查询提交方式

    ON 表示 自动提交


    输入 set autocommit =0; OFF表示关闭自动提交


    输入 set autocommit =1; ON表示打开自动提交


    事务常见操作方式

    输入 set global transaction isolation level read uncommitted;

    将mysql的隔离级别设置成 读未提交(read uncommitted)

    再输入 select @@tx_isolation; 查询当前的隔离级别

    发现隔离级别 依旧为 可重复读(repeatable read) 而不是读未提交


    将隔离级别修改后 ,需要重启客户端

    重启后,再次输入 select @@tx_isolation; 进行查询

    发现隔离级别 已经变为 读未提交(read uncommitted)


    基本操作

    创建一张表 acount,其中包含 约束为主键的key 、不为空 并且默认为空字符串的name

    指定长度为10 小数部分为2位 并且默认为0.0 的blance


    输入 show variables like ‘autocommit’ 查询提交方式

    ON 表示 自动提交

    说明当前提交方式为自动提交


    启动事务的方案 为 start transaction begin

    在终端1 和终端2 中 分别 使用 start transaction begin 启动不同的事务


    在终端1中 输入 savepoint s1 记录 保存点 s1

    并向 account表中插入 数据

    插入后,再次设置保存点 s2


    在终端2中,输入 select * from account 查询account表的信息 就可以查到插入的数据


    在终端1中,再次插入数据

    在终端2中,依旧可以从表中查到数据


    在终端1中,若不想把 李四插入到表中,可以进行定向回滚

    输入 rollback to s2 回滚到保存点s2

    在终端2中,此时再次查询account表中数据,发现只有张三存在

    最终输入 commit 结束事务


    在终端1中 插入数据后 , 若直接输入 rollback 则会将表中数据全部清空


    若想将对应的两个插入操作,变为 持久化 保存到 mysql中

    先 输入 commit 进行提交

    再输入 rollback 清空表时 ,发现 表中数据依旧存在

    即已经进行提交的操作, 是没办法进行回滚的