事务

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

事务的特性

  • 原子性

事务中包含的逻辑,不可分割。

  • 一致性

事务执行前后。数据完整性

  • 隔离性

事务在执行期间不应该受到其他事务的影响

  • 持久性

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

使用命令行方式演示事务。

  • 开启事务

start transaction;

  • 提交或者回滚事务

commit; 提交事务, 数据将会写到磁盘上的数据库 rollback; 数据回滚,回到最初的状态。

微信截图_20190912141921.png

  • 也可以通过关闭自动提交加commit的方式来执行事务

微信截图_20190912142426.png

代码方式使用事务

package cn.sort;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;

public class Jdbctool {
    private Jdbctool(){}
    //创建出BasicDataSource类对象
    private static BasicDataSource datasource = new BasicDataSource();

    //静态代码块,对象BasicDataSource对象中的配置,自定义
    static{
        //数据库连接信息,必须的
        datasource.setDriverClassName("com.mysql.jdbc.Driver");
        datasource.setUrl("jdbc:mysql://localhost:3306/javastudy");
        datasource.setUsername("root");
        datasource.setPassword("123456");
        //对象连接池中的连接数量配置,可选的
        datasource.setInitialSize(10);//初始化的连接数
        datasource.setMaxActive(8);//最大连接数量
        datasource.setMaxIdle(5);//最大空闲数
        datasource.setMinIdle(1);//最小空闲
    }

    public static DataSource getDataSource(){
        return datasource;
    }
}
  • 测试代码
package cn.sort;

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


public class Test {
    public static void main(String[] args) throws Exception {

        Connection con = Jdbctool.getDataSource().getConnection();
        con.setAutoCommit(false);// 设置关闭自动提交
        String sql = "INSERT INTO sort (sname,sprice,sdesc)VALUES(?,?,?)";
        PreparedStatement ps = con.prepareStatement(sql);
        ps.setString(1, "水果");
        ps.setDouble(2, 100.12);
        ps.setString(3, "核桃");
        ps.executeUpdate();
        con.rollback();// 回滚
//      con.commit();// 提交
        con.close();

    }
}

事务的安全隐患

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

  • 脏读

一个事务读到另外一个事务还未提交的数据

  • 不可重复读

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

  • 幻读

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

  • 丢失更新

特定情况下开启多个事务并更新数据后,先后提交事务会出现数据覆盖,导致丢失数据

隔离级别

  • 按效率划分,从高到低

读未提交 > 读已提交 > 可重复读 > 可串行化

  • 按拦截程度 ,从高到底

可串行化 > 可重复读 > 读已提交 > 读未提交

读未提交

引发问题:脏读

读已提交

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

可重复读

解决:脏读,不可重复读,未解决:幻读

可串行化

解决:脏读,不可重复读,幻读。

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

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

丢失更新

img08.png

  • 悲观锁

可以在查询的时候,加入for update

img09.png

  • 乐观锁

要求程序员自己控制

img10.png