第30讲:事务的基本概念以及如何实现事务

事务的基本概念以及如何实现事务

文章目录

  • 事务的基本概念以及如何实现事务
    • 1.事务的基本概念
    • 2.模拟一个事务场景(未控制事务)
      • 2.1.创建余额信息表并写入数据
      • 2.2.测试正常情况不控制事务的现象
      • 2.2.测试不正常情况不控制事务的现象
    • 3.事务的配置语法
    • 4.以手动控制事务的提交观察转账场景的效果
      • 4.1.将事务行为调整为手动提交
      • 4.2.正常情况下的手动控制事务的现象
      • 4.2.不正常情况下的手动控制事务的现象
    • 5.以手动开启事务并提交的方式来实现转账场景的效果

1.事务的基本概念

数据库中有事务的概念,那么什么是事务呢?

事务指的是一组操作的集合,事务会把集合中所有的操作看成是一个整体,一起向数据库提交这些操作,或者撤销这些操作,这些操作可以是增加数据、修改数据、插入数据、查询数据,但是这一个集合中的所有操作必须要么全部成功,要么全部失败。

事务的重点概念就是:要么全部执行成功、要么全部执行失败。

事务这种操作经常应用于银行、金融等业务场景,只要涉及金额、交易等这类场景,就需要用到事务操作。

为了更清楚的理解什么是事务,我们一起来看下面这个场景。

小明的账户里有5000元,要给小红转账1000元,此时数据库就开启了一组事务,事务中分为了三个操作模式:

  • 首先查询小明账户中的余额是否满足要转账的金额。
  • 然后触发更新数据的操作,小明的账户减少1000元。
  • 最后再次触发一个更新数据的操作,小红账户增加1000元。

事务中的三个操作要么全部执行成功,要么全部执行失败,当三个操作全部执行成功时,数据库会提交这个事务,如果中间有一个操作执行失败了,会立刻回滚事务,将修改过的数据全部还原,防止业务逻辑出现问题。

如果其中某个操作异常了,其他的都提交到数据库了,那么就会导致数据异常,金融行业的数据异常是万万不能存在的。

事务在MySQL中是默认开启的,默认情况系啊,每一条DML语句,都是一条事务。

事务的应用有两种方式:

  • 控制事务的提交方式(手动、自动。)

  • 开启事务、提交事务、回滚事务。

事务的四大特性分别是原子性、一致性、隔离性、持久性。

  • 原子性(Atomicity):事务是不可分割的最小操作单元,事务里的多个操作单元,要么全部执行成功,要么全部执行失败。
  • 一致性(Consistency):事务完成时,所有的数据都保持一致的状态,以转账场景为例,一旦提交事务后,转账双方的金额变化必须符合业务逻辑,小明余额减1000元,小红余额就必须加1000元,数据要保持一致状态。
  • 隔离性(Isolation):数据库系统提供事务的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行,在很多场景下,会有多个事务同时对一个数据表进行操作,此时有了隔离机制,事务A运行的时候并不会影响事务B的运行。
  • 持久性(Durability):事务一旦提交或者回滚后,对于数据库的数据改变将是永久性的,数据都会被写入到磁盘中。

2.模拟一个事务场景(未控制事务)

创建一张金融数据表,里面有小明和小红两个人,分别有2000块钱的余额,小明给小红转账一千元,我们针对转账场景模拟事务,观察事务的表现方式。

2.1.创建余额信息表并写入数据

create table yexxb (
	id int primary key auto_increment comment 'ID',
	xm varchar(10) comment '姓名',
	ye double(10,2) comment '余额'
) comment '余额信息表'

insert into yexxb (xm,ye) values ('小明','2000'),('小红','2000');

2.2.测试正常情况不控制事务的现象

首先来测试一下未控制事务的情况下,数据的一个执行状态。

下面的SQL语句是小明给小红转账的完整语句流程,全部选中一起执行。

-- 查询小明的余额
select * from yexxb where xm = '小明';

-- 将小明的余额减少1000
update yexxb set ye = ye - 1000 where  xm = '小明';

-- 将小红的余额增加1000
update yexxb set ye ye + 1000 where xm = '小红';

正常情况下,SQL语句全部执行成功,业务逻辑也没有任何问题,小明给小红转账后,小明的余额减少了1000元,小红的余额增加了1000元,没有任何问题。

image-20220522225154286

2.2.测试不正常情况不控制事务的现象

业务逻辑并不是时时刻刻都能够成功执行的,也有很多因为网络问题,程序产生了异常,三个SQL操作,只有某一个成功了,那么就会导致数据异常。

