(A)原子性
指的是事务中的整个活动序列必须被全部完成或全部放弃。事务不能部分地完成。与隔离性相结合后(见表1),原子性指的是任意一个事务将查看任何其他同时或以原子形式发生的事务所采取的所有活动。
(C)一致性
指的是事务既可以建立一个新的、有效的数据状态(在这种状态中可以进行所有的改动),它可以在操作失败的情况下,把所有的数据返回到事务发生之前已有的状态。
(I)隔离性
指在一个事务中发生的所有活动对其他事务来说都是不可见的,直到该事务被提交。
(D)持续性
指的是事务成功做出并提交的所有改动是不变的,并且必须克服系统故障。比如说,如果发生了故障或者系统重新启动,数据在最后提交事务之后所存在的状态下是可用的。
JDBC事务级别
JDBC事务级别分为5级:
(1)TRANSACTION_NONE
正式地讲,TRANSACTION_NONE不是一个有效的事务级别。根据java.sql.Connection API文件,这个级别表示事务是不被支持的,因此理论上说你不能使用TRANSACTION_NONE作为一个自变量赋给Connection.setTransactionIsolation()方法。
事实上,虽然一些数据库实施了这个事务级别,但是Oracle9i却没有实施。
(2)TRANSACTION_READ_UNCOMMITTED
这是最快的完全有效的事务级别。它允许你读取其他还没有被提交到数据库的并发事务做出的修改。这个API文件指出,脏读取(dirty reads)、不可重复读取(non-repeatable reads)和错误读取(phantom reads)都可以在这个事务级别发生(参阅" 一些非ACID事务问题 "部分)。这个级别意在支持ACID的"原子性(Atomic)"部分,在这个级别中,你的修改如果被提交,将被认为是同时发生的;如果被撤销,就被当作什么也没发生。
Oracle9i不支持这个级别。
(3)TRANSACTION_READ_COMMITTED
这是继TRANSACTION_READ_UNCOMMITTED之后最快的完全有效的级别。在此级别中,你可以读取已经被提交到数据库中的其他并发事务所做出的修改。API文件指出,脏读取在这个级别中是被禁止的,但是不可重复读取和错误读取都可以发生。
这个级别是Oracle9i默认的级别。
(4)TRANSACTION_REPEATABLE_READ
这个级别比TRANSACTION_SERIALIZABLE快,但是比其他的事务级别要慢。读取操作可以重复进行,这意味着两次读取同样的域应该总是得到同样的值,除非事务本身改变了这个值。API文件指出,脏读取和不可重复读取在这个事务级别中是被禁止的,但是错误读取可以发生。
从技术上讲,数据库通过在被读取或写入的行上加锁来实施这个级别,并且保持锁定状态直到事务结束。这就防止了这些行被修改或删除,但是不能防止额外的行被添加--因此,就可能产生错误读取。?????
Oracle9i不支持这个级别。
(5)TRANSACTION_SERIALIZABLE
这是最慢的事务级别,但是它完全与ACID兼容。"单词可串行化(serializable)"指的就是ACID兼容,其中你的事务被认为在整体上已经发生,就如同其他所有已提交的事务在这个事务之前或之后全部发生。换句话说,事务被串行执行。脏读取、不可重复读取和错误读取在TRANSACTION_SERIALIZABLE级别是全部被禁止的。
从技术上讲,数据库通过锁定在事务中使用的表来实施这个级别。???????
Oracle9i支持这个级别(正如每个与符合ACID的数据库那样)。
Oracl事务级别
Oracle支持的2种事务隔离级别:Read committed,Serializable;
Isolation Level |
Description |
Read committed |
This is the default transaction isolation level. Each query executed by a transaction sees only data that was committed before the query (not the transaction) began. An Oracle query never reads dirty (uncommitted) data. Because Oracle does not prevent other transactions from modifying the data read by a query, that data can be changed by other transactions between two executions of the query. Thus, a transaction that runs a given query twice can experience both nonrepeatable read and phantoms. 默认的隔离级别设置。事务中的查询只能看到在此查询之前(而非事务开始之前)提交的数据。 由于Oracle不会因为查询数据而阻止另外一个事务修改数据,因此数据可以在一个事务中的 2 次查询中,查到不同的结果。因此可能出现 nonrepeatable read and phantoms 的情况。 |
Serializable |
Serializable transactions see only those changes that were committed at the time the transaction began, plus those changes made by the transaction itself through INSERT , UPDATE , and DELETE statements. Serializable transactions do not experience nonrepeatable reads or phantoms. Serializable transactions 只能查到此事务开始之前提交的数据,以及本次事务内部的INSERT,UPDATE,DELETE语句修改后的数据。因此能够做到没有nonrepeatable reads or phantoms的情况。 |
以上 2 点都会保证不能脏读脏写,就是说不能得到另外一个事务修改没有提交的事务的修改后的数据。区别在于前者做不到nonrepeatable reads or phantoms,后者可以做到。
前提条件:
有四个事务:事务A、事务B、事务C、事务D;
事务A:1个UPDATE操作;
事务B:3个操作,依次为SELECT-1、UPDATE、SELECT-2;
事务C:1个UPDATE操作;
事务D:1个UPDATE操作;
从时间前后来讲,事件顺序为:事务A的开始、事务A的UPDATE、事务B的开始、事务C的开始、事务D的开始、事务D的UPDATE、事务A的提交、事务B的SELECT-1、事务C的UPDATE、事务C的提交、事务B的UPDATE、事务B的SELECT-2、事务B的提交、事务D的提交;
结论:
如果事务B的事务隔离级别为Read committed
(1)事务B的SELECT-1能读到事务A的UPDATE后的数据吗?
可以。因为在SELECT-1之前事务A已经提交了。
(2)事务B的SELECT-1能读到事务B的UPDATE后的数据吗?
不能。虽然在同一个事务内,但是事务B的UPDATE是在SELECT-1之后。
(3)事务B的SELECT-1能读到事务C的UPDATE后的数据吗?
不能。因为这个时候这个时候事务C的UPDATE还没有进行。
(4)事务B的SELECT-1能读到事务D的UPDATE后的数据吗?
不能。因为事务D的UPDATE这个时候还没有提交。Read commited不会脏读。(如果读到了,即为脏读。)
(5)事务B的SELECT-2能读到事务A的UPDATE后的数据吗?
可以。因为在SELECT-2之前事务A已经提交了。
(6)事务B的SELECT-2能读到事务B的UPDATE后的数据吗?
可以。因为在同一个事务内部,而且UPDATE在前,SELECT-2在后。
(7)事务B的SELECT-2能读到事务C的UPDATE后的数据吗?
可以。因为Read commited会读到已经提交的事务内的修改,而事务C这个时候已经提交了。
(8)事务B的SELECT-2能读到事务D的UPDATE后的数据吗?
不能。因为事务D的UPDATE这个时候还没有提交。Read commited不会脏读。(如果读到了,即为脏读。)
如果事务B的事务隔离级别为Serializable
(1)事务B的SELECT-1能读到事务A的UPDATE后的数据吗?
不能。因为在事务B开始的时候事务A还没有提交。Serializable只能查到此事务开始之前提交的数据。
(2)事务B的SELECT-1能读到事务B的UPDATE后的数据吗?
不能。虽然在同一个事务内,但是事务B的UPDATE是在SELECT-1之后。
(3)事务B的SELECT-1能读到事务C的UPDATE后的数据吗?
不能。因为在事务B开始的时候事务C还没有开始。而且,事务C的UPDATE发生在事务B的SELECT-1之后。
(4)事务B的SELECT-1能读到事务D的UPDATE后的数据吗?
不能。因为事务D的UPDATE这个时候还没有提交。Serializable不会脏读。(如果读到了,即为脏读。)
(5)事务B的SELECT-2能读到事务A的UPDATE后的数据吗?
不能。因为在事务B开始的时候事务A还没有提交。Serializable只能查到此事务开始之前提交的数据。
(6)事务B的SELECT-2能读到事务B的UPDATE后的数据吗?
可以。Serializable可以查到本事物内部修改的数据。
(7)事务B的SELECT-2能读到事务C的UPDATE后的数据吗?
不能。因为在事务B开始的时候事务C还没有开始,更别说提交了。Serializable只能查到此事务开始之前提交的数据。
(8)事务B的SELECT-2能读到事务D的UPDATE后的数据吗?
不能。因为事务D的UPDATE这个时候还没有提交。Serializable不会脏读。(如果读到了,即为脏读。)