这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战
我们今天来了解一下事务,写事务的原因是因为比较重要,而且大家都在写,所以我也想结合玩我自己的想法,谈谈自己的理解。
事务
什么是事务呢?其实是针对数据库的,数据库有最基础的增删改查操作,但问题是一次业务的完成可能附带一系列的增删改查,也就是修改数据库操作,怎么保证一次业务操作对数据库操作的逻辑上的正确性是我们要考虑的问题。
因为这一个业务,包含很多数据库相关的操作,要是有哪个操作失败了,或者是预期的失败或者是未预期的失败,我们能让这次业务操作数据更新成功嘛?是不是就不能了,因为我们要保证数据的什么?正确性,这个正确性可不光是一个库的数据,而是多个库的数据。
事务的特性
怎么保证数据的正确性?肯定不是单一层面保证,而是多层面,
- 操作层面:原子操作,要么全部成功,要么全部失败,不存在概率成功的情况。
- 数据层面:数据一致性,不管是跨表、跨行或跨事务,数据在各表的状态都要符合我们设定的逻辑。
- 事务层面:隔离性,多个事务之间的并发操作,彼此不干扰,就是一个事务不能去读到另一个事务还没操作完的数据,有4种隔离级别。
- 数据库层面:一旦事务提交数据,要永久化保存,不管是数据库挂了还是服务器挂了。
我们可以总结一下:怎么保证数据落盘的正确性呢?首先,我们一个业务可能存在多个事务,需要保证事务之间互不干扰,事务里面包含多个操作,需要这些操作全部正确执行,这些操作里面呢,会涉及多个表,保证这些对数据的操作符合我们的逻辑,最后呢,数据落盘持久化保存,就能保证我们的数据的正确性了。
讲完了这些,我们可以趁热打铁,熟悉下Spring给我们提供的事务的传播特性。
事务传播特性
关于事务,Spring给出了自己的解决方案,并发事务之间怎么操作呢?Spring有它的解决方案,供你选择:
其实,我们还可以先思考一下事务之间的关系,一个事务要么有或者没有,你有没有事务不要紧,事务之间的联系不取决于有没有,而取决于有没有事务到底是重要还是不重要,对吧。(这就和回家过年一样,有钱没钱一样回家过年,因为过年重要)
事务重要不抛异常
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED):当前有事务就用当前,没有搞新的。
NESTED(TransactionDefinition.PROPAGATION_NESTED):当前有事务就启新的。
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW):之前事务可有可无,都开个新事务
事务重要抛异常
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY):事务非常重要,没有就得抛异常。
事务不重要不抛异常
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),事务可有可无,不是必须。
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED):事务不支持,按非事务运行。
事务不重要抛异常
NEVER(TransactionDefinition.PROPAGATION_NEVER):事务不支持,有事务抛异常。