事务:由一个或多个执行、完成的语句组成,以组的形式提交或回滚。当前事务结束,另一个事务开始。
在JDBC中,事务默认是自动提交的,即每执行一条语句,就是一个事务。
事务特性:ACID特征,Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)。
- 原子性:指整个事务是不可以分割的工作单元。只有事务中所有的操作执行成,才算整个事务成功;事务中任何一个SQL语句执行失败,那么已经执行成功的SQL语句也必须撤销,数据库状态应该回到执行事务前的状态。
- 一致性:指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。例如对于银行转账事务,不管事务成功还是失败,应该保证事务结束后两个转账账户的存款总额是与转账前一致的。
- 隔离性:指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。
- 持久性:指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
事务各个特征的实现手段:
- 原子性:日志
- 一致性:日志
- 隔离性:锁机制
- 持久性:日志
事务隔离级别(5级):
- 0:TRANSACTION_NONE
- 1:TRANSACTION_READ_UNCOMMITTED
- 2:TRANSACTION_READ_COMMITTED 防止脏读
- 4:TRANSACTION_REPEATABLE_READ 防止不可重复读
- 8:TRANSACTION_SERIALIZABLE 防止 幻影读
Oracle支持2种:2和8,默认为2.
并发环境中的几种情况:
- 脏读:一个事务在提交前可以看到另一个事务的行为,则出现脏读。一个事务读到了其它事务没有提交的数据;
- 不可重复读:一个事务通过SQL读取数据后,有其它事务立刻作了DML操作,并且提交了,然后第一个事务通过相同的SQL语句再次读取,所得的数据和第一次读取的数据不一致的情况。
要点:同一个事务,同一语句,在多次读取过程中,所得到的结果不一致的情况。
如何防止:在执行SELECT语句时加上for update子句 - 幻(影)读:基本理解同不可重复读。
区别:
不可重复读:指某些列的值的不同,
幻影读:指表的总记录数量上的不同。
如何防止:锁表,代价很高。
使用如下方法控制连接的独立性等级:
conn.setTransactionIsolation(Connection.TRANSACTION_XXX);
事务的开始与结束:
首先,因为默认的JDBC事务是自动提交的,故我们在获取数据库连接后,应该将连接改为非自动提交模式:
conn.setAutoCommit(false); //标志着新事务的开始
conn.commit(); //提交
conn.rollback(); //回滚
在JDBC 3.0新增功能中,提供对事务commit和rollback的更好支持,在事务过程中,在两个操作间可以插入一个命名的存储点作为标记,因此可以将事务回滚到那个标记,保留标记有效前的所有操作。
示例:
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
stmt.executeUpdate(update1);
Savepoint point1 = conn.setSavepoint("point1");
stmt.executeUpdate(update2);
stmt.executeUpdate(update3);
conn.rollback(point1);
conn.commit();
概念:从这一点设置的时间点开始(时间点a)到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据) 应用场合: 如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性; 怎样设置: 对于只读查询,可以指定事务类型为readonly,即只读事务。 (1)在JDBC中,指定只读事务的办法为: connection.setReadOnly(true); (2)在Hibernate中,指定只读事务的办法为: session.setFlushMode(FlushMode.NEVER); (3)在Spring的Hibernate封装中,指定只读事务的办法为: bean配置文件中,prop属性增加“readOnly” 在将事务设置成只读后,相当于将数据库设置成只读数据库,此时若要进行写的操作,会出现错误 |