什么是事务?
事务的概念最开始出现在关系型数据库中,英文解释如下:
A database transaction is a larger unit that frames multiple SQL statements. A transaction ensures that the action of the framed statements is atomic with respect to recovery.
事务是确保"同时成功则成功,任何一个失败则失败"的一种机制。一个事务往往包括三种动作行为:开始事务(Begin Transaction),提交事务(Commit)和回滚(Rollback)。从开始事务到提交事务过程中所发生的一切数据库修改要么同时成功(被Commit,固化在数据库中),要么一个失败,大家同时回复原有状态(Rollback,数据库回复到事务开始时的状态)。
简单的理解:它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
随着IT技术的发展,事务的范畴也变大,又称之为交易,指一个程序或程序段,在一个或多个资源如 数据库 或文件上为完成某些功能的执行过程的集合。
事务基本属性:
事务的ACID特点分别是指原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
数据库事务有以下3种运行模式:
自动提交事务:每条单独的语句都是一个事务。
显式事务:每个事务均以BEGIN TRANSACTION语句显式开始,以COMMIT或ROLLBACK语句显式结束。
隐性事务:在上个事务完成时新事务隐式启动,但每个事务仍以COMMIT或ROLLBACK语句显式完成。
事务的并发控制 :
如果不对事务进行并发控制,并发事务的无序执行将会破坏数据的完整性。事务并发执行可能导致的异常可以分为以下几种情况。
Lost update(丢失更新)
A和B事务并发执行,A事务执行更新后,提交;B事务在A事务更新后,B事务结束前也做了对该行数据的更新操作,然后回滚,则两次更新操作都丢失了。
更新都做白搞了,被一个不争气的事务又还原了!
Dirty Reads(脏读)
A和B事务并发执行,B事务执行更新后,A事务查询B事务没有提交的数据,B事务回滚,则A事务得到的数据不是数据库中的真实数据。也就是脏数据,即和数据库中不一致的数据。
读了数据库中不存在的数据,感觉被人忽悠了。
Non-repeatable Reads(非重复读)
A和B事务并发执行,A事务查询数据,然后B事务更新该数据,A再次查询该数据时,发现该数据变化了。
在同一事务中两次读取中被其他事务强行修改,有种横刀夺爱,物是人非的意思。
Second lost updates(第二类丢失更新,可以称为覆盖更新):
是非重复读的一种特殊情况,即A事务更新数据,然后B事务更新该数据,A事务查询发现自己更新的数据变了。
一个事务修改了数据,事后发现不是按照自己意思修改的,原来是被另外一个事务做了手脚,偷天换日!
Phantom Reads(幻像读)
A和B事务并发执行,A事务查询数据,B事务插入或者删除数据,A事务再次查询发现结果集中有以前没有的数据或者以前有的数据消失了。
这么多问题,可以分类理解:事务A查询或修改数据,与此同时事务B也修改数据,根据事务B的完成情况(事务成功完成,事务回滚)可以区分不同问题。
数据库的sql-92隔离级别:
一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。为了兼顾并发效率和异常控制,在标准SQL规范中,定义了4个事务隔离级别。
Read Uncommitted(未提交读):
即使一个更新语句没有提交,别的事务也可以读到这个改变。如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据。
Read Committed(已提交读):
更新语句提交以后别的事务才能读到这个改变。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。
Repeatable Read(可重复读):
在同一个事务里面先后执行同一个查询语句的时候,确保得到的结果是一样的。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。
Serializable(串行化):
事务执行的时候不允许别的事务并发执行。事务串行化执行,事务只能一个接着一个地执行,而不能并发执行。
隔离级别对并发的控制 :
各隔离级别对各种异常的控制能力如下表所示,其中Y表示会出现该种异常,N表示不会出现该种异常。
丢失更新 脏读 非重复读 覆盖更新 幻像读
未提交读 Y Y Y Y Y
已提交读 N N Y Y Y
可重复读 N N N N Y
串行化 N N N N N
事务涉及的对象:
资源:应用程序存储和获取数据的地方,可以是数据库,文件,也可以是内存。如果是应用程序的事务块代码中涉及到的数据库,文件,内存,那这些资源就称为事务型资源。
资源管理器:在事务模型中,应用不是直接访问资源,而是通过中间介访问资源,这个中间介就叫资源管理器。资源分为可持久化资源(对应了持久化资源管理),易失资源(对应了易失资源管理器)。
事务管理器:实现事务的开始,提交,回滚。
事务的分类:
本地事务
本地(Local Transaction)事务指只有一个数据源参与的事务,比如只有数据库或者只有JMS;
分布式事务
分布式事务(Distributed Transaction)指有多个数据源同时参与的事务,比如一项操作需要同时访问数据库和通过JMS发送消息,或者一项操作需要同时访问两个不同数据库。对于分布式事务,Java提供了JTA规范,它的原理与本地事务存在不同。
Java事务的类型有三种:
JDBC事务、JTA(Java Transaction API)事务、容器事务。