事务(ACID)、数据库事务回滚(脏读、幻读、不可重复读)

1. 事务特性

应该具有4个属性:原子性一致性隔离性持久性。这四个属性通常称为ACID特性。*

1- 原子性(atomicity)
一个事务是一个不可分割的工作单位,事务中包括的所有操作要么全部提交成功,要么全部失败回滚。对于一个事务来说,不可能只执行其中的一部分操作。

最经典的例子:我给你转了10000RMB(大方点hh),你的账号会多10000块,我的账户会少10000块。
(这是个资金的流转,要么同时成功,要么同时失败)

begin; -- 开始一个事务
update table set A = A - 100; 
update table set B = B + 100;
-- 其他操作
commit; -- 提交事务

begin和commit之间所有操作完成后,才能成功保存到数据库
只要有一条操作失败,就撤销之前的操作,这要就保证了同生共死


2- 一致性(consistency)

  • 事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

一 个或多个事务执行后,原来一致的数据和数据库仍然是一致的。
数据库总是从一个一致性的状态转换到另外一个一致性的状态。在前面的例子中,一致性确保了,即使在执行第三、四条语句之间时系统崩溃,CMBC账户中也不会损失100万,不然因为事务最终没有提交会导致很严重的影响,所以事务中所做的修改也不会保存到数据库中。


3- 持久性(durability)

  • 持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。持久性是个有点模糊的概念,因为实际上持久性也分很多不同的级别。有些持久性策略能够提供非常强的安全保障,而有些则未必。而且「不可能有能做到100%的持久性保证的策略」否则还需要备份做什么。

4- 隔离性(isolation)
通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。在前面的例子中,当执行完第三条语句、第四条语句还未开始时,此时如果有其他人也准备给lemon的CMBC账户存钱,那他看到的CMBC账户里还是有100万的。

2、拓展:事务隔离级别

脏读


在事务A修改数据之后提交数据之前,这时另一个事务B来读取数据,如果不加控制,事务B读取到A修改过数据,之后A又对数据做了修改再提交,则B读到的数据是脏数据,此过程称为脏读Dirty Read。


不可重复读


一个事务内在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了变更、或者某些记录已经被删除了。


幻读


事务A在按查询条件读取某个范围的记录时,事务B又在该范围内插入了新的满足条件的记录,当事务A再次按条件查询记录时,会产生新的满足条件的记录(幻行 Phantom Row)


3、相关问题

(1)不可重复读与幻读有什么区别?
不可重复读:第一次读的数据和第二次读的「数据不一样」。(因为中间有其他事务提交了修改)
幻读:第一次和第二次读出来的「记录数不一样」。(因为中间有其他事务提交了插入/删除)

(2)如何保证隔离性(Isolation):
有多个事务同时进行,最后结束时,最终的结果应该是相同的
原子性的问题解决了,但是在另外的事务中同时修改数据,数据的一致性就会被破坏,所以要有隔离机制,一个事务完成后,另一个事务才能开始,要加上互斥锁。
具体步骤:
1.先获得锁,然后才能修改数据A
2.修改并提交事务之后释放锁,给下一个要修改数据A的事务
3.然后第二个事务开始修改数据并提交。
对于同一个数据,只有一个事务能持有互斥锁,没有锁的事务,需要等待其他事务释放锁
只有当事务提交或者回滚后,才能释放锁。在这期间,其他事务只能读取数据

(3)隔离级别:
1.串行化:最高的隔离级别,两个事务百分百隔离,串行执行。
2.可重复读(MySQL默认模式):这些数据对其他正在执行的事务是可见的。如果成功修改了一条数据,修改结果对于正在运行的事务仍然不可见。所以只是对于新数据产生了新隔离,旧数据还是旧隔离。
3.读取已提交(Read committed,Oracle、PostgreSQL、SQL Server默认模式):可重复读+新的隔离突破,A事务在读取D数据时,B事务对D数据进行了删除或者修改操作并提交,A重新读取时就会看到B事务修改以后的数据。A事务在第一次读取的数据和第二次数据不一样,这叫幻读
4.读取未提交:读取已提交+新的隔离突破:A事务在读取D数据时,B事务对D数据进行了删除或者修改操作并提交,A重新读取时就会看到B事务修改以后的数据。但是此时B事务出错回滚了,A还是会看到B事务修改的数据结果,看到的数据是毫无用处的,这叫脏读
此部分原文链接:https://blog.csdn.net/weixin_43326401/article/details/104003945

这篇文章不错自己看吧,懒得写了
网址:https://www.zhihu.com/question/31346392

猜你喜欢

转载自blog.csdn.net/weixin_43889487/article/details/121842897