采访又被问到事了,加油,要么滚,要么躺。如果卷不移动或平放,是否会导致数据不一致?事务概念事务是数据库管理系统执行过程中的一个逻辑单元,由有限的数据库操作序列组成。简单来说,要么所有的执行都成功,要么都失败。它的最终目标:数据不会被破坏。即事务操作成功,数据结果与业务预期结果一致。事务的属性一个逻辑工作单元必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性才能成为一个事务。1:原子性:原子性要求事务作为一个不可分割的整体执行,其中包含的对数据库的操作要么全部执行,要么不执行(如果其中一个操作失败则全部失败)。2:一致性:一致性要求事务保证数据库的状态从一种一致的状态变化到另一种一致的状态。一致状态的意思是数据库中的数据应该满足完整性约束。执行前数据之间的一致性状态===执行后数据之间的一致性状态3:隔离性:事务的隔离性要求多个事务并发执行时,一个事务的执行不能影响其他事务的执行。4:持久性:事务的持久性是指一旦整个事务提交成功,对数据的修改应该永久保存在数据库中,不可逆。隔离事务规定了4个隔离级别(从弱到强):ReadUncommittedReadCommittedRepeatableReadSerializableDirtyread、non-repeatableread)、幻读(phantomread)。1:ReadUncommitted(读未提交):一个事务可以读取另一个未提交事务的数据。2:已提交读(ReadCommitted):一个事务不能读取数据,直到另一个事务被提交。3:可重复读(repeatableread):当开始读取数据(事务开启)时,不再允许进行修改操作。4:Serializable(序列化):Serializable是最高的事务隔离级别。在这个层次上,事务是按串行顺序执行的,可以避免脏读、不可重复读和幻读。大多数数据库默认的事务隔离级别是Readcommitted,比如SqlServer、Oracle。MySQL的默认隔离级别是Repeatableread。Spring事务的传播级别和数据隔离级别是事务控制的两个主要特性。传播级别定义了事务的控制范围,事务隔离级别定义了事务在数据库读写方面的控制范围。Spring事务传播有七种类型,REQUIRED、SUPPORTS、REQUIRES-NEW、NOT-SUPPORTED、MANDATORY、NEVER、NESTED。以下思维导图:Spring事务的传播特性介绍:PROPAGATION_REQUIRED:如果有事务,则支持当前事务。如果没有事务,则开始一个新事务。PROPAGATION_SUPPORTS:如果有事务,支持当前事务。如果没有事务,则非事务执行。PROPAGATION_MANDATORY:如果事务已经存在,则支持当前事务。如果没有活动事务,则会抛出异常。PROPAGATION_REQUIRES_NEW:总是开始一个新的事务。如果事务已经存在,则暂停现有事务。PROPAGATION_NOT_SUPPORTED:始终以非事务方式执行,暂停任何现有事务。PROPAGATION_NEVER:始终以非事务方式执行,如果有活动事务,将抛出异常7.(spring)PROPAGATION_NESTED:如果存在活动事务,它将在嵌套事务中运行。如果没有活动事务,则按TransactionDefinition强制执行.PROPAGATION_REQUIRED属性。Spring事务传播特性总结:1、只要把bean定义为spring,就可以在里面的方法上使用@Transactional注解。2、Spring的事务传播是Spring特有的。不是底层jdbc的代理。3.使用spring声明式事务。Spring使用AOP来支持声明式事务。它会根据事务属性自动决定是否在[调用方法]之前开启一个事务,[在方法执行之后]决定是否提交或回滚事务。4、Spring支持的PROPAGATION_NESTED和PROPAGATION_REQUIRES_NEW的区别:PROPAGATION_REQUIRES_NEW:两个事务之间没有信任关系,不会出现A事务成功依赖B事务的情况。有可能A提交B失败,A失败(比如执行到doSomeThingB时抛出异常),B提交,AB提交,AB失败。PROPAGATION_NESTED:与PROPAGATION_REQUIRES_NEW不同,嵌入式事务B会信任A。即存在A失败B失败。A成功,B失败。A成功,B成功。没有A失败和B成功这样的事情。5、特别注意PROPAGATION_NESTED的使用情况:使用JDBC3.0驱动时,只支持DataSourceTransactionManager作为事务管理器。需要JDBC驱动程序的java.sql.Savepoint类。有一些JTA的事务管理器实现可以提供相同的功能。要使用PROPAGATION_NESTED,还需要将PlatformTransactionManager的nestedTransactionAllowed属性设置为true;nestedTransactionAllowed属性值默认为false;6、特别注意PROPAGATION_REQUIRES_NEW的使用条件:JtaTransactionManager作为事务管理器的Spring事务的隔离级别?Spring事务的隔离级别:ISOLATION_DEFAULT:这是一个PlatfromTransactionManager默认的隔离级别,使用数据库的默认事务隔离级别。ISOLATION_READ_UNCOMMITTED:这是一个事务的最低隔离级别,它允许另一个事务看到这个事务未提交的数据。ISOLATION_READ_COMMITTED:保证一个事务修改的数据在提交后只能被另一个事务读取。另一个事务无法读取此事务未提交的数据。ISOLATION_REPEATABLE_READ:这个事务隔离级别可以防止脏读和不可重复读。但是,可能会出现幻读。除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免以下情况(不可重复读)。ISOLATION_SERIALIZABLE这是最昂贵但最可靠的事务隔离级别。事务处理为顺序执行。除了防止脏读和不可重复读,还要避免幻读。除了第一个是spring特有的,其他四个对应的是JDBC的隔离级别。第二个隔离级别会产生脏读、不可重复读和幻读,尤其是脏读,一般是不允许的,所以很少使用这个隔离级别。大多数说数据库默认的grid基本都是第三种。它消除了脏读,但不能保证可重复读取。第四个隔离级别也有一些数据库作为默认的隔离级别,比如MySQL。最后一个用得不多。除非对多数据访问的要求特别高,否则不要轻易使用,因为它会严重影响数据库的性能。Spring事务架构?Spring的事务框架设计理念的基本原则是:让事务管理关注点与数据访问关注点分离。架构Spring的事务抽象包括三个主要接口,分别是PlatformTransactionManager、TransactionDefinition和TransactionSatus。PlatformTransactionManager负责定义事务边界;TransactionDefinition负责定义事务的相关属性,包括隔离级别、传播行为等;PlatformTransactionManager参考TransactionDefinition的属性定义开启相关交易。TransactionStatus负责事务开始到事务结束的事务状态,我们可以通过TransactionStatus对事务进行有限的控制。TransactionDefinition常用的实现有DefaultTransactionDefinition和TransactionTemplate(这两个主要用于程序化事务场景),DefaultTransactionAttribute和RuleBasedTransactionAttribute(这两个场景主要使用SpringAOP进行声明式事务管理,RuleBasedTransactionAttribute允许我们同时制定多个返回rolling规则)。TransactionStatus有一个实现类DefaultTransactionStatus,用于记录交易状态信息。PlatformTransactionManager的实现类可以分为两个分支:面向本地事务和面向全局事务。本地事务常用的PlatformTransactionManager包括DataSourceTransactionManager(用于JDBC和Mybatis)和HibernateTransactionManager。如何使用Spring进行事务管理?事务管理配置ProgrammatictransactionsDeclarativetransactionsProgrammatictransactions使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于程序化的事务管理,spring推荐使用TransactionTemplate。声明式事务建立在AOP之上。它的本质是拦截方法前后,然后在目标方法开始前创建或加入一个事务,在目标方法执行后根据执行状态提交或回滚事务。声明式事务最大的优点是不需要通过编程来管理事务,这样就不需要在业务逻辑代码中混入事务管理代码,只需在配置文件中(或者通过@Transactional注解)声明相关的事务规则即可,您可以将事务规则应用于业务逻辑。显然,声明式事务管理优于程序化事务管理,后者是spring所提倡的非侵入式开发方式。声明式事务管理使业务代码不被污染。一个普通的POJO对象只要加注解就可以获得完整的事务支持。与程序化事务相比,声明式事务唯一的缺点是其最细粒度只能应用于方法级别,而不能像程序化事务一样应用于代码块级别。但即使有这样的需求,也有很多workaround,比如可以将需要事务管理的代码块分离成方法等等。声明式事务管理也有两种常用的方法,一种是基于tx和aop命名空间的xml配置文件,另一种是基于@Transactional注解。显然,基于注释的方法更易于使用和清洁。本文转载自微信公众号《Java编程技术乐园》,可通过以下二维码关注。转载本文请联系Java编程技术天堂公众号。
