文章目录
一、事务
事务,是由一组操作构成的可靠的独立的工作单元,事务具备ACID的特性,即原子性、一致性、隔离性和持久性。
二、事务的四大特性
2.1 原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。
2.2 一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态。
也就是说事务前后数据的完整性必须保持一致。
2.3 隔离性(Isolation)
隔离性是指一个事务的执行不能有其他事务的干扰,事务的内部操作和使用数据对其他的并发事务是隔离的,互不干扰。
2.4 持久性(Durability)
持久性是指一个事务一旦提交,对数据库中数据的改变就是永久性的。此时即使数据库发生故障,修改的数据也不会丢失。接下来其他的操作不会对已经提交了的事务产生影响。
三、事务的几个问题
多个事务并发执行时,读取数据方面可能碰到三个问题:
- 脏读:读到了脏数据,即无效数据。
- 不可重复读:是指在数据库访问中,一个事务内的多次相同查询却返回了不同数据。(修改)
- 幻读:指同一个事务内多次查询返回的结果集不一样,比如增加了行记录。(新增)
备注:不可重复读对应的是修改update操作。幻读对应插入操作。幻读是不可重复读的特殊场景。
四、事务的隔离级别
提高事务隔离级别的目的:解决脏读、不可重复读、幻读等读现象。
矛盾:隔离级别越高,并发能力就越低。所以,需要根据业务来场景来衡量使用哪种隔离级别。
隔离级别由低到高如下:
-
Read uncommitted(读未提交) :一个事务可以读取另一个未提交事务的数据。
示例:小明去商店买衣服,付款时,小明发起事务,但还没有提交。而商店老板查看自己账户,发现钱已到账(读未提交),于是小明正常离开。【可能事故:小明在走出商店后,马上回滚差点提交的事务,撤销了本次交易,于是小明没花钱就买到了衣服】
-
Read committed (读已提交):一个事务要等另一个事务提交后才能读取数据。在事务A处理期间,如果事务B修改了相应的表,则事务A的同一读sql在事务B执行前后的返回结果是不同的。(会造成幻读、不可重复读)
示例:小明卡里有1000元,聚餐时,准备计算1000元(事务开启),收费系统检测到他卡里有1000元。收费系统检测完毕时,小明的老婆转成功走了卡里的钱。【可能事故:当收费系统准备扣款时,再检查小明卡里的金额,发现已经没钱了,付款不成功。】
-
Repeatable read (重复读):在开始读取数据(事务开启)时,不再允许修改操作。
示例:还是小明有1000元,准备跟朋友聚餐消费这个场景,当他买单(事务开启)时,收费系统检测到他卡里有1000元,这个时候,他的女朋友不能转出金额。接下来,收费系统就可以扣款成功了
问题拓展:写和读在同一事务的操作
第一步:更新A表id=1的记录
第二步:查询A表id=1的记录
第三步:使用第二步的查询结果作为依据继续业务逻辑
第四步:提交事务
问题:同一个事务中,事务未提交前,第二步的查询结果是第一步执行前的结果还是第一步执行后的结果?
答案:是第一步执行后的记过。事务隔离级别是针对不通事务的,同一事务中的未提交的更新,在后续是可以查询到的。 -
Serializable (序列化)
数据库事务的最高隔离级别。在此级别下,事务串行执行。可以避免脏读、不可重复读、幻读等读现象。但是效率低下,耗费数据库性能,不推荐使用。
五、MySQLh和Spring的事务隔离级别
-
MySQL和Spring默认的事务隔离级别:重复读REPEATABLE-READ,可以避免脏读,不可重复读,不可避免幻读
-
mysql查看数据库实例默认的全局隔离级别sql
(1) Mysql8以前:SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
(2) Mysql8开始:SELECT @@GLOBAL.transaction_isolation, @@transaction_isolation; -
修改MySQL隔离级别命令:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
六、分布式事务
-
分布式锁解决分布式资源抢占的问题;
-
分布式事务和本地事务是解决流程化提交问题。
-
分布式事务为什么复杂?
(1)存储端的多样性。本地事务的情况下,所有数据都会落到同一个DB中,但是,在分布式的情况下,就会出现数据可能要落到多个DB,或者还会落到Redis,落到MQ等中。
(2)请求链路被延展拉长,一个操作会被拆分成多个服务,它们呈现线状或网状,依靠网络通信构建成一个整体。
分布式事务要求:保证分布式系统中的数据一致性,保证数据在子系统中始终保持一致,避免业务出现问题。分布式系统中对数要么一起成功,要么一起失败,必须是一个整体性的事务。
举个例子:在电商网站中,用户对商品进行下单,需要在订单表中创建一条订单数据,同时需要在库存表中修改当前商品的剩余库存数量,两步操作一个添加,一个修改,我们一定要保证这两步操作一定同时操作成功或失败,否则业务就会出现问题。
6.1 分布式中的CAP理论
- 一致性(Consistency) : 客户端知道一系列的操作都会同时发生(生效)
- 可用性(Availability) : 每个操作都必须以可预期的响应结束
- 分区容错性(Partition tolerance) : 即使出现单个组件无法可用,操作依然可以完成
6.2 分布式事务解决方案——TCC
TCC 分布式事务模型需要业务系统提供三段业务逻辑:
-
初步操作 Try:完成所有业务检查,预留必须的业务资源。
-
确认操作 Confirm:真正执行的业务逻辑,不作任何业务检查,只使用 Try 阶段预留的业务资源。因此,只要 Try 操作成功,Confirm 必须能成功。另外,Confirm 操作需满足幂等性,保证一笔分布式事务有且只能成功一次。
-
取消操作 Cancel:释放 Try 阶段预留的业务资源。同样的,Cancel 操作也需要满足幂等性。
6.3 分布式事务解决方案——二阶段/三阶段
略…