解决问题:要把转账的三步操作控制在一个事务之内
当前每一个SQL语句就是一个事务,默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务。
一、方式一:修改当前窗口事务提交方式
1、概念
手动提交——
输入SQL代码,点执行按钮,accout表刷新不会生效;
必须输入SQL代码,点执行按钮,再输入commit代码并运行commit行,account表刷新才会生效。
2、正常场景演示
1)恢复数据到初始状态2000
2)查看当前数据库的事务提交方式
1表示自动提交,0表示手动提交
3)修改事务提交方式为手动提交——只对当前窗口有效
4)执行三步转账代码
控制台看到三条代码都已执行完毕:
account表刷新,2000数据不变:(因为未执行commit操作)
5)提交事务
account表刷新,转账操作生效:
3、异常场景演示
1)恢复数据到初始状态2000
记住此时事务为手动提交,必须要commit才能生效!!
2)执行三步转账代码(异常)
控制台看到第一条和第二条代码执行成功,第三条代码异常:
此时,不要commit操作,数据库就不会影响。(commit的话,张三变1000,李四还是2000)
3)回滚事务
account表刷新,数据回滚到原来的值:
二、方式二:不修改事务提交方式,针对局部代码开启手动提交
1、概念
2、异常场景演示
1)恢复原样:
事务提交方式置为1:自动提交
数据恢复初始状态2000
2)开启事务(手动提交)
抛出异常,不能提交事务commit,要回滚事务rollback。
此时,表中数据没有真正生效,还是2000。(只有start transaction没有commit)
3)回滚事务
account表刷新,数据回滚到原来的值:
【代码】
- -------------------------------- 事务操作 --------------------------------
-- 数据准备
create table account(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment '姓名',
money int comment '余额'
) comment '账户表';
insert into account(id, name, money)
values (null, '张三', 2000),
(null, '李四', 2000);
-- 恢复数据
update account set money = 2000 where name = '张三' or name = '李四';
-- 方式一
select @@autocommit; -- 返回1:自动提交。 返回0:手动提交。
set @@autocommit = 0; -- 设置为手动提交(只对当前窗口有效)
-- 方式二
start transaction ;
-- 转账操作(张三给李四转账1000)
-- 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 ;