事务管理之事务基础

339 阅读6分钟

这是我参与8月更文挑战的第7,活动详情查看:8月更文挑战

因最近遇到Spring事务管理相关问题,故总结记录一下问题

1 什么是事务

如果一个业务完成,需要执行多条SQL语句.即涉及多个增删改查.必须使用事务.简单来说,事务,就是把这些所有的SQL语句当做一个整体来执行,要么全部成功,要么全部失败. 如果执行失败,则需要回滚到没有执行SQL前的状态.

2 事务的四大特性

原子性,一致性,隔离性,持久性.

事务特性含义
原子性(Atomicity)一个事务所有的SQL语句是一个整体,不可分割。要么全部成功,要么全部失败
一致性(Consistency)对数据库中数据的操作状态在事务执行前后必须是一致的,
如:转账前2个人的总金额与转账后2个人的总金额是一致的
隔离性(Isolation)每个表中同时有多个事务在执行,事务与事务之间是隔离的,不能相互影响
持久性(Durability)如果一个事务执行成功,对数据库的影响是持久的,服务器关闭也是存在的

3 事务的应用场景

1 银行转账业务模拟

​ 虹猫给蓝兔转1000元,而这个业务,至少要执行2条语句,即虹猫扣减1000元语句,蓝兔增加1000元语句.


-- 创建账户表:id,name,balance
create table account(
	id int primary key auto_increment,  -- 主键自动增长
	name varchar(20),  -- 账户名
	balance int   -- 账户的余额
);  
 
-- 添加数据:虹猫和蓝兔各1000块
insert into account values(null, 'hm',2000),(null,'lt',2000);

select * from account;

-- 模拟虹猫转账给蓝兔 1000块钱的功能:
-- 至少要执行2条SQL语句
-- 1. 更新虹猫账户,虹猫减1000
-- 2. 更新蓝兔账户,蓝兔加1000
-- 执行第1条
update account set balance=balance-1000 where name='hm';
-- 执行第2条,可能会出现第1条语句执行成功,第2条语句没有执行,或者执行失败的情况
update account set balance=balance+1000 where name='lt';

-- 查询转账后结果
select * from account;

-- 还原2个账户的钱为1000
update account set balance = 2000;

​ 如果当虹猫扣减1000元的语句执行了,此时遭遇其他意外问题,服务器崩溃了.给蓝兔增加1000元的语句没有执行,那么数据就出了问题,对于银行类机构,这样问题不能容忍的.

​ 所以,我们要保证,如果有一个语句出现问题,整个转账就算失败.数据恢复到没执行语句前的状态. 只有两个语句都成功了,这个转账就算成功.这就是事务的应用场景.

4 事务的提交

事务的提交,分为手动提交和自动提交.

默认情况下Mysql任务每条DML语句(增删改)都是一个单独的事务,所以上面转账的是2个事务在执行.

1 手动提交

​ 手动提交事务,即通过人为控制事务的开启,关闭,回滚.

1 相关命令操作

功能SQL语句
开启事务start transaction
提交事务commit
回滚事务rollback

2 手动提交事务

1 开启事务

2 执行业务相关的多条sql语句 (此时并没有把数据写到数据库表中,所有的操作都是在一个日志文件去完成)

3 如果所有的SQL语句都没有异常,提交事务

4 如果有失败的语句,则进行回滚事务

image-20210728081605536

3 案列

1 提交事务

​ 模拟虹猫给蓝兔转1000元成功的案列.

1 使用Dos控制台进入Mysql

2 执行业务流程

start transaction;

select * from account;

update account set balance=balance-1000 where name='hm';

update account set balance=balance+1000 where name='lt';

select * from account;

commit;
- 1开启事务
- 2 虹猫账号-1000
- 3 蓝兔账号+1000
- 4 使用navicat查看数据库,数据不变.
- 5 在控制台提交事务
- 6 使用navicat查看数据库,数据改变.

navicat事务提交前:

image-20210801135610062

navicat事务提交后:

image-20210801135711744

2 回滚事务

​ 模拟虹猫给蓝兔转1000元失败的案列.

1 使用Dos控制台进入Mysql

2 执行业务流程

start transaction;

select * from account;

update account set balance=balance-1000 where name='hm';

update account set balance=balance+1000 where name='lt';

select * from account;

rollback;

select * from account;
  • 1开启事务
  • 2 虹猫账号-1000
  • 3 蓝兔账号+1000
  • 4 使用navicat查看数据库,数据不变.
  • 5 在控制台回滚事务
  • 6 使用navicat查看数据库,数据改变.

navicat事务提交前:

image-20210801135610062

navicat事务提交后:

image-20210801135610062

2 自动提交

​ 自动提交的关闭和开启.

功能Sql语句
查看当前事务自动提交状态Select @@autocommit;
改变事务状态0表示手动,1表示自动set @@autocommit=1;

1 默认提交方式

Mysql默认情况下,认为每条DML语句(增删改)都是一个独立的事务,所以上面的案例,mysql认为是2个事务在执行.

每条语句开始执行前会自动开启事务,执行完毕会自动提交事务,这样我们就不能进行回滚了。

为了完成相关的业务, 我们必须要能有回滚的功能. 可通过设置Mysql的事务提交方式.默认是自动提交,我们可以手动关闭该功能.

2 案例

1 自动提交事务

select * from account;

update account set balance=balance-1000 where name='hm';

select * from account;
  • 1 更新虹猫账户-1000
  • 2 使用navicat查看数据

2 关闭自动提交事务

  • 1 关闭自动提交事务
  • 2 更新虹猫账户-1000
  • 3 使用navicat查看数据
  • 4 提交事务
  • 5 使用navicat查看数据
  • 6 开启自动提交事务
Select @@autocommit;

set @@autocommit=0;

update account set balance=balance-1000 where name='hm';

commit;

set @@autocommit=1;

navicat事务提交前:

image-20210801135610062

navicat事务提交后:

image-20210801135711744

3 事务的回滚

1 事务回滚的概述

​ 事务回滚: 回滚到事务执行前最开始的状态.如果不愿意回滚到最开始的状态,可以回滚到整个流程中的一步.

​ 提前保存回滚点,再回滚到保存的这个位置.

事务的操作MySQL操作事务的语句
开启事务start transaction
提交事务commit
回滚事务rollback
设置回滚点savepoint 回滚名字
回到回滚点rollback to 回滚名字
查询事务的自动提交情况select @@autocommit
设置事务的手动提交方式set @@autocommit

2 回滚案例

1 案例步骤

  • 1 开启事务
  • 2 让虹猫的账号减500元
  • 3 设置回滚点
  • 4 让虹猫的账号减500元
  • 5 回到回滚点
  • 6 提交事务
start transaction;

select * from account;

update account set balance=balance-500 where name='hm';

savepoint back_point_one; 

update account set balance=balance-500 where name='hm';

rollback to back_point_one;

commit;

select * from account;

image-20210801140011076

navicat事务提交前:

image-20210801135610062

navicat事务提交后:

image-20210801140038396