目录
原子性
持久性
隔离性
隔离级别(并发事务之间的关系)
读未提交
读已提交
可重复读
串行化(最严格的隔离级别)
一致性
问题
不可重复读性(已经提交的数据)
什么是脏读问题(未提交的数据)?
幻读
保存点
自动提交机制--autocommit
会话隔离级别与全局隔离级别
原子性
事务原子性是指在数据库操作中,事务要么全部执行成功,要么全部执行失败,不存在部分执行成功部分执行失败的情冿。事务原子性保证了数据的一致性和可靠性,确保数据库中的数据不会出现不一致的情况。当一个事务中的所有操作都成功完成时,事务被提交;当有任何一个操作失败时,事务将会被回滚,使得数据回到事务开始之前的状态。这样保证了数据库中的数据始终处于一致的状态。
持久性
事务持久性是指一旦事务成功提交,其所做的改变就会永久保存在数据库中,即使系统发生故障或意外断电也不会丢失。数据库系统通过将事务的操作记录持久化保存在磁盘上来实现事务的持久性,确保数据库的一致性和可靠性。要实现事务的持久性,数据库系统通常会使用日志记录和事务提交机制来保证事务的持久性。
隔离性
隔离级别(并发事务之间的关系)
隔离怎么理解?
隔离级别是相对于自己的事务还是其他事务
-->是相对于自己会话的事务来说的,先简单的拿读已提交为例;
自己会话的事务读取其他客户端的事务的数据必须是已经提交的;并不是自己设置事务为读已提交,其他客户端的事务就读不到的我的事务的数据了,有可能其他事务设置的是读未提交,如此,可以实时的获取我的事务的数据;
读未提交
那么什么是读未提交级别呢?
-->可以读到未提交的数据。就这么简单。
默认情况下,我开启了一个事务,还向表中插入了一行元组,但是我没有提交事务,由于事务的隔离性,其他事务是读不到我新插入的一行数据的,只能读到这个事务之前的数据;
但是,现在我把事务隔离级别设置为是“读未提交”,那么即便我不提交事务,其他客户端也可以读到我这个新插入的数据了;
总结:读未提交隔离级别下,事务的任何修改都是透明的,,都可以被其他客户端读到,但是他们没法访问;
代码示例:
设置全局事务隔离级别(读未提交):
Set global transaction isolation level read uncommitted;
查看全局事务级别:
SELECT @@transaction_isolation;
向表中插入一行数据但不commit,我们会发现右边的事务也能够看到新数据;
解释:
开启事务,向price表中插入一行数据,但不提交,再打开一个客户端,查看price表,发现新增了一条数据,
insert into price values(1,"小小",500);
事务回滚,重新查看price表,发现刚才的元组没了;
读已提交
只能读到其他事务已经提交的数据;如果别的客户端不提交事务,那么我们就读到的始终是旧数据;
设置隔离级别SQL语句: set session transaction isolation level read committed;
可重复读
可重复读,我们可以这么理解,我们设置当前会话隔离级别是可重复读,那么意思就是"放心读,不用担心数据会更改",事实是,他跟读已提交的区别就在于即便有其他事务把数据更改了提交了,我当前事务读到的数据依旧是原来的数据,不会改变,这就是可重复读;
所以可重复读级别下读到的数据是其他事务开始之前的数据;即便其他事务提交了,读到的数据也不会发生变化;
串行化(最严格的隔离级别)
将所有的事务串行执行,同一时间只有一个事务在执行;类似与加锁;--->效率问题
一致性
一致性简单来讲就是对数据的操作要合理;
比如:小红转给小明100块钱,那最后的结果就是小红余额减少100元,小明的余额增加100元,这就是要保持一致,如果小红的余额没减货或者小明的余额没增,那就是不一致;
一致性算是一种目的和要求,通过前面的原子性,隔离性,持久性来保证事务的一致性;
问题
不可重复读性(已经提交的数据)
在MySQL事务中,不可重复读(non-repeatable read)是指在同一个事务中多次读取相同的数据,但在读取过程中数据发生了变化,导致多次读取的结果不一致的情况。这可能会导致事务在处理过程中出现异常或错误的情况。
不可重复读的典型例子如下:
- 事务A在读取一行数据后,事务B修改了这行数据,然后事务A再次读取同一行数据,此时读取的数据已经发生了变化,造成不一致。
- 事务A在读取一批数据后,事务B删除了其中的一部分数据,然后事务A再次读取同一批数据,发现有部分数据已经被删除,导致不一致。
简单来说就是,我没有把握确定当前数据具体的值,因为他随时可能变化;
什么是脏读问题(未提交的数据)?
其他事务读到的数据可能被修改了,比如,事务A开启事务,事务B读到了一个数据行。但是B事务读取完毕后,事务A马上就修改了那一个数据行,所以就造成了事务B拿到的数据是"假数据",这就是"脏读“;
幻读
幻读是指一个事务在执行过程中,按照相同的查询条件多次查询,由于其他事务插入或删除了满足查询条件的新数据,导致结果集的行数发生变化。
重点:其他事务插入货删除数据,导致的结果集发生变化;
哪种隔离级别会出现幻读现象?
-->读未提交,读已提交;
这两种都是我在执行事务的时候可以读到别的事务操作过的数据;
保存点
SQL语句:savepoint 保存点名称;
开启事务后,可以通过设置保存点决定回滚到哪一次保存前的内容
示例:
准备好的一个表;
我向表中插入了两行数据,插入后保存了两个保存点;
现在我们回到保存点s1处的状态;我们会发现表就是s1保存时的状态;
现在试试能不能回到s2了;-->是无法回到时间点后面的保存点的;
自动提交机制--autocommit
SQL语句:Set autocommit=1(默认就是自动提交的)
因为默认就是自动提交的所以我这里设为不自动提交;
什么是默认提交呢?
-->顾名思义,就是我执行完任意一条SLQ语句后都相当于是一个事务,自动commit;
我们平时写的一个SQL语句就是一个事务;
下面我们来验证下,在不自动提交的情况下是什么样的:
首先,左边的我设置为不自动提交,右边的设置为自动提交,隔离级别都是可重复读;
我插入在左边的客户端向表中插入了一行数据,但是不commit;我们发现右边查不到新的数据,这是因为左边的事务没有提交,一个SQL语句已经不再是一个完整的事务了。
下面把左边的事务提交了试试看,发现左边的事务提交了之后,右边才可以看到新的数据行;
会话隔离级别与全局隔离级别
会话隔离级别:设置当前客户端的隔离级别,不会影响到其他的客户端的隔离级别。
全局隔离级别:设置所有客户端的隔离级别,对象是该服务端对应的所有的客户端;
简单来讲,一个是全局变量,一个是局部变量;使用的时候是局部优先,因此我们修改会话级别的时候记得修改当前会话的级别,如果修改的是全局的隔离级别,其实还是使用的局部的会话隔离级别,记得检查一下;