事务、事务的隔离级别、一致性

事物

定义:
数据库事务指的是一组数据操作,事务内的操作要么就是全部成功,要么就是全部失败,什么都不做;

事务具有原子性一致性隔离性持久性

https://www.runoob.com/mysql/mysql-transaction.html

  • A 原子性:一个事务中的所有操作,要么全部执行,要么全部不执行。
  • C 一致性:在事务开始之前和事务结束以后,数据库的一致性没有被破坏。
  • I 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,各个事务不干涉内部数据,处理的都是另外一个事务处理之前或之后的数据。
  • D 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

原子性

原子性强调的是操作的完整性,连续的操作不可分割,要么全部成功,要么全部失败。


一致性

https://blog.csdn.net/l1394049664/article/details/81814090

一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

这里说的一致性状态是指:  
1. 系统的状态满足完整性约束,主码、参照完整性、check约束等;  
2. 系统的状态满足反应现实世界的真实状态,比如转账前后2个账户的总金额应保持不变,这里依赖程序员实现;

隔离性

多个事物之间不能互相干扰;


持久性

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。


MySQL如何保证事务的ACID

A原子性由undo log日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql

C一致性一般由代码层面来保证

I隔离性由MVCC来保证(也说是通过锁来实现)

D持久性由内存+redo log来保证,mysql修改数据同时在内存和redo log记录这次操作,事务提交的时候通过redo log刷盘,宕机的时候可以从redo log恢复


事务的隔离级别

以下几个概念是事务隔离级别要实际解决的问题,所以需要搞清楚都是什么意思。

重要概念

脏读

脏读指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并一定最终存在的数据,这就是脏读。

不可重复读

不可重复读指的是在同一事务内,不同的时刻读到的同一批数据可能是不一样的,可能会受到其他事务的影响.

事务 T1 读取某一数据后,事务 T2 对其做了修改,当事务 T1 再次读该数据时得到与前一次不同的 值。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。

幻读

幻读 : 事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据或者缺少了第一次查询中出现的数据(并不要求两次查询的 SQL 语句相同)。这是因为在两次查询过程中有另外一个事务插入数据造 成的

不可重复度和幻读区别:
不可重复读的重点是修改,幻读的重点在于新增或者删除

https://blog.csdn.net/sanyuesan0000/article/details/90235335


SQL 标准定义了四种隔离级别,MySQL 全都支持。这四种隔离级别分别是:

读未提交(READ UNCOMMITTED)
读提交 (READ COMMITTED)
可重复读 (REPEATABLE READ)
串行化 (SERIALIZABLE)

越往下,效率越低;

mysql默认的事务隔离级别时rc,spring事务默认是rr;


Read uncommitted读未提交

读未提交 是指 读取到 未提交的事务.

例如 b往a账号转100元,但是还未提交事务,那么此时a可以看到b转给自己100元,但是b也可以回滚事务,那么a的账号就是0元。

当隔离级别设置为Read uncommitted时,就可能出现脏读


Read committed 读已提交

设置为读已提交

SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;

只有事物提交后,其他事物才能读到更新后的数据。

读提已提交,避免了脏读,但是不能避免 不可重复读幻读

不可重复读:例如事物a,先读取了数据,事务b修改并提交了事物,当事物a再读取该数据时是不同的。

幻读:例如事物a,先读取了某表(还未提交事物),事务b 删除 或者新增了这张表的数据 并提交了事物,当事物a再读取该表数据时数据量是不同的。


Repeatable read 可重复读(MySQL默认)

https://blog.csdn.net/sanyuesan0000/article/details/90235335

SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;

事物a在事物期间,即使事物b修改了数据并提交了事物,事物a读取的数据是不变的。
但是增删的数据能读取到,修改的数据是不变的。

解决了不可重复读的问题,但不能解决幻读的问题;

例如,num1=30,事物a第一次读 num1=30(事物a还未提交事物),此时事物b对num1进行了修改num1=20 并且增加了一条数据num2=100 并提交了事物,然后事物a第二次读数据时num1=30,num2=100,num1依旧不变但却凭空多了个num2(幻读);

注意

上面只是一般对幻读的理解,但在mysql中Repeatable read,上面出现的幻读被innodb的mvcc避免了,也就是说,在mysql中会出现以下的情况:

例如,num1=30,事物a第一次读 num1=30(事物a还未提交事物),此时事物b对num1进行了修改num1=20 并且增加了一条数据num2=100 并提交了事物,然后事物a第二次读数据时依旧只有num1=30(增加的数据也看不到);

但是mysql中会出现以下的幻读情况:
例如,事物a查询后发现没有ID(主键)=5的数据,此时事物b增加了一条ID=5的数据 并提交了事物,然后事物a增加了一条ID=5的数据,但此时必然主键冲突。


Serializable 串行化

Serializable是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。

例如,事物a对数据操作的期间,事物b的修改、增加、删除操作会被阻塞并不会返回结果(查询不会被阻塞),只有当事物a提交后才会返回结果;

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring的事务隔离级别包括READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE,以及一个数据库默认的隔离级别DEFAULT,而MySQL默认的隔离级别是REPEATABLE_READ。 事务隔离级别是用来控制并发事务之间的可见和影响范围的。在数据库事务隔离级别中,隔离(isolation)是ACID特的一部分,它保证了并发事务的相互隔离,使得每个事务在看待数据时都能够获得一致和可靠的结果。 事务隔离级别主要涉及到并发事务的读取和写入操作的可见。具体来说,事务隔离级别决定了一个事务对另一个事务所做的修改的可见。在不同的隔离级别下,事务之间的可见有所不同,包括脏读、不可重复读、幻读等现象。 READ_UNCOMMITTED(读未提交)是最低的隔离级别事务可以读取到其他未提交事务的修改。这可能导致脏读的问题,即读取到未提交的数据。 READ_COMMITTED(读已提交)是常见的隔离级别,默认也是Spring的默认隔离级别事务只能读取到已经提交的数据,避免了脏读问题。但是,可能会出现不可重复读的问题,即一个事务中多次读取同一数据,但得到的结果可能不同。 REPEATABLE_READ(可重复读)是较高的隔离级别,保证了在一个事务中多次读取同一数据时,得到的结果是一致的。它避免了脏读和不可重复读的问题。但是,可能会出现幻读的问题,即一个事务中多次查询同一范围的数据,但得到的结果集可能不同。 SERIALIZABLE(串行化)是最高的隔离级别,它通过强制事务串行执行来避免脏读、不可重复读和幻读的问题。但是,它也造成了并发能的降低,因为事务需要一个接一个地执行。 在Spring中,可以通过设置@Transactional注解或配置文件来指定事务隔离级别。例如,在@Transactional注解中,可以使用isolation属指定隔离级别。默认情况下,Spring会使用数据库的默认隔离级别

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值