数据库事务 (一)

数据库事务的概念

● 事务是指一组相互依赖的操作行为,如银行交易,股票交易或网上购物。事务的成功取决于这些相互依赖的操作行为是否都能执行成功,只要有一个操作行为失败,就意味着整个事务失败。

例如,Tom到银行办理转账事务,把100元转到Jack的账号上,这个事务包括以下操作行为:
- (1)从Tom的账号上减去100元。
- (2)往Jack的账号上增加100元。
以上两个操作必须作为一个不可分割的工作单元。 假如仅仅第一步操作执行成功,使得Tom的账户上扣除了100元,
但是第二部操作执行失败,Jacj账户上没有增加100元,那么整个事务失败。

数据库事务是对现实生活中事务的模拟,它由一组在业务逻辑上相互依赖的SQL语句组成。



事物(Transaction)



声明事务的边界:
- 事务的开始边界。
- 事务的正常结束边界(commit):提交事务,永久保存被事务更新后的数据库状态。
- 事务的异常结束边界(rollback):撤销事务,使数据库退回到执行事务钱的初始状态。


数据库事务的4个特性(ACID):
1) 原子性(Atom)   
  -事务中的最基本的操作单位,它所做的数据更改操作要么全部执行,要么全部不执行。

2) 一致性(Consistence)
- 一个事务执行之前和执行之后,数据库必须处于一致状态。比如满足所有完整性约束。

3) 隔离性(Isolation)
- 事务是相互隔离的,既一个事务内部的操作和正在操作的数据必须封锁起来。
比如两个用户都在操作一个数据,要保证二者不互相影响。

4) 持久性(Duration)
- 事务提交后,对数据库数据的改变时永久性的。



实例:
在JDK的sql包中,接口Conntection的setAutoCommit()方法就是针对数据库连接的事务提交。

void setAutoCommit(boolean autoCommit)
                   throws SQLException

Sets this connection's auto-commit mode to the given state. If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either the method commit or the method rollback. By default, new connections are in auto-commit mode.
The commit occurs when the statement completes. The time when the statement completes depends on the type of SQL Statement:

For DML statements, such as Insert, Update or Delete, and DDL statements, the statement is complete as soon as it has finished executing.
For Select statements, the statement is complete when the associated result set is closed.
For CallableStatement objects or for statements that return multiple results, the statement is complete when all of the associated result sets have been closed, and all update counts and output parameters have been retrieved.
NOTE: If this method is called during a transaction and the auto-commit mode is changed, the transaction is committed. If setAutoCommit is called and the auto-commit mode is not changed, the call is a no-op.

Parameters:
autoCommit - true to enable auto-commit mode; false to disable it



代码实例如下:

	public static void main(String[] args)throws  ClassNotFoundException, SQLException
	{	
		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection con=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORCL","123","123");
		
		
		
	
		
		try
		{//	con.setAutoCommit(false);
		
			Statement stmt=con.createStatement();
			stmt.execute("insert into test values (2)");
			stmt.execute("insert into test values('1sd')");
		//	con.commit();
		}
		catch (SQLException e)
		{
			try{
				System.out.println("rollback begin");
				//con.rollback();
				System.out.println("rollback finished");
			}catch(Exception e1){
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
 
		
		
		
	}

第一遍执行先不设置任何事务管理,让程序直接运行。
这样当执行了insert into test values(2),  这里的插入操作就会被成功执行。
而到了insert into test values('lsd'),就会抛出异常。
此时查看数据库,发现test表中已经有了第一个insert语句的数值。
假如这两条是相关的,比如上面所说的银行转账, 那就必须都被执行才可以。。

当setAutoCommit被设置了false,并使用commit和rollback时,这个问题就得到了解决。
上面的程序执行结果就变成了:

rollback begin
rollback finished
java.sql.SQLException: ORA-01722: 无效数字

这时查看数据库,就会发现数据库里并没有第一个insert语句所插入的数值。



===============================================================
多个事务并发运行时的并发问题

-第一类丢失更新: 撤销一个事务时,把其它事务已提交的更新数据覆盖。
-脏读: 一个事务读到另一事务未提交的更新数据。
-虚读: 一个事务读到另一事务已提交的新插入的数据。
-不可重复读: 一个事务读到另一事务已提交的更新数据。
-第二类丢失更新: 这是不可重复读中的特例,一个事务覆盖另一事务已提交的更新数据。

取款事务和支票转账事务
取款事务包括以下步骤:
1. 某银行客户在银行前台请求取款100元,出纳员先查询账户信息,得知存款余额为1000元。
2. 出纳员判断出存款额超过了取款额,就支付给客户100元,并将账户上的存款余额改为900.
支票转账事务包含以下步骤:
1. 某出纳员处理一转账支票,该支票向一账户汇入100元。 出纳员先查询账号信息,得知存款余额为900元。
2. 出纳员将存款余额改为1000元。


脏读例子:








猜你喜欢

转载自alleni123.iteye.com/blog/1982977