目录
1.事务
狭义上来说,事务就是不可再分的业务动作,这个动作一般为一条或者多条语句。
事务失败的原因:
a.主动失败(硬件的原因、软件的原因)
b.被动失败(DBMS本身的原因、我们的原因 如异常)
事务的四大特性:(ACID)
1.1原子性
完成动作看成一个整体,不可能有局部完成的情况
rollback之后,数据没有发生改变 。
1.2.一致性
业务方来定义的,针对数据整体做不可变的承诺。
1.3.隔离性
当有多个DBMS的用户,同时针对数据做增删查改时,是否互相直接保持隔离的特性。
最理想的情况下,一个用户操作数据时,意识不到其他用户同时也在操作数据。
1.4持久性
一旦DBMS通知我们修改成功了,则数据必然修改成功(数据被持久化了)
我们如何使用事务
2.在sql层面
重新启动服务器之后数据回滚 ,没有发生变化
我们也可以主动回滚
rollback之后,数据没有发生改变 。
如果我们没有使用事务,则会破环一致性,造成有记录而book表没有发生变化
3.通过JDBC的方式来使用事务
四个场景分别是:
(1)有事务,commit
(2)没有事务,主动失败
(3)有事务,主动失败
(4)有事务,被动失败
场景一:有事务的情况下
package com.wangqi.primary; import com.wangqi.lib.DBUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Demo4 { public static void main(String[] args) throws SQLException { String sql1 = "insert into records (rid, bid) values (1, 2)"; String sql2 = "update books set count = count - 1 where bid = 2"; // 要使用事务,在同一个事务中,操作 sql1 和 sql2,意味着必须在一条 Connection 完成 try (Connection c = DBUtil.connection()) { // connection 中有一个 自动提交(autocommit)的属性,默认情况下,是 true(开启) // 开启状态下,意味着,每一条 sql 都会被独立的视为一个事务 // 我们要让 sql1 和 sql2 看作整体,只需要关闭 connection 的自动提交 c.setAutoCommit(false); // 不会提交之后,只能被我们进行手动提交 // 我们就可以手动的控制事务的结束位置 try (PreparedStatement ps = c.prepareStatement(sql1)) { ps.executeUpdate(); } try (PreparedStatement ps = c.prepareStatement(sql2)) { ps.executeUpdate(); } // 由于我们关闭了自动提交了,所以,所有的修改还没有真正地落盘 c.commit(); // 只有加上这句话,才表示事务被提交了(数据真正落盘了) } } }
运行成功之后,发现数据更新了
一致性
这是主动失败
场景二:没有事务的情况下:事务一致性被破坏
场景三:有事务的情况下(数据回滚,没有发生变化,保持了一致性)主动失败
场景四:这是被动失败(这里写了一个除0异常)
此时发现数据也没有做任何修改
场景五:回滚操作
回滚操作的结果也有维护一致性同样的效果
隔离性(宏观上同时,微观上不同时)
微观角度下,同一时刻(不可再分)对一个数据的操作,只能一个用户操作
如果要实现真正的隔离性,要牺牲并发性。引出了隔离级别。
两个场景
(1)
(2)
4.总结
2.1事务出现的必然性(维护数据的一致性+一个业务由一组SQL组成)
2.2认识事务(SQL、JDBC)
2.3事务的四个特性(ACID)
2.4隔离级别:读未提交、读已提交、可重复读、可串行化