1.含义:其实指的是一组操作,里面包含许多个单一的逻辑。只要有一个逻辑没有执行成功都算失败。所有的数据都回归到最初的状态(俗称回滚)。
2.为什么要有事务?为了确保逻辑的成功。例子:银行转账。
3.开启事务:start transaction
提交或者回滚事务:commit 提交事务,数据将会写到磁盘上的数据库;rollback 数据回滚,回到最初的状态。
4.代码里的事务,主要是针对链接来的。
——通过conn.setAutoCommit(false)来关闭自动提交的设置
——提交事务conn.commit();
——回滚事务conn.rollback();
5.例子(使用java代码演示)
@Test
public void login() {
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//1.得到链接对象
connection = JDBCUtil.getConn();
connection.setAutoCommit(false); //关闭自动提交
String sql = "update account set money= money - ? where id = ?";
//2.创建ps对象
ps = connection.prepareStatement(sql);
//扣钱,扣ID为1的100块钱
ps.setInt(1, 100);
ps.setInt(2, 1);
ps.executeUpdate();
int a = 10/0; //出现错误,使程序不能够进行
//String s = null;
//s.length();
//加钱,给ID为2加100块钱
ps.setInt(1, -100);
ps.setInt(2, 2);
ps.executeUpdate();
}catch(SQLException e){
e.printStackTrace();
}finally {
JDBCUtil.release(connection, ps, rs);
}
}
6.事务的特性
——原子性
指的是食物中包含的逻辑不可分割
——一致性
指的是事务执行前后数据完整性
——隔离性
指的是事务在执行执行期间不应该受到其他事务的影响
——持久性
指的是事务执行成功,那么应该持久保存到磁盘上
7.事务的安全隐患
——不考虑隔离级别设置,那么会出现脏读、不可重复度、幻读等问题。
脏读——一个事务读到了另外一个事务还未提交的数据。解决办法: 将隔离级别设置为Read Committed。但这样能够解决脏读,但是无法解决不可重复读。
不可重复度——一个事务前后两次读取另一个事务的数据不一致。解决方法:将隔离级别设置为repeatable Read。
幻读——一个事务读到了另一个事务已提交的插入的数据,导致多次查询结果不一致。解决方法:将隔离级别设置为Serializable-该级别是最高的事务级别。比前面级别都要强大一点,也就是前面几种问题【脏读、不可重复度、幻读】都能够解决,但是有一些缺点。
串行化后,谁先打开了事务,谁就有了先执行的权利,谁后打开事务,谁就只能等着前面的那个事务提交或者回滚后才能执行。但是这中隔离级别一般比较少用,容易造成型嗯那个上的问题——效率低。
Mysql默认的隔离级别是可重复度,Oracle默认的隔离级别是读已提交。
——写,丢失更新。后面的数据会将前面的数据覆盖掉。解决方法:
1)悲观锁——可以在查询的时候加入for update。
2)乐观锁——要求程序员自己控制。