简单理解事务的ACID属性、事务的隔离级别,并用JAVA连接Mysql简单实现事务操作

6 篇文章 2 订阅


个人网站文章地址

一、事务的ACID属性

1.原子性(Atomicity)

事务的操作要么同时执行成功,要么同时执行失败。比方说:
sql = “update user set money = money - 1000 where name = ‘Tom’”;
sql = “update user set money = money + 1000 where name = ‘weder’”;
以上为用户Tom给weder转1000块的操作,要么两条sql同时成功,要么同时失败,是不可分割的(原子)。

2.一致性(Consistency)

一个事务操作前后的数据是一致的。比方说:
用户weder与用户Tom相互转钱后,他们两个人的总金额(共:2000)与没相互转钱之前(共:2000)是相同的(一致的),只是占有不同而已。

3.隔离性(Isolation)

前提是在并发环境中,事务之间是不会相互干扰的(隔离),比方说:
两个事务同时对用户weder的金额进行操作,它们之间是不会产生干扰的。
显然,隔离性会出现问题:
脏读:一个事务(A)读到了另一个事务(B)未提交前的数据(一旦B事务执行了回滚操作,A读到的数据(脏的数据)就无效了)
不可重复读:事务中,前后两次查询的数据不一致(第一次查到金额为1500,再查一次就变成了1000(有事务进行了提交))
幻读:事务中,前后两次查询的数据行不一致(第一次查出现了用户Tom与用户weder的数据,第二次查多出了个用户Jack的数据)

4.持久化(Durability)

事务一旦提交,就会保存(持久化到)在数据库中,就算数据库出现问题宕机,重启后,数据一定是回到事务已提交的状态。

二、事务的隔离级别

1.读未提交

事务可以读到其它事务未提交的内容,一般不采用

2.读已提交

只能读到其它事务已提交的内容,防止了脏读

3.可重复读

是MySQL的默认隔离级别,让事务每次读到的数据都一致,防止了脏读、不可重复读

4.串行化

是最高的隔离级别,每一个事务都要串行(一个接一个)执行,防止了脏读、不可重复读、幻读。但是这样也会导致效率极低。

三、使用JAVA实现MySQL中的事务

数据库建立:其中将money设置为无符号(为了不出现负数的值,同时也为了用来测试事务)

CREATE DATABASE test;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) ,
  `money` int(255) UNSIGNED ,
  PRIMARY KEY (`id`) 
)
INSERT INTO `user` VALUES (1, 'weder', 1000),(2, 'Tom', 1000);

效果
在这里插入图片描述

Java代码目录
在这里插入图片描述
Connect类:用作连接数据库,并封装好查询数据库、关闭连接的方法

public class Connect {
    //定义连接数据库参数
    static final String url = "jdbc:mysql://localhost:3306/test?useSSL=false";
    static final String user = "root";
    static final String passWord = "123456";

    //连接类
    public static Connection connection() throws SQLException, ClassNotFoundException {
        //注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //返回连接类
        return DriverManager.getConnection(url, user, passWord);
    }

    //查询数据库信息类
    static void  sele(PreparedStatement stat,Connection con) throws SQLException {

        //执行查询表信息的sql
        String sql = "select * from user ";
        stat = con.prepareStatement(sql);

        //执行sql语句后返回结果集
        ResultSet rs = stat.executeQuery();

        // 展开结果集数据
        while(rs.next()){
            // 通过字段检索
            String name = rs.getString("name");//获取user_name值
            String money = rs.getString("money");//获取sex值

            // 输出数据
            System.out.print("名字: " + name);
            System.out.println("  余额: " + money);

        }
        rs.close();
    }

    //关闭连接释放资源
    static void closeConnect(PreparedStatement stat,Connection con) throws SQLException {
        stat.close();
        con.close();
    }
}

UseTest测试类:用于测试事务,实现Tom用户给weder用户转1000

public class UseTest {
    public static void main(String[] args) throws Exception {
        //加载驱动并获取连接
        Connection con = Connect.connection();

        //初始化PreparedStatement
        PreparedStatement stat = null;

        //初始化sql语句
        String sql;

        //执行查询语句
        System.out.println("执行事务前:");
        Connect.sele(stat,con);

        //执行事务
        try {
            //先停止自动提交(try方法块的内容可以同时执行),使用rollback()回滚操作必须关闭
            con.setAutoCommit(false);
            
            //weder用户获得了1000块
            sql = "update user set money = money + 1000 where name = 'weder'";
            stat = con.prepareStatement(sql);
            stat.executeUpdate();

            //Tom用户失去了1000块
            sql = "update user set money = money - 1000 where name = 'Tom'";
            stat = con.prepareStatement(sql);
            stat.executeUpdate();
         
            //开启自动提交
            con.setAutoCommit(true);
        }catch (SQLException e){
            System.out.println("错误信息:" + e);
            //出现问题则使数据回滚,回到执行事务前的数据状态
            con.rollback();
        }

        //执行查询语句
        System.out.println("执行事务后:");
        Connect.sele(stat,con);

        //释放资源
        Connect.closeConnect(stat,con);
    }
}

第一次运行:双方都有1000,所以事务执行成功
在这里插入图片描述
第二次运行:Tom用户余额为0,不能执行money = money-1000的操作(money被设置为无符号,即不能为负号),故会执行失败,即使前面weder用户已经有获得1000块的操作,但是事务未提交,会回滚到未执行事务前的状态(原子性:同时成功,同时失败)
在这里插入图片描述
以上为个人对于事务的理解,如果有什么纰漏,希望可以帮忙指正~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值