事务的级别控制

在SQL术语中,事务是逻辑工作单元(logical unit of work,LUW)构成的一个或多个语句。这在某种含义上意味着,一切都是事务。不过,通常而言,术语事务用来表示或全或无的系列操作;也就是说,要么一切十分成功,要么什么也没有发生。典型的事务是从银行帐户提款,并存放到另一个。只要提款完成,金额就消失了。另一个范例是复式薄记记帐法中的借方和贷方:借方和贷方都必须完成。

在单用户模式,事务非常容易理解-它们只是和保存或忘记应用程序的状态有关。在多用户模式中,事务变得复杂多了。多用户事务的经典说明是银行帐户,其中一个应用程序试图在借记帐户,同时另一个应用程序试图贷记同一个帐户。在前面已经介绍过多线程编程(并发编程)。类似的,事务的根本问题是保持两个事务相互隔离,否则一个应用程序就可能影响另一个,从而导致错误的程序状态。当处理多个访问相同数据的用户时,通常可能出现三种问题:

n 脏读:当应用程序使用了被另一个应用程序修改过的数据,而这个数据处于未提交状态时,就会发生脏读。第二个应用程序随后会请求回滚被其修改的数据。第一个事务使用的数据就会被损坏,或者"变脏"。

n 不可重复的读:当一个事务获得了数据,而该数据随后被一个单独的事务所更改时,若第一个事务再次读取更改后的数据,就会发生不可重复的读。这样,第一个事务进行了一个不可重复的读。

n 虚读:当事务通过某种查询获取了数据,另一个事务修改了部分该数据,原来的事务第二次获取该数据时,就会发生虚读。第一个事务现在会有不同的结果集,它可能包含虚读。

为了解决与"多个线程请求相同数据"相关的问题,事务之间用锁相互隔开。多数主流的数据库支持不同类型的锁;因此,JDBC API支持不同类型的事务,它们由Connection对象指派或确定。在JDBC API中可以获得下列事务级别:

n TRANSACTION_NONE 说明不支持事务

n TRANSACTION_READ_UNCOMMITTED说明在提交前一个事务可以看到另一个事务的变化。这样脏读,不可重复的读和虚读都是允许的。

n TRANSACTION_READ_COMMITTED说明读取未提交的数据是不允许的。这个级别仍然允许不可重复的读和虚读产生。

n TRANSACTION_REPEATABLE_READ说明事务保证能够再次读取相同的数据而不会失败,但虚读仍然会出现。

n TRANSACTION_SERIALIZABLE是最高的事务级别,它防止脏读,不可重复读和虚读。

为什么不是所有事务都运行在TRANSACTION_SERIALIZABLE模式以保证最高程度的数据完整性呢?问题在于,和处理多线程编程有关的问题相似,事务保护的级别越高,性能损失就越大。假定您的数据库和JDBC驱动程序支持这个特性,则给定一个Connection对象,您可以明确地设置想要的事务级别:con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);

您还可以确定当前事务的级别:

int transactionIsolation = con.getTransactionIsolation();
if (transactionIsolation == Connection.TRANSACTION_NONE)
System.out.println("当前事务级别为:TRANSACTION_NONE。");

代码:

import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.NamingException;

public class TranTest {
	public static void main(String[] args) {
		String jndiname = "jdbcPool/mydatasource";
		Connection con = null;
		try {
			con = DBCon.getConnectionFromPooledDataSource(jndiname);
			int transactionIsolation = con.getTransactionIsolation();
			if (transactionIsolation == Connection.TRANSACTION_NONE) {
				System.out.println("当前事务级别为:TRANSACTION_NONE。");
			} else if (transactionIsolation == Connection.TRANSACTION_READ_COMMITTED) {
				System.out.println("当前事务级别为:TRANSACTION_READ_COMMITTED。");
			} else if (transactionIsolation == Connection.TRANSACTION_READ_UNCOMMITTED) {
				System.out.println("当前事务级别为:TRANSACTION_READ_UNCOMMITTED。");
			} else if (transactionIsolation == Connection.TRANSACTION_REPEATABLE_READ) {
				System.out.println("当前事务级别为:TRANSACTION_REPEATABLE_READ。");
			} else if (transactionIsolation == Connection.TRANSACTION_SERIALIZABLE) {
				System.out.println("当前事务级别为:TRANSACTION_SERIALIZABLE。");
			}

			con.setAutoCommit(false);
			con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
			transactionIsolation = con.getTransactionIsolation();
			if (transactionIsolation == Connection.TRANSACTION_NONE) {
				System.out.println("当前事务级别为:TRANSACTION_NONE。");
			} else if (transactionIsolation == Connection.TRANSACTION_READ_COMMITTED) {
				System.out.println("当前事务级别为:TRANSACTION_READ_COMMITTED。");
			} else if (transactionIsolation == Connection.TRANSACTION_READ_UNCOMMITTED) {
				System.out.println("当前事务级别为:TRANSACTION_READ_UNCOMMITTED。");
			} else if (transactionIsolation == Connection.TRANSACTION_REPEATABLE_READ) {
				System.out.println("当前事务级别为:TRANSACTION_REPEATABLE_READ。");
			} else if (transactionIsolation == Connection.TRANSACTION_SERIALIZABLE) {
				System.out.println("当前事务级别为:TRANSACTION_SERIALIZABLE。");
			}

		} catch (NamingException ex) {
			System.err.println("Name Not Bound : " + ex.getMessage());
		} catch (SQLException ex) {
			System.err.println("SQLException : " + ex.getMessage());
		} finally {
			try {
				if (con != null)
					con.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		System.out.println("程序执行结束!");
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值