选中下面所有的SQL语句,全部一起执行,模拟不正常情况下事务的现象。

-- 查询小明的余额
select * from yexxb where xm = '小明';

-- 将小明的余额减少1000
update yexxb set ye = ye - 1000 where  xm = '小明';

程序异常,网络波动
-- 将小红的余额增加1000
update yexxb set ye ye + 1000 where xm = '小红';

由于网络或者程序的异常,导致应该三个都需要执行成功的SQL,此时只执行成功了前两个,第三条并没有执行成功,此时就会导致小明的余额虽然减少了1000元,但是小红的余额却没有增加。

image-20220522225525259

这在金融行业是绝对不允许发生的现象,涉及到钱的问题都不是小问题。

此时我们也可以得到一个结论,在默认的情况下,MySQL数据库中的一条SQL语句,都是一个事务,执行完一条SQL后,都会提交到数据后,对数据进行操作,当遇到多SQL有关联性,需要一起实现某个业务逻辑时,如果还使用默认的事务配置,那么就会对数据产生不可逆的影响。

3.事务的配置语法

1)设置事务的提交方式

SET @@autocommit = 0|1

1:自动提交事务,1SQL表示1个事务
0:手动提交事务,不提交事务,数据就不会发生改变

当设置了手动提交事务的行为后,此时我们执行的SQL语句不会提交到数据库,数据不会发生修改,需要手动执行提交事务的命令。

2)查看事务的提交方式

SELECT @@autocommit

3)提交事务

COMMIT

4)回滚事务

ROLLBACK

4.以手动控制事务的提交观察转账场景的效果

在前面不控制事务时,当有网络波动,数据就会执行异常,下面我们手动控制事务的提交,来观察控制事务后转账场景的效果。

4.1.将事务行为调整为手动提交

set @@autocommit = 0;

4.2.正常情况下的手动控制事务的现象

此时同时执行下面的SQL,下面的SQL就是完整的转账流程,观察手动控制事务的提交后,数据有什么变化。

-- 查询小明的余额
select * from yexxb where xm = '小明';

-- 将小明的余额减少1000
update yexxb set ye = ye - 1000 where  xm = '小明';

程序异常,网络波动
-- 将小红的余额增加1000
update 网络波动yexxb set ye ye + 1000 where xm = '小红';

和前面没有控制事务时,有了很明显的编号,当手动控制了事务的提交后,只要我们不提交数据,无论执行了多少个更新数据的操作,数据表中的数据永远都不会发生改变。

image-20220522231758591

下面我们来执行提交事务的操作,然后再观察表中的数据。

commit;

当事务提交成功后,数据库表中的数据才会执行对应的操作,否则任何处理数据的动作只会存在于当前会话中(在这个会话中使用select就可以看到修改后的数据,但是不提交就不会再表中进行更改)。

image-20220522231933678

4.2.不正常情况下的手动控制事务的现象

在前面演示了正常情况下的手动控制事务提交的现象,下面来看看非正常情况时,手动控制事务的现象。

此时执行下面的所有SQL时,就会看到异常的现象,此时,第三条SQL是不会执行成功的,但是前面两条都是成功的。

-- 查询小明的余额
select * from yexxb where xm = '小明';

-- 将小明的余额减少1000
update yexxb set ye = ye - 1000 where  xm = '小明';

程序异常,网络波动
-- 将小红的余额增加1000
update 网络波动yexxb set ye ye + 1000 where xm = '小红';

我们还没有提交事务,因此当发现异常时,可以执行回滚的操作,将事务撤销,保证数据不受影响。

rollback;

可以看到此时的数据时不会受到任何影响的。

image-20220522232459301

5.以手动开启事务并提交的方式来实现转账场景的效果

效果和手动控制事务提交行为一样,重点是语法不同,使用手动开启事务的方式时,无需调整事务提交的默认行为。

1.开启事务
start transaction 

2.执行事务的SQL逻辑
-- 查询小明的余额
select * from yexxb where xm = '小明';

-- 将小明的余额减少1000
update yexxb set ye = ye - 1000 where  xm = '小明';

-- 将小红的余额增加1000
update  set ye = ye + 1000 where xm = '小红';

3.提交事务
commit 

4.如果SQL执行异常那么就回滚事务
rollback

在实际的生产环境中,建议使用此种方式。

你可能感兴趣的:(《MySQL,DBA封神打怪之路》,1024程序员节,Mysql,事务,数据库,DBA)