一.为什么需要事务
1.1上图是一个简单的转账逻辑,A账户转账100到B账户,但是有可能在A转账到B的过程中会出现问题比如:
1.1.1A账户已经减少100了,但是在B账户增加的时候出现了异常,此时就会导致A账户钱少了100,但是B账户又没有增加。
1.1.2A账户减少了100,B账户也增加了100,但是在此时由于某些原因系统崩溃了,系统重启恢复的时转账记录已经丢失了。
1.1.3A账户转账给B的同时,又有其他用户給B转账,导致最终的金额出现了异常
二.事务的概念
2.1数据库访问并有可能更新的各种数据项的一个程序执行单元
三.事务的组成
3.1一个数据库事务通常包含对一个数据的读写操作的序列
3.2比较典型的事务:
3.3事务的相关特性
3.3.1.数据库事务可以包含一个或多个数据库操作,但这些操作构成一个逻辑上的整体。
3.3.2.构成逻辑整体的这些数据库操作,要笔记全部执行成功,要么全部执行不成功。文稿
3.3.3.构成事务的所有操作要么全都对数据库产生影响,要么全都不产生影响,即不管事务是否执行成功,数据库总能保持一致性状态
3.3.4.以上即使在数据库出现故障以及并发事务存在的情况下依然成立。
四.事务的四大特性
4.1原子性
4.1.1 事务中所有的操作是不可分割的,是一个整体,要么全部成功,要么全部失败
4.2一致性
4.2.1事务的执行结果必须是从一种一致性到另外一种一致性,比如: A是100元,B也是100元,他们总金额是200,A给B转账50,B增加50,总金额依然是200,这就是事务的一致性,
4.3隔离性
4.3.1事务的并发执行并不互相影响,结果依然是很他们串行化一样,(串行化就是没有并发一个一个执行)
4.4持久性
4.4.1事务一旦提交了,对于数据库的更新都是持久的,无论是数据库崩溃还是什么,对于数据没有任何影响
五.事务并发异常
5.1丢失更新
5.1.1 丢失更新是指事务覆盖掉了其他事务对数据已经提交的修改,导致其他事务对数据的操作跟丢失了一样
5.2脏读
5.2.1 脏读是指事务读取到了,其他事务对数据修改还未提交的数据
5.3幻读
5.3.1指事务读取某个范围的数据时因为其他事务的操作导致前后两次读取的结果不一致
5.4不可重复读
5.4.1 指事务对同一数据两次的读取结果不一致
六.事务并发异常案例
6.1 脏读:
A事务读取了B事务尚未提交的更改数据,并在这个读取的脏数据上进行操作。如果这时B事务恰巧进行了回滚事务,那么A事务读取的事务是不被承认的。如下取款事务和转账事
6.2 幻读:
A事务读取到B事务提交的新增数据,幻象读一般发生在数据统计事务中,如下所示
6.3 不可重复读:
是指A事务读取到了B事务已经提交的更改数据,在同个时间段内,两次查询的结果不-一致。
七.事务的隔离级别
7.1什么是隔离级别
事务并发操作对同一批数据的操作可以通过隔离级别来解决
7.2隔离级别的分类
7.2.1 读未提交(READ UNCOMMITTED)
7.2.1 读已提交(READ COMMITTED)--Oracle默认级别
7.2.1 可重复读(REPEATABLE READ)--MySQL默认级别
7.2.1 串行化(SERIALIZABLE)
7.3隔离级别解决的并发带来的问题
八.并发异常之丢失更新解决方案
8.1悲观锁机制
8.1.1什么是悲观锁: 悲观锁就是认为对于数据的操作他一定会修改,所以一开始就直接锁上,很悲观
8.1.2假定这样的问题是高概率的,最好一开始就锁住,免得更新老是出。
添加共享锁方式: select* from accountlockin share mode
添加排它锁方式: select*from account for update;
8.2乐观锁机制
8.2.1 什么是乐观锁: 乐观锁就比较乐观了他认为对于数据的操作可能不会修改,所以只是在最后提交的时候在去锁住,
8.2.2假定这样的问题是小概率的,最后一步做更新的时候再锁住,免得锁住时间太长影响其他人做有关操作。
在表中增加一个类型是timestamp 字段,并将其设置只要该表进行插入或修改操作时都会更新该字段为最新时间;
在修改数据时通过检查timestamp 是否改变判断出当前更新基于的查询是否已经是过时的版本