作者:jp85201 | 来源:互联网 | 2023-10-13 09:21
什么是事务?事务是由一步或几步数据库操作序列组成逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。程序和事务是两个不同的概念。一般而言:一段程序中可能包含多个事务。(说白了就
什么是事务?
事务是由一步或几步数据库操作序列组成逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。程序和事务是两个不同的概念。一般而言:一段程序中可能包含多个事务。(说白了就是几步的数据库操作而构成的逻辑执行单元)
为什么需要有事务
了解事务之前,先来看看数据库为什么需要有事务,假设没有事务会有什么影响?
举一个转账的例子,假设你朋友向你借10000元,你打开APP,乐呵呵的把钱转了,你的卡里已经少了10000元,但是你打电话给朋友时,你朋友说没有收到啊,你这时候肯定卖银行怎么不靠谱,没到账怎么把我卡里的钱给扣了。
我们来捋一捋上述银行发生的过程,简单的分三步:
A发起转账10000给B -> A银行卡减10000元 -> B银行卡增加10000元。
上述案例是第三步出现了问题,如果有事务,则不会发生案例中的事情,可以理解为事务就是这三个步骤是一根绳子上的蚂蚱,要么都成功,要么都失败。
所以数据库引入事务的主要目的是事务会把数据库会从一种一致状态转换到另一种一致状态,数据库提交工作时可以确保要么所有修改都保存,要么所有修改都不保存。
了解事务,还需要了解事务的理论依据ACID,也可以说事务的几个特性。
ACID
A(Atomicity) 原子性
还是上面转账的例子,原子性强调转账从A-B的三个步骤必须要么都成功,要么都不成功。
原子性是整个数据库事务是不可分割的工作单位,只有事务中的所有的数据库操作都执行成功,才算整个事务成功。事务中任何一个SQL执行失败,已经执行成功的SQL语句也必须撤销,回到执行事务的之前的状态。
C(Consistency) 一致性
一致性是指事务将数据库从一种一致性状态变为下一种一致性状态。在事务开始之前和之后,数据库的完整性约束没有被破坏。
上面转账的例子,无论转账成功或者失败,A和B加起来变化就是10000元,不会多也不会少。
I(Isolation) 隔离性
隔离性要求每个读写事务对其他事务的操作对象能相互分离。
比如A转账的银行是工商银行,那么别人在工商银行转账不能干扰A的转账行为。
D(Durability) 持久性
持久性指事务一旦提交,其结果就是永久性的。
事务的实现
事务隔离级别
数据库事务的隔离级别有4种,由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable
。而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读。下面通过事例一一阐述它们的概念与联系。
Read uncommitted 未提交读
事物中的修改,还没有提交,对于其他的事物是可见的。藏读。
读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。
事例:老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交。
分析:实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是==脏读==。
如何解决脏读?读提交。
Read committed 已提交读
解决了脏读问题。就是一个事务要等另一个事务提交后才能读取数据。
事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(程序员事务开启),收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(==第二次检测金额当然要等待妻子转出金额事务提交完==)。程序员就会很郁闷,明明卡里是有钱的…
分析:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了==一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。==
如何解决不可重复读?可重复读。
Repeatable read 可重复读
就是在开始读取数据(事务开启)时,不再允许修改操作
事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(==事务开启,不允许其他事务的UPDATE修改操作==),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。
分析:重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,==不可重复读对应的是修改,即UPDATE操作==。但是可能还会有==幻读==问题。因为==幻读问题对应的是插入INSERT操作,而不是UPDATE操作。==
事例:程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开启),看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即==新增INSERT==了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻觉,这就是幻读。
那怎么解决幻读问题?Serializable。
Serializable 序列化
可串行化:对行进行加锁读,可能会导致锁超时。
Serializable 是最高的事务隔离级别,在该级别下,事务==串行化顺序执行==,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。