欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-02 11:47:53
...

事物

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

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

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提交后才会返回结果;