6.事务
1.什么是事务
事务就是将一组SQL语句放在同一批次内去执行
如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行
MySQL事务处理只支持InnoDB和BDB数据表类型
特点:要么都成功,要么都失败。
情景分析:
1.Sql执行:成龙龙给成果果转钱, 成龙龙 777 —> 77 给成果果 700
2.Sql执行:成果果接到成龙龙的钱, 成龙龙 700 <—> 成果果 777
两个Sql语句放在一起执行,一个批次进行执行,一成全成,一败全败。
2.事务的原则:ACID
(1)原子性(Atomicity)
一批次的操作,要么一起成功,要么一起失败。
整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(ROLLBACK)到事务开始前的状态,就像这个事务从来没有执行过一样。
(2)一致性(Consistency)
事务前后的数据完整性要保持一致。
一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。也就是说:如果事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是保护性和不变性(Preserving an Invariant),以转账案例为例,Eg:成龙和成果一共有777+700元,转账前后,都是如此,金额总数不变。
(3)隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。
隔离所导致的一些问题:
脏读
一个事务读取了另外一个事务没有提交的数据。
不可重复读取
在一个事务内读取表中的某一行数据,多次读取结果不同。(这个不一定是错误,只是某些场合不对)
虚读(幻读)
是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。(一般是行影响,多了一行)
(4)持久性(Durability)
事务一单提交就不可逆了,被持久化到数据库里。
1.事务没有提交,就恢复到原状态。
2.事务一旦提交,就持久化到数据库。
3.执行事务
执行事务的流程和基本语法:
-- MySQL是默认开启事务自动提交的,咱们学习时,可以先关闭。
set autocommit = 0; -- 关闭事务
set autocommit = 1; -- 开启事务,开启是默认的
-- 手动处理事务
set autocommit = 0; -- 关闭事务
-- 事务开始:
start transaction;
-- 标记一个事务的开始,从这个代码之后的sql都在同一个事务里面
-- 提交:实现持久化。(成功的话)
commit;
-- 回滚:返回原来的样子。(失败的话)
rollback;
-- 事物结束,重新开启。
set autocommit = 1; -- 开启事务,开启是默认的
-- 了解:设置事务的保存点,就像游戏里的存档点。
savepoint 保存点名;
-- 回滚至保存点:就像游戏里死后的返回上一个存档点。
rollback to savepoint 保存点名;
-- 撤销保存点:
release savepoint 保存点名;
模拟场景:
转账练习:创建数据库和表格。
create database `shop` character set utf8 collate utf8_general_ci;
use shop;
create table `account` (
`id` int(3) not null auto_increment,
`name` varchar(30) not null,
`money` decimal(9,2) not null,
primary key (`id`)
)engine = innodb default charset = utf8;
/*
mysql字段decimal(9,2)中9是定点精度,2是小数位数。
存在这么一个公式:decimal(a,b)。
其中a指定指定小数点左边和右边可以存储百的十进度制数字的最大个数,最大精度38;
b指定小数点右边可以存储的十进制数字的最大个数,小数位数必须是从 0 到 a之间的值,
默认小数位数是 0。
*/
insert into account(`name`,`money`) values
('成果果','7777'),
('成龙龙','70000');
模拟转账:事务处理
-- 关闭自动提交。
set autocommit = 0;
-- 开启一个事务。
start transaction;
-- 关闭安全模式,防止无法删改数据等。
SET SQL_SAFE_UPDATES = 0;
-- 成果果减去777元
update account set money = money - 777 where `name` = '成果果';
-- 成龙龙接收777元。
update account set money = money + 777 where `name` = '成龙龙';
-- 判断成功,提交。
commit;
-- 判断失败,回滚。
rollback;
-- 开启安全模式,
SET SQL_SAFE_UPDATES = 1;
-- 恢复默认值,恢复自动提交。
set autocommit = 1;
成功修改后:
执行rollback:
执行commit:
且无法再次修改为原来的样子。
参考文献
《【狂神说Java】MySQL最新教程通俗易懂》
视频连接:https://www.bilibili.com/video/BV1NJ411J79W
《狂神说MySQL06:事务和索引》
原文连接
2020.05.17