zoukankan      html  css  js  c++  java
  • JavaWeb学习之事务

    一、事务(Transaction):其实是一组操作(包含许多个单一的逻辑)。只要有一个逻辑没有执行成功,那么都算失败。 所有的数据都回归到最初的状态(回滚)

    例如:银行转账

    A用户向B用户转账,这样的话转账中就有两个逻辑操作,1、A用户账户金额要减少  2、B用户账户金额要增加,此时就需要把这两个逻辑操作放入事务中

    代码格式:

    @Test
        public void testTransaction(){
            
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            try {
                conn = JDBCUtil.getConn();
                
                //连接,事务默认就是自动提交的。 关闭自动提交。
                conn.setAutoCommit(false);
                
                String sql = "update account set money = money - ? where id = ?";
                ps = conn.prepareStatement(sql);
                
                //扣钱, 扣ID为1 的100块钱
                ps.setInt(1, 100);
                ps.setInt(2, 1);
                ps.executeUpdate();//加钱, 给ID为2 加100块钱
                ps.setInt(1, -100);
                ps.setInt(2, 2);
                ps.executeUpdate();
                
                //成功: 提交事务。
                conn.commit();
                
            } catch (SQLException e) {
                try {
                    //事变: 回滚事务
                    conn.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
                
            }finally {
                JDBCUtil.release(conn, ps, rs);
            }
        }

    二、事务的特性

      ①、原子性:事务中包含的逻辑,不可分割。

      ②、一致性:事务执行前后。数据完整性

      ③、隔离性:事务在执行期间不应该受到其他事务的影响

      ④、持久性:事务执行成功,那么数据应该持久保存到磁盘上。

    三、隔离级别

      ①、读未提交(read uncommitted)

          引发问题: 脏读

      ②、读已提交(read committed)

          解决: 脏读 , 引发: 不可重复读,SQL Server没有这个问题

      ③、可重复读(repeatable-read)

          解决: 脏读 、 不可重复读 , 引发: 幻读 

      ④、可串行化(SERIALIZABLE)

          解决: 脏读、 不可重复读 、 幻读

      mySql 默认的隔离级别是 可重复读

      Oracle 默认的隔离级别是  读已提交

      Sql Server 默认的隔离级别是  读已提交

    四、事务的安全隐患

      不考虑隔离级别设置,那么会出现以下问题

        ①、读

          脏读:一个事务读到了另一个事务未提交的数据        

            事务A:

    USE Bank
    GO
    --使用默认隔离级别
    BEGIN TRANSACTION
    UPDATE ACCOUNT SET Money=Money-300 WHERE Id=1
    WAITFOR DELAY '00:00:10'
    ROLLBACK TRANSACTION

            事务B:

    USE Bank
    GO
    --设置隔离级别:未提交读
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    BEGIN TRANSACTION
    --发生在事务回滚前
    SELECT * FROM ACCOUNT WHERE Id=1
    WAITFOR DELAY '00:00:10'
    --发生在事务回滚后
    SELECT * FROM ACCOUNT WHERE Id=1
    COMMIT TRANSACTION

            先执行事务A再执行事务B结果:

               

          不可重复读:一个事务读到了另一个事务已提交的数据,造成前后两次查询结果不一致 

            事务A:

    USE Bank
    GO
    --使用默认隔离级别
    BEGIN TRANSACTION
    UPDATE ACCOUNT SET Money=Money-300 WHERE Id=1
    WAITFOR DELAY '00:00:10'
    COMMIT TRANSACTION --注意

            事务B:

    USE Bank
    GO
    --设置隔离级别:读已提交
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    BEGIN TRANSACTION
    --发生在事务回滚前
    SELECT * FROM ACCOUNT WHERE Id=1
    WAITFOR DELAY '00:00:10'
    --发生在事务回滚后
    SELECT * FROM ACCOUNT WHERE Id=1
    COMMIT TRANSACTION

            先执行事务B再执行事务A结果:

               

          幻读:一个事务读到了另一个事务insert的数据 ,造成前后查询结果不一致

            事务A      

    USE Bank
    GO
    --使用默认隔离级别
    BEGIN TRANSACTION
    INSERT INTO ACCOUNT VALUES('Kimi',1000)
    COMMIT TRANSACTION

            事务B

    USE Bank
    GO
    --设置隔离级别:读已提交
    SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
    BEGIN TRANSACTION
    --发生在事务提交前
    SELECT * FROM ACCOUNT
    WAITFOR DELAY '00:00:10'
    --发生在事务提交后
    SELECT * FROM ACCOUNT
    COMMIT TRANSACTION

             先执行事务B再执行事务A结果不一致,为幻读:

              

        ②、写

          丢失更新

            

             

           数据丢失更新可以通过锁机制,来加以控制

    五、总结

      脏读 更新丢失 不可重复读 幻读
    Read Uncommitted 可能 可能 可能 可能
    Read Committed 不可能 可能 可能 可能
    Repeatable Read 不可能 不可能 不可能 可能
    Serializable 不可能 不可能 不可能 不可能
  • 相关阅读:
    高德全链路压测平台TestPG的架构与实践
    性能测试之稳定性测试(可靠性测试)
    服务端高并发分布式架构演进之路
    高性能高并发系统的稳定性保障
    聊聊服务稳定性保障这些事
    qt 待研究
    k73 uboot 和emmc启动移植
    Qt更新组件出现(“要继续此操作,至少需要一个有效且已启用的储存库”)
    C++ Lambda 编译器实现原理
    qt 网络编程参考资料
  • 原文地址:https://www.cnblogs.com/WarBlog/p/12566548.html
Copyright © 2011-2022 走看看