一个数据库事务是一个被视为单一的工作单元的操作序列。在同一个事务中,要么完整的执行,要么完全不执行,以确保数据完整性和一致性。
1、事务的四大特性:原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durability)
原子性(Atomicity):事务应该当作一个单独单元的操作,一个不可分割的最小工作单元,这意味着整个序列操作要么是全部提交成功,要么是全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。
一致性(Consistency):这表示数据库处理前后结果应与其所抽象的客观世界中的真实状况保持一致。这种一致性是一种需要管理员取定义的规则。管理员如何指定规则,数据库就严格按照这种规则去处理数据。
隔离性(Isolation):一个事务所做的修改在最终提交之前,对其他事务时不可见的。
持久性(Durability):一旦事务提交,则其所做的修改就会永久保存到数据库中。即使系统崩溃,修改的数据也不会丢失。
2、事务控制语法:
begin / start transaction 显示的开启一个事务;
commit / commit work 提交事务,并使已对数据库进行的所有修改成为永久性的;
rollback / rollback work 回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
savepoint identifier 在事务中创建一个保存点,一个事务中可以由多个 savepoint;
release savepoint identifier 删除一个事务的保存点;
rollback to identifier 把事务回滚到标记点;
set transaction 设置事务的隔离级别,InnoDB 存储引擎提供事务的隔离级别有:read_uncommitted,read_committed,repeatable_read,serializable
3、Spring 事务管理
Spring 支持两种类型的事务管理:编程式事务管理,声明式事务管理。
五大属性:隔离级别、传播行为、是否只读、事务超时、回滚规则。
事务的隔离性主要是为了解决事务的脏读、幻读或不可重复读。
脏读:指一个事务在处理数据的过程中,读取到另一个未提交事务的数据;强调的是第二个事务读到的数据不够新。
不可重复读:指对于数据库中的某个数据,一个事务范围内的多次查询却返回了不同的结果,这是由于在查询过程中,数据被另外一个事务修改并提交了,读取到的是前一个事务提交的数据(同一条数据结果不同);重点是修改,同一事务,两次读取到的数据不一样。
幻读:是事务非独立执行时发生的一种现象;重点在于新增或者删除,同样的条件,两次读出来的记录数不一样。
①、隔离级别:
读未提交(read uncommitted):隔离级别最低,并发性能高,会出现脏读,幻读,不可重复读。
读已提交(read committed):锁定正在读取的行,会出现不可重复读,幻读。
可重复读(repeatable read):锁定所夺取的所有行,会出现幻读(mysql的默认隔离级别)。
串行化(serializable):锁表,保证所有的情况不会发生,是一致性最高,并发性最差的隔离级别。
四种隔离级别,最低的是 read uncommitted,最高的是 serializable ,级别越高,执行效率越低。
MySQL数据库支持上面四种隔离级别,默认的隔离级别为 repeatable read(可重复读)。
Oracle数据库只支持 serializable,read committed 两种级别,默认的隔离级别为 read committed。
查询数据库隔离级别:select @@tx_isolation;
设置数据库隔离级别:set @@tx_isolation = 'read-committed';
②、传播行为:是用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法时事务是如果传播的。
REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。Spring 默认的传播行为。
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY:使用当前事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED:如果当前存在事务,则在嵌套事务内执行,如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作
提示:
Ⅰ、Spring 中事务的默认实现方式使用的是 AOP,使用JDK代理方式(接口代理),不能通过 cglib方式代理(类集成代理方式),这种方式会导致接口上的注解信息会丢失,导致事务不能生效。
Ⅱ、事务注解最好是使用在业务实现类上,业务方法必须是 public 方法,不能是 protected 或 private 方法,否则注解不生效。
Ⅲ、如果同一个 service 类中的方法互相调用时需要使用注入的对象来调用,而不是使用 this.方法名直接调用,this.方法名 调用方式是对象内部方法调用,不会通过 Spring 代理,事务不会起作用。
③、是否只读:(待学习)
/** * A boolean flag that can be set to {@code true} if the transaction is * effectively read-only, allowing for corresponding optimizations at runtime. * <p>Defaults to {@code false}. * <p>This just serves as a hint for the actual transaction subsystem; * it will <i>not necessarily</i> cause failure of write access attempts. * A transaction manager which cannot interpret the read-only hint will * <i>not</i> throw an exception when asked for a read-only transaction * but rather silently ignore the hint. * @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly() * @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly() */ boolean readOnly() default false;
④、事务超时:(待学习)
/** * The timeout for this transaction (in seconds). * <p>Defaults to the default timeout of the underlying transaction system. * <p>Exclusively designed for use with {@link Propagation#REQUIRED} or * {@link Propagation#REQUIRES_NEW} since it only applies to newly started * transactions. * @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout() */ int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
⑤、回滚规则:
noRollbackFor:可以指定哪种异常不回滚。事务虽然不会回滚,但是事务是生效的。
rollbackFor:可以指定哪种异常回滚。事务回滚。
RuntimeException:异常回滚,不指定时,发生了运行时异常,事务回滚。