JDBC 事务
@author ixenos
事务
1.概念:我们将一组语句构建成一个事务(trans action),当所有语句顺利执行之后,事务可以被提交(commit);否则,如果其中某个语句遇到错误,那么事务将被回滚,就好像没有任何语句被执行一样
2.需求背景:将多个语句组合成事务的主要原因是为了确保数据库完整性(database integrity)
3.默认情况下,数据库连接处于自动提交模式(autocommit mode),每个SQL语句一旦被执行便被提交给数据库,一旦命令被提交就无法对它进行回滚操作;
而我们在使用事务时,就要关掉这个默认值:
conn.setAutoCommit(false); //以下是一般的执行流程 Statement stmt = conn.createStatement(); //任意多次调用executeUpdate方法 stmt.executeUpdate(command1); stmt.executeUpdate(command2); stmt.executeUpdate(command3); .... //如果没有捕获异常而走到了这一步,那么调用commit方法 conn.commit(); //捕获到了异常,则调用rollback,自动撤销上次提交以来的所有语句 conn.rollback();
保存点(save point)
1.使用保存点可以更细粒度地控制回滚(rollback)操作
2.创建一个保存点意味着只需返回到这个点,而非事务的开头
conn.setAutoCommit(false); //事务开始 Statement stmt = conn.createStatement(); stmt.executeUpdate(command1); //创建保存点 Savepoint spoint = conn.setSavepoint(); stmt.executeUpdate(command2); if(.....){ conn.rollback(spoint); //撤销command2的影响 } ... conn.commit();
3.当不需要保存点时,释放它
conn.releaseSavepoint(spoint);
批量更新(batch update)
1.需求背景:一个程序需要执行许多INSERT语句,以便将数据填入数据库表中,此时可以使用批量更新的方法来提高性能;
2.注意:
(1)处于同一批中的语句可以使INSERT、UPDATE和DELETE操作,也可以是数据库定义的语句,如CREATE TABLE和DROP TABLE
(2)但是在批量处理中添加SELECT语句将抛出异常! 因为批量处理SELECT语句是没有意义的,因为只是返回结果集,而不会更新数据库!
3.示例:
Statement stmt = conn.createStatement(); //此时调用addBatch冯方法,而非executeUpdate方法 String command = "CREATE TABLE ..."; stmt.addBatch(command); while(...){ command = "INSERT INTO ... VALUES(" + ... + ")"; stmt.addBatch(command); } //最后提交整个批量更新语句 int[] counts = stmt.executeBatch();
事务mix批量更新
为了在批量模式下正确识别错误,必须将批量执行的操作视为单个事务(原子性),如果批量更新在执行过程中失败,那么必须将它会滚到批量操作开始之前的状态。
首先,关闭自动提交模式,然后收集批量操作,执行并提交该操作,最后恢复到最初的自动提交模式:
//备份原来提交模式的参数 boolean autoCommit = conn.getAutoCommit(); //设置手动提交事务,将批量更新视为一个事务 conn.setAutoCommit(false); //执行一系列 stmt.addBatch(...); 操作 Statement stmt = conn.getStatement(); ... stmt.addBatch(...) ... //先批量更新,成为一个批量更新事务 stmt.executeBatch(); //确定提交 批量更新 事务 conn.commit(); //还原原来的提交模式的参数 conn.setAutoCommit(autoCommit);
恢复日志
1.撤销修改(rollback)的实现,基本的解决方案是:DB系统会永久保存一个日志,日志中记录了修改的详细信息,特别是记录每次修改对象之前的值和修改对象之后的值;因此,如果要撤销特定的修改,DB系统会使用相应的日志记录把修改对象恢复到初始值(修改前的值)
2.撤销修改的过程必须遵循:事先写入日志规则;即给定修改的日志记录必须在这个修改被实际写入到数据库之前记录到日志文件中;
(1)对于给定事务的所有其他日志都要在该事务COMMIT记录被物理地写入日志之前,被物理地写入到日志中
(2)直到该事务的COMMIT记录被物理地写入到日志中,COMMIT处理才能完成
遵循该规则的事务不仅是一个工作单元,也是一个恢复单元。
事务的ACID特性
ACID代表原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
1.原子性:事务要么全部执行,要么全部不执行;
2.一致性:事务把数据库从一个一致性状态转换到另一个一致性状态,不去考虑中间状态;
3.隔离性:任何事务的修改都与其他事务隔离,直到该事务被成功提交;(锁!)
4.持久性:一旦事务被成功提交,所有的修改会被永久保存在数据库中;
#原子性和持久性的含义是事务分别是一个工作单元和一个恢复单元;
#一致性的含义是事务是完整性单元;
#隔离性的含义是事务是并发单元