一个事务是一个完整的业务逻辑单元,不可再分。
比如:银行账户转账,从A账户向B账户转账10000.需要执行两条update语句:
update t_act set balance = balance - 10000 where actno = ‘act-001’;
update t_act set balance = balance + 10000 where actno = ‘act-002’;以上两条DML语句必须同时成功,或者同时失败,不允许出现一条成功,一条失败。
要想保证以上的两条DML语句同时成功或者同时失败,那么就需要使用数据库的“事务机制”。
事物的和事务相关的语句只有:DML语句。(insert delete update)—— 事务之和对数据产生变化的操作有关
为什么?因为它们这三个语句都是和数据库表当中的“数据”相关的。
事务的存在是为了保证数据的完整性,安全性。
如果只有一条DML语句,还需要事务机制嘛?
不需要!
但实际情况不是这样的,通常一个“事儿(事务【业务】)”需要多条DML语句共同联合完成。
综上所述:事务机制就是在处理某一个业务(事务)时多条DML语句同时成功或者同时失败,保证数据的完整性,安全性
事务如何做到多条DML语句同时成功或者同时失败?
MySQL中的InnoDB存储引擎:提供了一组用来记录事务活动的日志文件(log)
事务开启了!
insert
insert
update
delete
…
事务结束了!
在事务执行的1过程中,每一条DML语句都会记录到事务性活动的日志文件中,在事务的执行过程中,我们可以提交事务,也可以回滚事务。
提交事务?
提交事务,就会清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中。
提交事务标志着,事务的结束!并且是一种全部成功(所有DML全部成功)的结束
事务回滚?
将之前的所有
DML全部撤销,并且清空事务性活动的日志文件。回滚事务,标志着事物的结束!并且是一种全部失败(所有DML全部失败)的结束
commit的地方)测试:MySQL中的事务默认提交方式是怎么样的?手动提交还是自动提交呢?——自动提交。
自动提交?—— 没执行一条DML语句,就会提交一次事务

上述我们删除表中的数据后,进行回滚,并不能将原来的数据恢复,那是因为,在执行delete语句后,事务自动提交(默认),然后就会清空事务性活动的日志文件,当进行回滚时无法从日志文件中拿到并恢复数据!
这种自动提交实际是不符合我们的开发习惯的,因为一个业务通常需要多条
DML语句共同执行完成的,为了保证数据的安全,必须要求同时成功完成后再进行提交,所以不能执行一条就提交一条!
我们如何关闭MySQL的默认自动提交事务,而是自己手动提交事务呢?
关闭自动提交事务命令(我们自己开启事务),先执行这一条命令:
start transaction然后就是DML语句
最后提交事务
事务回滚:

提交事务与回滚事务:滚不回去了!

一个事务就是完成一件事(一个完整的业务逻辑)
事务有四大特性:ACID
多条DML语句同时成功或者同时失败。事务隔离性存在隔离级别,理论上隔离级别包括4个:
read uncommitted)MySQL命令行的默认配置中事务都是自动提交的,即执行SQL语句就会马上执行COMMIT操作。可以用命令START TRANSACTION开始一个事务。
我们可以通过下面命令设置事务隔离级别。
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
第1级别:读未提交
set global transaction isolation level read uncommitted;
第2级别:读已提交
set global transaction isolation level read committed;
第3级别:可重复读
set global transaction isolation level repeatable read;
cd C:\Program Files\MySQL\MySQL Server 8.0\bin
查看当前事务级别:
select @@transaction_isolation;
我们再来看一下我们在实际操作中使用到的一些并发控制语句:
第一级别:读未提交(
read uncommitted)
对方事务还没有提交,我们当前事务可以读取到对方未提交的数据。
读未提交存在脏读(Dirty Read)现象:表示读到了脏的数据。
事务A--------------------------------------事务B
窗口A和窗口B并行进行测试检验!
1、在窗口A将全局事务级别设为 read uncommitted
set global transaction isolation level read uncommitted;
成功,退出,再进入
查看级别等级——设置成功
select @@transaction_isolation;

