数据库事务
数据库事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。
一组逻辑操作单元:一个或多个DML操作。
事务处理的原则:保证所有的事务作为一个工作单元来执行,即使出现故障也不能改变执行的方式。当在一个事务中执行多个操作时,要么所有事务都被提交(commit),那么这些修改就永久的保存下来;要么数据库管理系统放弃所有修改,整个事务回滚到最初状态。
数据一旦提交就不可以回滚。
DDL操作一旦执行,就会自动提交。
DML默认执行,就会自动提交;我们可以通过 set autocommit = false 的方式取消DML操作的自动提交。
默认关闭连接也会自动提交。
//这是一个通用的增删改方法,考虑到事务,内部不创建连接由外部传入
public static int update(Connection con ,String sql,Object...args){
PreparedStatement ps = null;
try {
ps = con.prepareStatement(sql);
for(int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
return ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
closeResource(null,ps);
}
return 0;
}
public static void updateWithTx(){
Connection con = null;
try {
con = getConnection();
//取消系统的自动提交
con.setAutoCommit(false);
String sql1 = "UPDATE users SET uname = ? WHERE uid = ?";
update(con,sql1,"吴彦祖",1);
String sql2 = "UPDATE users SET uname = ? WHERE uid = ?";
update(con,sql2,"神仙姐姐",2);
System.out.println("修改成功");
//数据提交
con.commit();
} catch (Exception e) {
e.printStackTrace();
try {
con.rollback(); //如果在事务处理间产生异常,回滚到提交之前
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
closeResource(con,null);
}
}
因此在代码中,一个事务的DML操作要使用同一个connection对象,在所有操作执行完之前不能关闭连接。在获得连接对象后,要取消自动提交,并在DML执行完,使用con.commit();提交。要在捕获异常后,执行 con.rollback(); 回滚操作。执行close前,建议修改。connection为自动提交(尤其是使用数据库连接池时)。
事务的ACID属性
- 原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
- 一致性:事务必须使数据库从一个一致性状态变到另外一个一致性状态。
- 隔离性:事务的隔离性是指,一个事务的执行不应该被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务 之间不能互相干扰。
- 持久性:指一个事务一旦提交,他对数据库中的数据改变是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
数据库的并发问题
对于同时运行的多个事务,当这些事务访问数据库中的相同数据时,如果没有采用必要的隔离机制,就会导致各种并发问题。
- 脏读:对于两个事务T1,T2,T1读取了已经被T2更新但还没有提交的字段。若T2回滚,T1读取的内容就是临时且无效的。
- 不可重复读:对于两个事务T1,T2,T1读了一个字段,然后T2更新了该字段。之后,T1再次读取同一个字段,值就不同了。
- 幻读:对于两个事务T1,T2,T1从一个表中读取了一个字段,然后T2在该表中插入一些新的行,之后如果T1再次读取同一个表,就会多处几行。
四种隔离级别
- READ UNCOMMITTED:三种问题都没解决
- READ COMMITTED:只允许事务读取被其他事务提交的变更,可以避免脏读。
- REPEATABLE READ:确保事务可以多次从一个字段中读取相同的值,这个事务持续期间,禁止其他事务对这个字段进行更新,可以避免脏读和重复读。
- SERIALIZABLE:确保事务可以从一个读取相同的行,在该事务持续期间,禁止其他事务对该表执行插入,更新和删除操作,能避免所有并发问题,但性能低下。