事务(Transaction)
What
数据库事务(百度百科):
数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作
要么全部执行,要么全部不执行,是一个不可分割的工作单位
。事务由事务开始与事务结束之间执行的全部数据库操作组成。
Java事务(Oracle官网):
Transactions in Java EE Applications. In a Java EE application, a transaction is a series of actions that must all complete successfully, or else all the changes in each action are backed out. Transactions end in either a commit or a rollback.
译:
在Java EE应用程序中,事务是一系列必须全部成功完成的操作,否则将撤消每个操作中的所有更改。事务以提交或回滚结束。
Before
为什么上面提到了数据库事务还有java事务呢?通常我们刚开始接触的时候,默认事务就是数据库事务,但是在javaweb开发中,很多时候我们接触到的是java事务,虽然有些许区别,但是核心都是一样的,也就是:(ACID),不同的只是我们会用java代码去控制事务。
What
要了解事务,首先要了解事务的四大特性:ACID:
- A(Atomicity):原子性:
对数据的一系列更改都像执行单个操作一样执行,要么全部执行,要么全部不执行
; - C(Consistency):一致性:
事务开始和结束时,数据处于一致状态。
; - I(Isolation):隔离性:
事务的中间状态对于其他事务是不可见的。 结果,同时运行的事务似乎已被序列化。也就是说,事务与事务之间是互不干扰的
; - D(Durability):持久性:
事务一旦被提交,它对数据的修改既是永久性的,不可回滚不可修改
。
事务的ACID特性是由关系数据库系统(DBMS)来实现的,DBMS采用
日志
来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所作的更新,如果某个事务在执行过程中发生错误,就可以根据日志撤销事务对数据库已做的更新,使得数据库同滚到执行事务前的初始状态。
对于事务的隔离性,DBMS是采用锁机制
来实现的。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。
如果说开发的系统是比较简单的,基本没有什么业务量/并发量,甚至是一个demo,那么这个时候很难体现出事务的特性,因为对于系统跟数据库来说,每一个事务的隔离级别都相当于是序列化(Serializable),关于隔离级别下面再提出,这里要提出的问题是:
高并发下,事务可能会带来的一些问题
:
- 第一类丢失更新:
撤销一个事务时,把其他事务已提交的更新数据覆盖
; - 第二类丢失更新:
两个事务同时操作一个数据,先提交的被后提交的覆盖
; - 脏读:
事务A读取到事务B
未提交的数据
; - 不可重复读:
在一个事务中,两次读取同一数据结果不同
; - 幻读:
一个事务里面的操作中发现了未被操作的数据
。
接下来,如何解决这些问题呢?这里我们就要提到事务的隔离级别:(由低到高排序)
- Read_uncommited:最低级别,任何情况都无法保证;
- Read_commited:一个事务要等到另一个事务提交后才能读取数据,可避免脏读的发生;
- Repeatable_read:开始读取数据(事务开启)时,不再允许修改操作;可避免脏读与不可重复读;
- Serializable:只允许一个事务在执行,其它事务必须等待这个事务执行完后才能执行。可避免幻读。
用mysql做一个比较好的展示:展示
以上最近提到的4点中的2,3,4,可以避免脏读/不可重复读/幻读;
第一类丢失更新:也就是回滚覆盖,目前主流数据库支持的所有的隔离级别基本杜绝了第一类数据更新丢失的问题;
第二类丢失更新比较特殊,这是另外一个话题了(如何解决第二类丢失更新,总结有提到)。
总结:
1.第一类丢失更新,由数据库去杜绝;
2.第二类丢失更新 与 脏读/不可重复读/幻读 的区别是,前者是两个以上事务同时开始的时候,都结束的情况下可能会发生情况;后者是两个以上事务同时开始的时候,至少还有一个没结束可能会发生的情况;
3.脏读/不可重复读/幻读,可以通过设置数据库的隔离级别去避免;
4.Serializable可以解决,第二类丢失更新,但是代价太大,如果有需要的话,可以通过增加版本号机制,或代码层面加锁等方式去控制其串行化执行。
After
上面介绍了数据库事务,接下来稍微介绍一下java事务,主要有以下几种:
- JDBC(Java DataBase Connection)事务(单库)
- JTA(Java Transaction API)事务(多库)
- Spring容器事务
这里有一篇博客写的不错:Java中的事务及使用。
Other
与事务有关的一个重要领域:分布式事务
。,请自行百度
在查找资料的过程中,找到一些写得不错的博客
大家可以参考参考。Java Spring 与数据库中的事务(transaction)
End
结束语:优秀是一种习惯。