本文学习参考:102-事务概述_哔哩哔哩_bilibili
本文仅用于加强学习记忆,如果需要系统学习就点击链接进行学习。
事务
- 一个事务就是一个完整的业务逻辑,一个最小的工作单元,不可再分
- 只有DML(insert、delete、update)语句和事务有关系其他都没关系。
因为这三个语句是对数据库表中的数据进行增删改的。
只要你的操作涉及到数据的增删改,那么就一定要考虑安全问题。
数据安全第一位。 - 最直白的说法就是,一个事务就是一批DML语句同时成功,或者同时失败
- 事务的运行:
InnoDB存储引擎:提供一组用来记录事务性活动的日志文件
eg:
事务开启了:
insert...
isnert...
delete...
update...
事务结束了。
在事务执行过程中,每一条DML的操作都会记录到“事务性活动的日志文件”中。
在事务执行过程中,我们可以提交事务,也可以回滚事务。
提交事务:
清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中。
提交事务标志着事务的结束,并且是一种全部成功的结束。
回滚事务:
将之前所有的DML操作全部撤销,并清空事务性活动的日志文件
回滚事务标志着,事务的结束,并且是全部失败的结束。 - 提交事务,回滚事务
提交事务:commit;语句
回滚事务:rollback;语句 (回滚只能回到上一次的提交点)
事务对应的单词:transaction
正常情况下,mysql是支持默认自动提交事务的。每执行一条DML语句就执行一次。
如果需要关闭mysql自动提交事务,就使用start transaction;这个就是开启事务的指令。
在使用了start transcation;后,如果一个事务结束就需要commmit指令或者rollback指令进行完成,否则你的事务是一直在记录,也就是说开启了start transcation指令,提交节点是你自己控制的,不再由mysql自动提交。 - 事务包括四个特性:
A:原子性
说明事务是最小的工作单元,不可在拆分。
C:一致性
所有事务要求,在同一个事务中,所有操作必须同时成功,或者同时失败,以保证数据的一致性
I:隔离性
A事务和B事务具有一定的隔离。
教室A和教室B之间有一道墙,这道墙就是隔离性。
A事务在操作一张表的时候,另外一个事务B也在操作这张表会怎么样,也就是多线程并发的情况
D:持久性
事务最终结束的一个保障。事务提交,就相当于将没有保存到硬盘的数据保存到硬盘。 - 事务的隔离性
A教室和B教室中间有一道墙,这道墙可以很厚,也可以很薄。这就是事务的隔离级别。
这道墙越厚,表示隔离级别越高
事务和事务之间有4个隔离级别:
读未提交: read uncommitted(隔离级别最低):
事务A可以读取到事务B为提交的数据
这种隔离级别存在的问题就是:
藏读现象(Dirty Read):读到了脏数据
读已提交:read committed:
事务A只能读取到事务B提交后的数据
这种隔离级别解决了脏读现象
存在问题:不可重复读取数据。
这种级别隔离是比较真实的数据,每一次读到的数据是绝对真实的。(oracle数据库默认的级别就是:read commited)
可重复读:repeatable read:
事务A开启之后,不管是多久,每一次在事务A中读取到的数据都是一致的。即使事务B将数据已经修改,并且提交了,事务A读取到的数据还是没有发生改变,这就是可重复读。
存在问题:会出现幻象读,每一次读取的数据都是幻象,不够真实。
序列化,串行化:serializable(隔离级别最高):
这种隔离级别最高,效率最低,解决了所有问题。
这种隔离表示事务排队,不能并发。 - 查看隔离级别:
SELECT @@transaction_isolation;![]()
mysql默认隔离级别
- 设置全局事务隔离级别:
set global transaction isolation level read uncommitted; 将相应的隔离级别换掉就行。![]()
设置完后需要退出mysql重新加载级别,否则还是可重复级别
使用t_user表测试隔离级别- 测试read uncommitted隔离:
开两个终端进行事务验证,可以发现,两边都开手动提交,但是在事务未提交时,双方对数据的操作依然是实时更新的
![]()
rollback再次查询:
![]()
- 测试read uncommitted隔离:
- 测试read committed隔离
切换了隔离级别后,对右边终端开启start transaction;
再对右端进行插入值操作,但是不提交,在左端进行查询,发现查不出来插入的信息,表依旧为空表。
![]()
只有当我右端进行提交后,左端才能查出插入的表值。
![]()
- repeatable read测试:
将数据库隔离级别切换成repeatable read,打开两个终端进行测试,都开启事务,一个终端只管查询,另外一个终端进行表的插值最后进行提交,查询的表最终再查一次看看结果:
发现进行插值的表就算提交了事务,另外一个终端也查询不到,
![]()
只有在查询那张表事务进行提交后,再次查询才是显示最新的情况。
![]()
- 验证序列化,串行化(serializable):
先将数据库隔离级别设置为serializable
再重启两个终端,开启事务,一个终端先对表进行插值,另外一个表再进行查询,结果如下:
发现另外一个终端光标卡在那不动了,只有先插值的终端能进行操作,另外一个终端对相同的表进行操作给锁住了。
![]()