2、同时开两个命令窗口,登录数据库,进入到我们测试用的数据库
窗口A:
1、开启事务
start transaction;
2、查一下数据
select * from user;
# 表此时为空
窗口B:
1、开启事务
start transaction;
2、插入数据(未提交(事务未提交,没有commit))
insert into user values("张三");
再回到窗口A:查看数据,发现数据查出来了!!!

第一级别:
第一级别:读未提交(
read uncommitted)
对方事务还没有提交,我们当前事务可以读取到对方未提交的数据。
事务A--------------------------------------事务B
窗口A和窗口B并行进行测试检验!
1、在窗口A将全局事务级别设为 read committed
set global transaction isolation level read committed;
成功,退出,再进入
查看级别等级——设置成功
select @@transaction_isolation;

2、同时开两个命令窗口,登录数据库,进入到我们测试用的数据库
窗口A:
1、开启事务
start transaction;
2、查一下数据
select * from user;
# 表此时为空
窗口B:
1、开启事务
start transaction;
2、插入数据(未提交(事务未提交,没有commit))
insert into user values("李四");
3、再回到窗口A:查看数据,数据未查出来!!!

4、回到窗口B,进行事务提交
commit;
5、再回到窗口A:查看数据,数据查出来了!!!

第二级别:
1第二级别:读已提交(read committed)
对方事务提交之后的数据我方可以读取到。
这种隔离级别解决了: 脏读现象没有了。
读已提交存在的问题是:不可重复读。
事务A--------------------------------------事务B
窗口A和窗口B并行进行测试检验!
1、在窗口A将全局事务级别设为 repeatable read
set global transaction isolation level repeatable read;
成功,退出,再登录进入
查看级别等级——设置成功
select @@transaction_isolation;

2、同时开两个命令窗口,登录数据库,进入到我们测试用的数据库
窗口A:
我们事先先插入一条数据:
insert into user values("6666");
1、开启事务
start transaction;
2、查一下数据
select * from user;
# 表此时有一条数据6666
窗口B:
1、开启事务
start transaction;
2、插入数据(未提交(事务未提交,没有commit))
insert into user values("李四");
insert into user values("李四");
insert into user values("李四");

4、提交事务
commit;
窗口A:
5、再回到窗口A:查看数据,数据未查出来!!!

6、窗口A中,提交事务后,就可以看到新数据了

1第三级别:可重复读(repeatable read)
这种隔离级别解决了:不可重复读问题。
这种隔离级别存在的问题是:读取到的数据是幻象。
总结:两个事务是独立的,当对同一张表同时开启事务,事务B中进行DML语句,commit结束事务B后,只要事务A此时还没结束,那么A事务中查询到的数据都是事务B提交前的数据(两个事务同时进行时,事务独立开来了,互不影响的(第三级别)),只有当事务A也commit后,事务B中的DML语句产生的影响才会作用到事务A,此时查询到的数据是更新后的!
窗口A和窗口B并行进行测试检验!
1、在窗口A将全局事务级别设为 serializable
set global transaction isolation level serializable;
成功,退出,再进入
查看级别等级——设置成功
select @@transaction_isolation;

2、同时开两个命令窗口,登录数据库,进入到我们测试用的数据库
窗口A:
1、开启事务
start transaction;
2、查一下数据
select * from user;
# 表此时为空
3、插入数据(未提交(事务未提交,没有commit)—— 事务A没结束)
insert into user values("张三");
窗口B:
1、开启事务(事务要同时开启的)
start transaction;
2、查询数据,发现窗口B,光标卡住了
因为两个事务同时操作这张表了,第四级别四需要排队的!!!

窗口A:
再回到窗口A:结束事务——发现窗口B立即查出数据来了(说明第四级别事务需要排队!!!!)