MySql中的事务、JDBC事务、事务隔离级别

一、MySql事务

之前在Oracle中已经学习过事务了,这个东西就是这个东西,但是在MySql中用法还是有一点不同,正好再次回顾一下。

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

开始事务:start transaction

结束事务:commit或rollback

在执行SQL语句之前,先执行start transaction,这就开启了一个新的事务,然后就可以去执行多条SQL语句,最后要结束事务,commit表示提交,即事务中多条SQL语句造成的影响会持久化到数据库中。rollback表示回滚,一切恢复到事务的起点,事务开始之后所到的操作全当没有发生过。

在orcale中拿银行转账举过例子,现在在MySql中实现以下:

首先建了一个银行账户表

现在张三余额800,李四余额1200,下面李四向张三转账200.

在两句update语句之后数据库貌似是变了,这时候注意其他用户看到的还是没有变化的数据库,因为没有提交,这时候在本用户查看好像是转成功了,但是一个rollback,一切归于开始。

二、JDBC事务

JDBC操作事务,全部都是由Connection完成。Connection的三个方法与事务有关

setAutoCommit(boolean):设置是否自动提交事务,如果不自动提交,那这句就表示事务的开始。

commit():表示提交事务

rollback():表示回滚事务

JDBC操作事务的代码格式

try{

 con.setAutoCommit(fasle);

....

....

con.commit();

}catch(){

con.rollback();

}

如果对事务的操作抛出异常,那么肯定就执行不来,所以回滚,要是没有出错,那就提交。

这里一定要注意的JDBC操作事务一定要使用一个Connection对象!!!!再拿银行转账来演示,首先建一个账户类。

复制代码

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




/**
 * @author WangXinwei
 *使用自建工具类JdbcUntils返回Connection对象
 */
public class Bank {
    public void account(String name,int blance) throws SQLException{
         Connection conn=JdbcUntils.getConn();
         String sql="update bank set blance=blance+? where name=?";
         PreparedStatement ps=conn.prepareStatement(sql);
         ps.setInt(1, blance);
         ps.setString(2, name);
         ps.executeUpdate();
     }
}

复制代码

使用JDBC操作事务

复制代码

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

/**
 * @author WangXinwei
 * 传入转账方,收账方,转账金额
 * 
 */
public class Demo3 {

    public void demo(String from, String to, int money) {
        Connection conn = JdbcUntils.getConn();
        try {
            conn.setAutoCommit(false);
            Bank bank = new Bank();
            bank.account(from, -money);
            bank.account(to, +money);
            conn.commit();
        } catch (Exception e) {
            // TODO: handle exception
            try {
                conn.rollback();
                conn.close();
            } catch (SQLException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        } finally {
            try {
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

复制代码

因为我使用的是单例模式返回的Connection对象,所以是一个对象,满足之前说的。

三、事务的隔离级别

事务的问题一般都是出现的并发操作的时候。

并发事务问题有五种,其中两种是更新问题,三种是读问题。重点看并发读问题,在这之前,先略微了解一下更新问题

1. 第一类丢失更新(lost update): 在完全未隔离事务的情况下,两个事务更新同一条数据资源,某一事务异常终止,回滚造成第一个完成的更新也同时丢失。

2. 第二类丢失更新(second lost updates):是不可重复读的特殊情况,如果两个事务都读取同一行,然后两个都进行写操作,并提交,第一个事务所做的改变就会丢失。

并发读问题:

1.脏读:读到未提交更新数据,就是读到另一个事务未提交数据,就是脏数据。

比如:

2.不可重复读:对同一记录两次读取不一致,因为另一事务对该记录做了修改

比如:

3.幻读:对同一张表的两次查询不一致,因为另一事务插入了一条数据

比如:

 不可重复读和幻读有什么区别呢?

不可重复读是读到了另一个事务的更新

幻读是读到了另个一表的插入(MySql中无法测试幻读)

 四大隔离级别:

四个等级的隔离级别,在除了隔离级别不同什么都相同的情况下处理结果是不同的,因为四种隔离级别对并发数据的处理能力是不同的。

1.SERIALIZABLE(串行化)

因为是串行化,所以不会出现任何问题,效率最差

2.REPEATABLE READ(可重复读)MySql默认

防止脏读和不可重复读,不能防止幻读

3.READ COMMITTED(读已提交数据)

防止脏读

4.READ UNCOMMITTED(读未提交数据)

可能出现任何问题,效率最好

查看MySql中隔离级别,使用select @@tx_isolation查看

也可以通过 set isolationlevel [4选1] 来设置隔离级别

JDBC设置隔离级别:

依旧通过Connection对象,使用方法setTransactionisolation[ int level]

参数可选为

转载:https://www.cnblogs.com/wxw7blog/p/7881719.html

猜你喜欢

转载自blog.csdn.net/sky198989/article/details/82884160