目录
事务的含义
举一个例子
事务的特征(面试高频)
原子性
一致性
隔离性
持久性
事务结束
查看事务提交方式
查看事务提交的变量值:on 自动提交 off 不是自动提交
实例
事务回滚
验证事务回滚
事务实现:是数据库提供
jdbc事务
Connection的三个方法与事务相关:
格式
实例代码
注意:
事务的含义
在同一个事物下,一组sql 语句,要么成功,要么失败。不允许出现中间状态
举一个例子
张三给李四转200块。正常状态是张三扣钱,李四收到200块。但如果出现异常状况:
张三支付成功,李四没有收到/ 张三没有支付成功,但李四收到钱。这两种情况,在现实生活都不被允许的,因此如果出现异常情况,都会表示失败(在数据库中,会进行事务回滚,回到初始状态),只有都成功,才算结束。这个过程称为事务
事务的特征(面试高频)
原子性
只有当前事务结束了,才能进行下一个事物,不允许被打断。有点类似与多线程中的同步代码块
一致性
一个事务在执行前和执行后,数据库,都必须处以一致性状态
例如:比如张三向李四转钱这个过程,钱的总量是不变的(钱一直在流通,并且始终保持平衡状态)
隔离性
每一个都有各自完整的数据空间,即使多个事物,操作有同一个数据。各个事务之间,不受影响。(后面会有验证)
持久性
事务一旦提交,数据就会被永久的保留下来,即使出现各种异常,只要重新启动,就可以恢复到事务成功结束后的状态
事务结束
含义:事务提交(sql执行成功,执行事务提交 ,才结束)commit
注意:
- mysql 默认 自动提交事务
- 注意事务不允许重复提交
注意:mysql 自动提交事务
查看事务提交方式
事务提交方式有两种; 自动提交,手动提交
查看事务提交的变量值:on 自动提交 off 不是自动提交
show variables like 'autocommit’
通过set命令设置autocommit 全局变量的值,可以打开或关闭事物的自动提交
// 禁止事务自动提交 set autocommit=0; // 开启事务自动提交 set autocommit=1;
注意:你关闭手动提交事务,只针对当前的窗口。如果你想永久的关闭自动提交,需要修改配置文件
打开命令行窗口,输入,关闭自动提交方式,改为手动 的sql 语句
实例
我现在 同时打开两个命令行A窗口 ,B窗口。并同时连接数据库,并在A窗口中 关闭自动提交 ,修改dj666数据库 user表的信息 。之后,会在两个窗口,中查看修改的数据,看是否会被修改
user表
1 在A窗口中 关闭自动提交 ,B窗口 修改dj666数据库 user表 中将第一行的用户名改为dj666
2 观察每张表是否被修改成功
3 发现B窗口中,数据没有被改变;A创建的数据发生改变。
两张表的数据之所以不一样的原因
我在A窗口中,将事务自动提交,关了。因此当修改数据时,不会直接在硬盘上修改。而是先将数据保存到内存中,在内存中修改数据,因此A窗口中查到的数据是还未被写入到硬盘上修改的数据。只有当我们手动提交事物成功后,才在硬盘上,修改完成。因此我们在B窗口中查到的数据,是还未被修改保存在硬盘上的数据
怎么处理呢?
输入
commit ;
命令表示提交事务
A窗口执行该命令之后,再在B窗口中查询,发现B窗口的表的数据和A窗口的相同。表示事务提交成功
验证事务的隔离性
我首先在A窗口(自动提交,已经关了)修改用户 dj111的密码为111,再在B窗口(自动提交)中修改
事务回滚
含义:当程序中有些sql 执行成功了,有些执行失败了,会进行回滚操作,恢复到执行之前的状态)
rollback;
验证事务回滚
在A窗口中,我们未提交事务,相当于事物提交失败,因此当我们输入rollback 命令时,回到之前未操作状态
事务实现:是数据库提供
jdbc事务
注意:jdbc 默认自动提交
Connection的三个方法与事务相关:
setAutoCommit(boolean):设置是否为自动提交事务。
- 如果true(默认值就是true)表示自动提交,也就是每条执行的SQL语句都是一个单独的事务,
- 如果设置false,那么就相当于开启了事务了;con.setAutoCommit(false)表示开启事务
commit():提交结束事务;con.commit();表示提交事务
rollback():回滚结束事务。con.rollback();表示回滚事务
格式
jdbc处理事务的代码格式: try { con.setAutoCommit(false);//开启事务… …. … con.commit();//try的最后提交事务 } catch() { con.rollback();//回滚事务 }
实例代码
public void transfer(boolean b) { Connection con = null; PreparedStatement pstmt = null; try { con = JdbcUtils.getConnection(); //手动提交 con.setAutoCommit(false); String sql = "update account set balance=balance+? where id=?"; pstmt = con.prepareStatement(sql); //操作 pstmt.setDouble(1, -10000); pstmt.setInt(2, 1); pstmt.executeUpdate(); // 在两个操作中抛出异常 if(b) { throw new Exception(); } pstmt.setDouble(1, 10000); pstmt.setInt(2, 2); pstmt.executeUpdate(); //提交事务 con.commit(); } catch(Exception e) { //回滚事务 if(con != null) { try { con.rollback(); } catch(SQLException ex) {} } throw new RuntimeException(e); } finally { //关闭 JdbcUtils.close(con, pstmt); } }
注意:
我们的jdbc默认是自动提交, 所以我们不需要手动提交了, 而且,==在实际开发中,我们的事务是加在业务层,而不是加在DAO层