1、Spring是如何管理事务的?
Spring中的事务:是指完成一系列sql操作,需要保证原子性,隔离性,一致性、持久性;
首要目标是保证原子性,要么都执行成功,要么都执行失败。
Spring提供两种事务管理方式:
1)编程式事务,即在代码中手动提交、回滚事务,灵活性比较强,但是维护起来比较困难,更复杂。
几个比较重要的接口:
PlatformTransactionMananger:平台事务管理基础接口;
TransactionDefinition:为当前操作定义一个事务;
TransactionStatus:事务的状态;
步骤:申明数据源、声明事务管理类、在代码中提交回滚事务
2)声明式事务:通过配置文件,或者注解的方式,基于IOC、AOP模式配置事务,将业务代码和事务
操作分离。维护方便,开发简单,减少冗余代码。
步骤:
配置数据源:org.springframework.jdbc.datasource.DataSourceTransactionManager;
配置事务管理通知:对save、insert、remove、delete;
事务AOP配置;通过execution配置事务层;
配置实用CGLIB代理;
启动对事物注解的支持
<tx:annotation-driven transaction-manager="transactionManager" />
在实际项目开发中数据库操作一般都是并发执行的,即有多个事务并发执行,并发执行就可能遇到问题,目前常见的问题如下:
丢失更新:两个事务同时更新一行数据,最后一个事务的更新会覆盖掉第一个事务的更新,从而导致第一个事务更新的数据丢失,这是由于没有加锁造成的;
脏读:一个事务看到了另一个事务未提交的更新数据;
不可重复读:在同一事务中,多次读取同一数据却返回不同的结果;也就是有其他事务更改了这些数据;
幻读:一个事务在执行过程中读取到了另一个事务已提交的插入数据;即在第一个事务开始时读取到一批数据,
但此后另一个事务又插入了新数据并提交,此时第一个事务又读取这批数据但发现多了一条,即好像发生幻觉一样。
为了解决这些并发问题,需要通过数据库隔离级别来解决,在标准SQL规范中定义了四种隔离级别:
未提交读(Read Uncommitted):最低隔离级别,一个事务能读取到别的事务未提交的更新数据,很不安全,可能出现丢失更新、脏读、不可重复读、幻读;
提交读(ReadCommitted):一个事务能读取到别的事务提交的更新数据,不能看到未提交的更新数据,不可能可能出现丢失更新、脏读,
但可能出现不可重复读、幻读;
可重复读(RepeatableRead):保证同一事务中先后执行的多次查询将返回同一结果,不受其他事务影响,
可能可能出现丢失更新、脏读、不可重复读,但可能 出现幻读;
序列化(Serializable):最高隔离级别,不允许事务并发执行,而必须串行化执行,最安全,不可能出现更新、脏读、不可重复读、幻读。
隔离级别越高,数据库事务并发执行性能越差,能处理的操作越少。因此在实际项目开发中为了考虑并发性能一般使用提交读隔离级别,它能避免丢失更新和脏读,尽管不可重复读和幻读不能避免,但可以在可能出现的场合使用悲观锁或乐观锁来解决这些问题。