事务

来源:互联网 发布:注册淘宝卖家要钱吗 编辑:程序博客网 时间:2024/06/04 20:01

1、事务概述


  事务(Transaction)是并发控制的基本单位。它是一个操作序列,这些操作要么都执行,要么都不执行,是一个不可分割的工作单位。事务具有四大特性,简称为ACID:

   原子性(Atomicity):事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。

   一致性(Consistency):事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。

   隔离性(Isolation):隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。

   持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。


2、数据库中的事务


  在默认情况下,数据库中每执行一条SQL语句,都是一个单独的事务。如果需要在一个事务中包含多条SQL语句,需要开启事务和结束事务:

    开启事务:start transaction;

    结束事务:commit或rollback。

  在执行SQL语句之前,先执行strat transaction,这就开启了一个事务(事务的起点),然后可以去执行多条SQL语句,最后要结束事务,使用commit表示提交,即事务中的多条SQL语句所做出的影响会持久化到数据库中。或者rollback,表示回滚,即回滚到事务的起点,将之前代码所做的所有操作撤消,并结束事务。

  数据库转账事务实例:

<pre name="code" class="sql"><span style="font-size:18px;">START TRANSACTION; /*开启事务UPDATE account SET balance=balance-10000 WHERE id=1; /*1号id余额减少10000UPDATE account SET balance=balance+10000 WHERE id=2; /*2号id余额增加一万COMMIT;/*提交事务</span>

3、JDBC中的事务


  在JDBC中,Connection的三个方法与事务相关:

     setAutoCommit(boolean):设置是否为自动提交事务,如果true(默认值就是true)表示自动提交,也就是说默认每条执行的SQL语句都是一个单独的事务,都被放在一个事务中,并且被默认设置为自动提交。如果我们设置为false,那么就相当于开启了事务了,con.setAutoCommit(false)表示开启事务;

     commit():提交结束事务,con.commit();表示提交事务;

     rollback():回滚结束事务,con.rollback();表示回滚事务;

  JDBC处理事务的代码格式:

<span style="font-size:18px;">try {    con.setAutoCommit(false);//开启事务…    ….    …    con.commit();//try的最后提交事务} catch() {    con.rollback();//如果try中代码出错则回滚事务}</span>


3、JDBC保存点

  保存点在JDBC3.0中出现,校验当前数据库服务器是否支持保存点的方法是:

<span style="font-size:18px;">boolean b = con.getMetaData().supportsSavepoints();</span>

  保存点的作用是允许事务回滚到指定的保存点位置。在事务中设置好保存点,回滚时可以选择回滚到指定的保存点,而不是回滚整个事务。注意,回滚到指定保存点并没有结束事务,只有回滚了整个事务才算是结束事务了。回滚到保存点只是表明回滚到保存点处的操作状态,并不回滚代码,代码还要从开始回滚处向下执行。

  Connection类的设置保存点,以及回滚到指定保存点方法:

    设置保存点:Savepoint setSavepoint();

    回滚到指定保存点:void rollback(Savepoint)。

  转账实例:

<span style="font-size:18px;">/* * 张三给李四转1W,李四给张三转100W。 * 操作步骤: *   1、张三给李四转1W(张三减去1W,李四加上1W) *   2、设置保存点 *   3、李四给张三转100W(李四减去100W,张三加上100W) *   4、查看李四余额为负数,那么回滚到保存点。 *   5、提交事务 */@Testpublic void fun() {Connection con = null;PreparedStatement pstmt = null;try {con = JdbcUtils.getConnection();//手动提交con.setAutoCommit(false);String sql = "update account set balance=balance+? where name=?";pstmt = con.prepareStatement(sql);//操作1(张三减去1W)pstmt.setDouble(1, -10000);pstmt.setString(2, "zs");pstmt.executeUpdate();//操作2(李四加上1W)pstmt.setDouble(1, 10000);pstmt.setString(2, "ls");pstmt.executeUpdate();// 设置保存点Savepoint sp = con.setSavepoint();//操作3(李四减去100W)pstmt.setDouble(1, -1000000);pstmt.setString(2, "ls");pstmt.executeUpdate();//操作4(张三加上100W)pstmt.setDouble(1, 1000000);pstmt.setString(2, "zs");pstmt.executeUpdate();//操作5(查看李四余额)sql = "select balance from account where name=?";pstmt = con.prepareStatement(sql);pstmt.setString(1, "ls");ResultSet rs = pstmt.executeQuery();rs.next();double balance = rs.getDouble(1);                  //如果李四余额为负数,那么回滚到指定保存点if(balance < 0) {con.rollback(sp); //回滚到指定保存点System.out.println("余额不足,回滚事务。");}//提交事务con.commit();} catch(Exception e) {//回滚事务if(con != null) {try {con.rollback();} catch(SQLException ex) {}}throw new RuntimeException(e);} finally {//关闭JdbcUtils.close(con, pstmt);}}</span>

  张三减少1万,李四增加1万后设置了sp保存点,如果接下来程序发现李四余额不足100万,那么就会回滚到sp,也就是说:张三没有得到任何回报就失去了1万。


  小结:事务是一个并发控制的基本单位,是一个操作序列,其内的操作要么全部执行,要么都不执行。ACID是事务的基本特性。此外,事务回滚分全部回滚和回滚到保存点,只有全部回滚时才会结束事务,否则代码继续向下执行。



3 0
原创粉丝点击