jdbc-事务概述

本文详细介绍了数据库事务的概念,以银行转账为例阐述了事务的必要性,并讲解了事务的四大特性——ACID。接着,通过MySQL和JDBC展示了事务的使用,包括开启、提交和回滚操作。此外,还探讨了事务的隔离性问题,解释了脏读、不可重复读和幻读等并发问题,并列举了四种隔离级别及其优缺点。最后,讨论了如何在MySQL和JDBC中设置事务隔离级别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.什么是事务(银行转账)

所谓的事务其实就是对一件事情的处理,只不过这件事情比较特殊!特殊的地方是实施这件事情的所有步骤要么全部成功,要么全部失败!

例如:银行转账,银行转账这件事情就是一个事务。因为他满足事务的特殊性!
比方说,小明要给小红转账1000,那么他就要有以下两个步骤(每个步骤对应于一条sql语句):

  • 给小明的账户减去1000元。(第一条sql)
  • 给小红的账户加上1000元。(第二条sql)

如果在第一条SQL语句执行成功后,在执行第二条SQL语句之前,程序被中断了,那么小红的账户没有加上1000元,而小明却减去了1000元。这肯定是不符合常规的!

这个就是所谓的事务,在整个转账操作步骤中,要么全部成功,要么全部失败!不可能存在成功一半的情况!也就是说给小明的账户减去1000元如果成功了,那么给小红的账户加上1000元的操作也必须是成功的;否则给小明减去1000元,以及给小红加上1000元都是失败的!

2.事务的四大特性(ACID)

  1. 原子性(Atomicity): 事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
  2. 一致性(Consistency): 事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
  3. 隔离性(Isolation): 隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。
  4. 持久性(Durability): 一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制(日志)恢复数据。

3. MySql中事务的演示

账户表

CREATE TABLE account(
	id INT PRIMARY KEY,
	NAME VARCHAR(30),
	balance NUMERIC(10.2)
);

MySql的事务默认是开启的
在默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。

一个事务中可以包含多个sql语句

如何使用MySql的事务

  • 开启事务:start transaction;
  • 结束事务:commit(事务成功)或rollback(事务失败)。

一个完整事务的范围:
两种情况:

  1. start transaction;步骤 commit(事务成功) 事务结束(成功,把数据持久化到数据库中)
  2. start transaction;步骤 rollback(事务失败) 事务结束(失败,所有的步骤都还原)

事务正常开启和提交
在执行SQL语句之前,先执行strat transaction,这就开启了一个事务(事务的起点),然后可以去执行多条SQL语句,最后各个SQL语句执行成功,然后就可以用commit提交事务。

总结:只有当事务正常开启和提交两个操作都完成时,数据的更改才会被持久化到数据库。事务正常开启但遇到异常执行回滚操作

在执行SQL语句之前,先执行strat transaction,这就开启了一个事务(事务的起点),然后可以去执行多条SQL语句,在执行各条SQL语句的过程中遇到异常,然后就可以用rollback

4. jdbc中的事务演示

在jdbc中处理事务,都是通过Connection完成的!

Connection的三个方法与事务相关:

  • setAutoCommit(boolean):设置是否为自动提交事务,如果true(默认值就是true)表示自动提交,也就是每条执行的SQL语句都是一个单独的事务,如果设置false,那么就相当于开启了事务了;con.setAutoCommit(false)表示开启事务!
  • commit():提交结束事务;con.commit();表示提交事务
  • rollback():回滚结束事务。con.rollback();表示回滚事务

jdbc处理事务的代码格式:

try {
  con.setAutoCommit(false);//开启事务….
	  throw Exception();
  con.commit();//try的最后提交事务
} catch(Exception e) {
  con.rollback();//回滚事务
}

代码演示:

package com.ruandy.jdbc05;

import com.ruandy.utils.JdbcUtils03;
import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TranDemo {
    /*
    * 小明给小红转1000
    * jdbc中的事务是通过哪个对象展开?
    *   Connection
    *   开启事务  connection.setAutoCommit(false);
     *   提交事务 connection.commit();
    *   回滚事务 connection.rollback();
    * */
    @Test
    public void method(){
        Connection connection = null;
        PreparedStatement pstmt = null;
        String sql = null;
        try{
            connection = JdbcUtils03.getConnection();
            connection.setAutoCommit(false); //开启事务,不让事务自动提交
            sql = "UPDATE account SET balance=balance+? WHERE NAME=?";

            pstmt = connection.prepareStatement(sql);
            pstmt.setDouble(1,-1000);
            pstmt.setString(2,"xm");
            pstmt.executeUpdate();


            //执行之前把pstmt里面的参数,先把他擦除
            pstmt.clearParameters();//建议大家好
            pstmt.setDouble(1,1000);
            pstmt.setString(2,"xh");
            pstmt.executeUpdate();

            connection.commit();//提交事务 手动提交
        }catch (Exception e){ //捕获到了算术异常
            try {
                connection.rollback();//回滚  结束事务
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
            //要么打印异常,要么把异常抛出去
//            e.printStackTrace();
            throw new RuntimeException(e);
        }finally{
            //释放资源
            try{
                if(pstmt!=null) pstmt.close();
                if(connection!=null) connection.close();
            }catch (Exception e){
                throw new RuntimeException(e);
            }
        }
    }
}

5.事务的隔离性

事务的隔离性:多个事务的并发需要对事务进行隔离,避免多个事务对数据操作的干扰。

5.1 事务的隔离级别(理解,面试会问)

并发事务问题

  • 脏读(dirty read):读到另一个事务的未提交更新数据,即读取到了脏数据;
  • 不可重复读(unrepeatable read):对同一记录的两次读取不一致,因为另一事务对该记录做了修改;如何解决?对记录加锁(更新)-
  • 幻读(虚读)(phantom read):对同一张表的两次查询不一致,因为另一事务插入了一条记录;

5.2 四大隔离级别

4个等级的事务隔离级别,在相同数据环境下,使用相同的输入,执行相同的工作,根据不同的隔离级别,可以导致不同的结果。不同事务隔离级别能够解决的数据并发问题的能力是不同的。(锁的问题很复杂)

  • SERIALIZABLE(串行化)事务执行的时候排队
    • 不会出现任何并发问题,因为它是对同一数据的访问是串行的,非并发访问的;
    • 性能最差;
  • REPEATABLE READ(可重复读)(MySQL)
    • 防止脏读和不可重复读,不能处理幻读问题;
    • 性能比SERIALIZABLE好
  • READ COMMITTED(读已提交数据)(Oracle)
    • 防止脏读,没有处理不可重复读,也没有处理幻读;
    • 性能比REPEATABLE READ好
  • READ UNCOMMITTED(读未提交数据)
    • 可能出现任何事务并发问题
    • 性能最好

MySQL的默认隔离级别为REPEATABLE READ,这是一个很不错的选择吧!

3.3 MySQL隔离级别的查看和设置

MySQL的默认隔离级别为Repeatable read,可以通过下面语句查看:
select @@tx_isolation;

也可以通过下面语句来设置当前连接的隔离级别:
set transaction isolation level [4选1]

3.4 JDBC设置隔离级别

con. setTransactionIsolation(int level)
参数可选值如下:

  • Connection.TRANSACTION_READ_UNCOMMITTED;
  • Connection.TRANSACTION_READ_COMMITTED;
  • Connection.TRANSACTION_REPEATABLE_READ;
  • Connection.TRANSACTION_SERIALIZABLE。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值