事务执行,提交与回滚
- 基本概念
- 什么是事务?
- 什么是自动提交?
- 错误事务案例
- 解决方案
- 方式一:控制事务
- 方式二:手动提交与回滚
- 自动提交更改为手动提交
- 进行手动提交
- 错误进行回滚
基本概念
什么是事务?
每一个SQL语句都是一个事务,一条SQL语句一旦执行完成,事务会自动提交。事务一旦提交,数据库表中数据就会发生变化。
然而我们希望可以控制事务,为什么?想象银行转账的场景,首先构建表:
# 构建表
create table account(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment '姓名',
money int comment '余额'
) comment '账户表';
# 插入值
insert into account values(null, '张三', 2000),(null,'李四',2000);
什么是自动提交?
每条SQL语句都是一个事务,下述两条SQL语句中(一个查询一个更新),是两个事务,执行次序如下:
select * from account where name='张三';
update account set money = money - 1000 where name='张三';
SQL语句执行系统默认自动提交,看似只是执行了两条SQL语句,其实实际上则是执行了两次执行,两次提交。
而且当且仅当提交时,才会上传至数据库,更改数据库信息。
错误事务案例
e . g . e.g. e.g. 张三给李四转账1000元,SQL中执行如下:
update account set money = money - 1000 where name='张三';
update account set money = money + 1000 where name='李四';
如果程序在第一句结束时发生异常,数据库会呈现:
已执行完成张三 money-1000,但是未执行李四 money+1000
这很离谱不是 ~
解决方案
事务本节内容,就是希望解决这个问题。如果发生异常,我们希望这两个 Update 事务组成的整体要么同时成功,要么同时失败。我们该如何做?
方式一:控制事务
我们通过控制事务命令:
start transaction; # 控制事务命令
# 被控制的事务
...
commit; # 正确即提交
rollback; # 错误即回滚
e . g . e.g. e.g.
start transaction;
update account set money = money - 1000 where name='张三';
update account set money = money + 1000 where name='李四';
-- 正确执行
commit;
-- 错误执行
rollback;
方式二:手动提交与回滚
自动提交更改为手动提交
查看当前数据库事务提交方式:
select @@autocommit;
结果为1,代表当前事务自动提交。可以理解为每句SQL语句执行即提交到数据库中。
我们可以取消自动提交:
set @@autocommit = 0;
在这里我想问一个问题,若是读者可以回答这个问题正确,那么说明你对上述概念皆已理解:
在执行 set @@autocommit = 0 代码之后,若此时再执行下述代码,请问最后张三李四的money为多少?
update account set money = money - 1000 where name='张三';
update account set money = money + 1000 where name='李四';
Answer: 张三2000,李四2000
原因是因为我们取消了自动提交,所以我们即使执行了SQL语句,因为未执行提交操作,所以仍不会对数据库进行更改。
进行手动提交
那么如何在此情况下,如何进行提交?执行指令:
commit;
再次刷新数据库,即可发现变化。
错误进行回滚
如果入出现错误,那么不能提交了我们该怎么办??
我们执行回滚指令:
rollback;
回滚之后,张三和李四保持金额2000不变。
综上所述:
如果事务执行正确,我们提交 (commit);
如果事务执行发生错误,那么我们回滚 (rollback)。