一、事务的基本要素(ACID)
事务是指多个操作单元组成的合集,多个单元操作是整体不可分割的,要么都操作不成功,要么都成功。其必须遵循四个原则(ACID)。
- 原子性(Atomicity):指一个事务要么全部执行,要么不执行,也就是说一个事务不可能只执行了一半就停止了.比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱.不可能划了卡,而钱却没出来.这两步必须同时完成.要么就不完成。
- 一致性(Consistency):在事务执行前数据库的数据处于正确的状态,而事务执行完成后数据库的数据还是应该处于正确的状态,即数据完整性约束没有被破坏;如银行转帐,A转帐给B,必须保证A的钱一定转给B,一定不会出现A的钱转了但B没收到,否则数据库的数据就处于不一致(不正确)的状态。
- 隔离性(Isolation):并发事务执行之间互不影响,在一个事务内部的操作对其他事务是不产生影响,这需要事务隔离级别来指定隔离性;
- 持久性(Durability):事务一旦执行成功,它对数据库的数据的改变必须是永久的,不会因比如遇到系统故障或断电造成数据不一致或丢失。
二、事务的隔离级别
数据库事务的隔离级别有4种,由低到高分别为Read uncommitted、Read committed、Repeatable read、Serializable
而且在事务的并发操作中可能会出现脏读,不可重复读,幻读。事务丢失。
脏读(读取了未提交的新事务,然后被回滚了)
事务A读取了事务B中尚未提交的数据,如果事务B回滚,则A读取使用了错误的数据。
不可重复读(读取了提交的新事务,指更新操作)
不可重复度是指在对于数据库中的某个数据,一个事务多次查询却返回了不同的结果,这是由于在查询期间,被另一个事务修改并提交了。
幻读(也是读取了提交的新事务,多增删操作)
在事务A多次读取过程中,事务B对数据进行了增删操作,导致事务A多次读取的数据不一致。
事务丢失:
1.回滚丢失:比如A和B同时在执行一个数据,然后B事务已经提交了,然后A事务回滚了,这样B事务的操作就因为A事务回滚而丢失了;
2.提交覆盖丢失:A和B一起执行一个数据,两个同时取到一个数据,然后AB依次提交事务,这样B就覆盖了A的事务。
Read uncommitted:读未提交,一个事务可以读取到另一个未提交事务的数据,会产生脏读;
Read committed:读提交,一个事务要等另一个事务提交后才能读数据,会产生不可重复读;(sqlserver oracle默认级别)
Repeatable read:重复读,就是在开始读取数据(事务开启)时,不再允许修改操作,可能产生幻读。(mysql默认级别)
Serializable:是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读,但效率低下,比较耗数据库性能,一般不使用
三、事务的传播
简单的理解就是多个事务方法相互调用时,事务如何在这些方法间传播。
举个例子,方法A是一个事务的方法,方法A执行过程中调用了方法B,那么方法B有无事务以及方法B对事务的要求不同都会对方法A的事务具体执行造成影响,同时方法A的事务对方法B的事务执行也有影响,这种影响具体是什么就由两个方法所定义的事务传播类型所决定。
spring的是默认有7种级别,默认的为REQUIRED
NEVER | 以非事务方式进行,有则抛出异常 |
NOT_SUPPORTED | 以非事务方式进行,有则挂起 |
SUPPORTS | 有事务就用,没有就不用 |
REQUIRES_NEW | 有没有都新建事务,原来有的则挂起 |
NESTED | 如果没有就新建;有就嵌套 |
REQUIRED | 如果没有,就新建,如果有就加入当前事务 |
MANDATORY | 如果没有就抛异常,有就使用 |
总结:
1.死活不要事务的:NEVER(从不)、NOT_SUPPORTED
2.可有可无的:SUPPORTS
3.必须有事务的:REQUIRES_NEW(各有各的事务)、NESTED(嵌套在一起)、REQUIRED、MANDATORY