主要内容:
- 事务概念
- 事务特性
- 事务不一致性问题
说到数据库,大家就会想到事务。对于事务来说,会想到事务的特性ACID以及不一致性问题,这里深入讲解下这两点。
事务
说事务特性之前,思考下什么是事务呢?事务其实就是一组相互依赖的操作序列,那么事务的成功意味着这些操作行为都要成功执行,如果有一个行为失败,整个事务也是失败的。举个最常见的例子银行转账业务,A向B账户转账100元,这个事务分为两个操作行为:操作1——A账户减少100元,操作2——B账户增加100元。
事务特性
原子性
高中物理说过,原子是化学反应中不可分割的基本微粒。事务的原子性呢,就是事务中的操作行为是不可分割的工作单元,这些操作要么全部操作成功事务成功,要么某个行为失败事务回滚。
用例子来说明,如果转账过程中A账户减少了100元操作成功,但是往B账户增加100元操作失败,那么这个事务是失败的,回滚到最初状态,即要么全部失败。
一致性
事务的一致性指事务执行之前和执行之后必须处于一致性状态,这样说比较难懂。
举例子来说明,A和B账户总金额为1000元钱,那么A向B账户转账事务执行成功以后,A和B账户的总金额还是1000元钱。
隔离性
隔离性指一个事务的操作以及用到的数据对其他并发的事务是隔离的,并发执行的各个事务之间互不干扰。即使多个事务并发执行,看上去的效果是多个成功事务串行调度执行,事务感觉不到其他并发事务的执行。
举个例子,例如两个并发的事务T1和T2,从T1角度看,T2要么在它执行之前已经结束,要么在它执行完成后才开始。
持久性
持久性指的是如果一个事务被提交了,那么事务对数据库所做的修改是持久的,系统崩溃或者机器故障对它都是不会产生影响的。
比如例子中如果A向B账户转账成功以后,那么这个转账记录就会保存,不用担心丢失这个记录。
事务的不一致性
事务是并发控制的基本单位,如果多个线程都开启事务操作数据库中的相同数据时,如果没有采取隔离性措施,那么可能会造成数据的不一致性。并发操作带来的数据不一致性问题主要分为四类,接下来具体介绍下这四类。
丢失更新
多个事务获取同一个数据,并且都基于原始数据进行更新,而每个事务都不知道其他事务的存在,所以最后的更新将会覆盖其他事务的更新操作。
举订票操作来说明,
- t1时刻事务T1中A售票员查询某一班车的剩余票数D为10;
- t2时刻事务T2中B售票员查询同一班车的剩余票数D也为10;
- t3时刻事务T1售票员A卖出一张票,剩余票数D修改为9,写入数据库;
- t4时刻事务T2售票员B也卖出一张票,因为t2时刻读取到的剩余票数为10,修改为9并写入数据库。最后结果为9,但其实是卖出了两张票,事务T2的修改覆盖了事务T1的修改,即丢失更新问题。
脏读
脏读指事务获取到了脏数据,具体说是一个事务读取到了另一个未提交事务中的数据。
举发工资的例子来说明,
- 事务T1开始,hr给李四发5000元工资,但还没有提交事务。
- 这时候事务T2李四查看自己工资,发现有5000元,激动人心。
- 但事务T1中hr发现工资计算错误,工资应该是4000元,回滚了事务。那么事务T2李四读取到的数据和数据库中数据是不一致,即所谓的脏数据。
不可重复读
对于某个数据,一个事务范围内多次查询该数据获得了不同的返回结果。即事务T1包含多次查询操作,第一次读取数据后,在事务T1时间范围内事务T2对该数据进行修改并提交,下一个操作再次查询该数据,就会得到和第一次不同的结果。
幻读
一个事务在提交查询结果前,另一个事务对数据进行了修改导致了该查询结果的更改,产生了幻读。
- 事务T1,李四查询这个月信用卡总共消费笔数,但没有提交查询结果。
- 事务T2张三使用这个信用卡消费了新的一笔交易。
- 这时候事务T1再次查询消费笔数发现笔数增加,产生了幻觉。
比较
可以发现幻读和不可重复读都是读取了已提交事务的数据,而不可重复读针对的是同一条数据,幻读针对一批数据(例如统计数据的个数)。