1、当处理多个访问相同数据的用户时,通常可能出现三种问题:
脏读
当应用程序使用了被另一个应用程序修改过的数据,而这个数据处于未提交状态时,就会发生脏读。第二个应用程序随后会请求回滚被其修改的数据。第一个事务使用的数据就会被损坏,或者“变脏”。
不可重复的读
当一个事务获得了数据,而该数据随后被一个单独的事务所更改时,若第一个事务再次读取更改后的数据,就会发生不可重复的读。这样,第一个事务进行了一个不可重复的读。
虚读
当事务通过某种查询获取了数据,另一个事务修改了部分该数据,原来的事务第二次获取该数据时,就会发生虚读。第一个事务现在会有不同的结果集,它可能包含虚读。
2、Java.sql.Connection接口定义的隔离级别
TRANSACTION_NONE 说明不支持事务
TRANSACTION_READ_UNCOMMITTED 说明在提交前一个事务可以看到另一个事务的变化。这样脏读、不可重复的读和虚读都是允许的。
TRANSACTION_READ_COMMITTED 说明读取未提交的数据是不允许的。这个级别仍然允许不可重复的读和虚读产生。
TRANSACTION_REPEATABLE_READ 说明事务保证能够再次读取相同的数据而不会失败,但虚读仍然会出现。
TRANSACTION_SERIALIZABLE 是最高的事务级别,它防止脏读、不可重复的读和虚读。
3、事务的隔离级别
在J2EE中,通过java.sql.Connection接口设置事务隔离级别,这一接口为连接的隔离级别提供了getter()和setter()
Int getTransactionIsolation() throws SQLException
void setTransactionIsolation() throws SQLException
Connection对象负责事务,一旦收到事务请求,事务将自动提交,因为Connection对象已定义为自动提交方式,可通过setAutoCommit(false)禁用自动提交模式
另外java.sql.DatabaseMetaData接口为数据存储提供支持的隔离级别查找方法:getTransactionIsolation(),supportsTransactionIsolationLevel()
对多个库操作的分布式事务必须在所有库中执行同一个隔离级别,否则会出现意想不到的结果
4、事务提交和回滚
为了完成提交事务和回滚事务,JDBC API包括了两个方法作为 Connection 接口的一部分。若将 Connection 对象名称指定为 con,通过调用 con.commit(); 可以保存程序状态;
通过调用 con.rollback(); 可以返回到以前保存的状态。如果数据库实际运行操作时有错误发生,这两个方法都会抛出 SQLExceptions,所以您需要在 try ... catch 块中包装它们。
5、批处理和事务
缺省情况下,JDBC 驱动程序运行在被称为自动提交的模式下,可禁用自动提交模式
con.setAutoCommit(false);
批处理操作中通过在一次单独的操作(或批处理)中执行多个数据库更新操作
{con.setAutoCommit(false) ;
Statement stmt = connection.createStatement() ; stmt.addBatch("INSERT INTO people VALUES('Joe Jackson', 0.325, 25, 105) ; stmt.addBatch("INSERT INTO people
VALUES('Jim Jackson', 0.349, 18, 99) ; stmt.addBatch("INSERT INTO people VALUES('Jack Jackson', 0.295, 15, 84) ;
int[] updateCounts = stmt.executeBatch() ; con.commit() ;