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 清空表时 ,发现 表中数据依旧存在
即已经进行提交的操作, 是没办法进行回滚的