目录
①事务的小导图
1. 从语雀上传上来:笔记的结构、字体颜色发送改变了
3.语雀笔记:https://www.yuque.com/docs/share/e1f10a98-5f51-4548-be1d-2733ee9e151a?# 《第6章:事务》
第51集:事务--间介
①事务简介
- 为了解决下述的问题,就需要通过数据的事务来完成,
-
- 我们只需要在业务逻辑执行之前开启事务,执行完毕后提交事务。
- 如果执行过程中报错,则回滚事务,把数据恢复到事务开始之前的状态。
②事务的操作:开启、提交事务
- 交易,买卖,业务;
1.代码:数据准备,需要一个账单表
drop table if exists account; create table account( id int primary key AUTO_INCREMENT comment 'ID', name varchar(10) comment '姓名', money double(10,2) comment '余额' ) comment '账户表'; insert into account(name, money) VALUES ('张三',2000), ('李四',2000);
2.方式①:更改提交的方式,
- 自己在这犯错(没有set @@autocommit = 0)
#方式1:更改提交的方式,自己犯错(没有set @@autocommit = 0) update account set money =2000 where name = '张三' or name = '李四'; select @@autocommit; set @@autocommit = 0; #是手动的提交,如果里面出现异常、执行上面的更新语句→要提交数据库的数据才会改变的 -- 1. 查询张三余额 select * from account where name = '张三'; -- 2. 张三的余额减少1000 update account set money = money - 1000 where name = '张三'; # 程序出现了异常... -- 3. 李四的余额增加1000 update account set money = money + 1000 where name = '李四'; #提交事务:当执行的转账没有出现错误时,才提交去(改变数据库的数据) commit; #回滚事务:当执行转账出现一条错误时,要进行回滚→是不用提交的,让数据库的数据不发生改变 rollback;
3.方式②:显式的开启事务
#方式2:显式的开启事务 start transaction ; #需要手动的提交,才能改变数据的 -- 1. 查询张三余额 select * from account where name = '张三'; -- 2. 张三的余额减少1000 update account set money = money - 1000 where name = '张三'; # 程序出现了异常... -- 3. 李四的余额增加1000 update account set money = money + 1000 where name = '李四'; #提交事务:当执行的转账没有出现错误时 commit;
③事务的四大特性
- 原子是一致的
-
- 把你隔离起来是持久的
- 一致性:拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,
-
- 那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
- 隔离性:对于任意两个并发的事务T1和T2,
-
- 在事务T1看来,T2要么在T1开始之前就已经结束;要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
- T2和T1是时空错位的
④并发事务问题:
- 脏款,不可以重复的幻想读取
1.脏读:但对于脏款,事务B读错了
- 脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中;
- 这时,另外一个事务也访问这个数据,然后使用了这个数据。
- 例如:
张三的工资为5000,事务A中把他的工资改为8000,但事务A尚未提交。
与此同时:事务B正在读取张三的工资,读取到张三的工资为8000。
随后:事务A发生异常,而回滚了事务。张三的工资又回滚为5000。
最后:事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读。
2.不可重复读:两次读取的数据不同
- 例如:
在事务A中,读取到张三的工资为5000,操作没有完成,事务还没提交。
与此同时,
事务B把张三的工资改为8000,并提交了事务。
随后,
在事务A中,再次读取张三的工资,此时工资变为8000。 - 在一个事务中前后两次读取的结果并不致,导致了不可重复读。
3.幻读:明明事务B插入了数据,但是一、三查找数据却都没有数据
- 因为我们解决了不可重复读的问题→那么是可以重复读取的
- 则一、三查找数据却都没有数据
- 例如:
目前工资为5000的员工有10人,事务A读取所有工资为5000的人数为10人。
此时,
事务B插入一条工资也为5000的记录。
这是,事务A再次读取工资为5000的员工,记录为11人。此时产生了幻读。
4.重点提醒:
- 不可重复读的重点是修改:
同样的条件,你读取过的数据,再次读取出来发现值不一样了 - 幻读的重点在于新增或者删除:
同样的条件,第 1 次和第 2 次读出来的记录数不一样
⑤事务的隔离级别
- 从上到下:事务的隔离级别越高,数据是越安全的,但是性能也是最低的