zoukankan      html  css  js  c++  java
  • 事务

    事务的定义:一组要么同时成功要么同时失败

    1.数据事物讲解

    1.1事务开始于

    • 连接到数据库上,并执行一条DML语句insert、update或delete

    • 前一个事务结束后,又输入了另一条DML语句

    1.2事务结束

    • 执行commit或rollback语句。

    • 执行一条DDL语句,例如create table语句,在这种情况下,会自动执行commit语句。

    • 执行一条DDL语句,例如grant语句,在这种情况下,会自动执行commit。

    • 断开与数据库的连接

    • 执行了一条DML语句,该语句却失败了,在这种情况中,会为这个无效的DML语句执行rollback语句

    2.事务的四大特点

    • actomicity(原子性)

        表示一个事务内的所有操作是一个整体,要么全部成功,要么全部失败

    • consistency(一致性)

        表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前状态

    • isolation(隔离性)

        事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会   查看中间状态的数据。

    事务之间相互隔离

    • durability(持久性)

        持久性事务完成之后,它对于系统的影响是永久性的。

    3.事务的隔离的级别

    SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

    Read Uncommitted(读取未提交内容)

    在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

    Read Committed(读取提交内容)

    ​ 这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

    不可重复读:同一个事务下,两条查询语句结果不一致(读取到了另一个事务修改后的数据)

    Repeatable Read可重读

    ​ 这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。

    幻读:同一个事务下,两条查询语句结果条数不一致(读取到了另一个事务新增后的数据)

    Serializable 可串行化​ 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

    ​ 这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。

    例如:

    ​   脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

    ​   不可重复读(Non-repeatableread):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

    ​   幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的

    ================mysql中===============

    默认隔离级别是:Repeatable Read可重读

    查看当前的事务隔离级别:select  @@tx_isolation;

    更改当前的事务的隔离级别:set transaction isolation level 四个级别之一。

    设置隔离级别必须在事务之前

    read uncommitted:不能避免脏读,不可重复读,幻读(虚读)

    read  committed :避免脏读,不可避免不可重复,幻读

    repeatable read:避免脏读,不可重复读,不能避免幻读

    Serializable:都能避免

    4.Java中事务应用

    如果jdbc连接处于自动提交模式,默认情况下,则每个sql语句在完成后都会提交到数据库

    事务使你能够控制是否何时更改应用于数据库。它将单个SQL语句或一组SQL语句视为一个简单的单元,

    如有任何语句失败,则整个事务将失败。

    要启动手动事务支持,而不是JDBC驱动程序默认使用的自动提交模式,请使用connection对象的

    setAutoCommit()方法。如果将boolean false 传递给setAutoCommit(),则关闭提交,

    我们可以传递一个布尔值true来重新打开它。

    4.1事务的提交和回滚

    完成更改后,我们要提交更改,然后在连接对象上调用commit()方法,如:conn.commit();

    否则,要使用连接名为coon的数据库回滚更新,请使用以下代码:conn.rollback();

    4.2使用Savepoints

    新的jdbc 3.0 Savepoint接口为你提供了额外的事务控制。

    设置保存点时,可以在事务中定义逻辑回滚点。如果通过保存点发生错误,则可以使用回滚的方式来撤销

    所有更改或仅保存在保存点之后所做的更改。

    connection对象有两种新的方法来帮助你管理保存点

    setSavepoint(String savepointName):定义新的保存点。它还返回一个是savepoint对象。

    releaseSavepoint(Savepoint savepointName):删除保存点。请注意,它需要一个savepoint

    对象作为参数。此对象通常是由setSavepoint ()方法生成保存点。

    1、要取消掉JDBC的自动提交:void setAutoCommit(boolean autoCommit)

    2、执行各个SQL语句,加入到批处理之中

    3、如果所有语句执行成功,则提交事务 commit();如果出现了错误,则回滚:rollback()


      ***************************   * 转账业务来理解事务*  *******************************

    数据库

    MySQL中开两个线程来查看银行账户是否进行转账()注意:每次在执行的时候都要刷新一下

     

            (线程一)

           (线程二)

    Java中事务表达方式的理解

    public class TestTransaction {
        @Test
        public void testTransaction() {
            Connection connection  = DBUtils.getConnection();
            PreparedStatement ps = null;
            //控制事务
            try {
                connection.setAutoCommit(false);//不自动提交事务  等价于数据库中执行:begin;start transaction;
                
                
                String sql = "update account1 set money = money -100 where name=?";
                
                ps  = connection.prepareStatement(sql);
                ps.setString(1, "k");
                
                //执行操作
                ps.executeUpdate();
                //ps.addBatch();
                
                //模拟断电
                int i = 10/0;
                
                String sql1 = "update account1 set money = money +100 where name=?";
                ps  = connection.prepareStatement(sql1);
                ps.setString(1, "h");
                ps.executeUpdate();
                
                //提交事务
                connection.commit();
                
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }catch (Exception e) {
                //回滚 到事务之前的状态
                try {
                    connection.rollback();
                } catch (SQLException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }finally {
                //提交事务
                try {
                    connection.commit();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }


     

  • 相关阅读:
    用于展现图表的50种JavaScript库
    EditPlus常用正则表达式
    人工智能生成仿真人脸
    树莓派搭建SVN服务器
    JS三座大山再学习 ---- 异步和单线程
    JS三座大山再学习 ---- 作用域和闭包
    基于C#的MongoDB数据库开发应用(2)--MongoDB数据库的C#开发
    基于C#的MongoDB数据库开发应用(1)--MongoDB数据库的基础知识和使用
    大数据高效复制的处理案例分析总结
    基于DevExpress的Winform程序安装包的制作
  • 原文地址:https://www.cnblogs.com/wanghuaying/p/9505690.html
Copyright © 2011-2022 走看看