事务
定义:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
要么都成功,要么都失败,这是事务最重要的性质。
ACID原则
- (Atomicity):原子性:要么都发生,要么都不发生
- (Consistency):一致性:总数不变
- (Isolation):隔离性:多个线程互不干扰
- (Durability):持久性:一旦提交不可逆,持久化到数据库
原子性是指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
隔离性是指多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。
持久性意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
隔离性的问题
- 脏读: 一个事务读取了另一个没有提交的事务
- 不可重复读:在同一个事务内,重复读取表中的数据,而在读的过程中表中数据发生了改变。
- 虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来的结果不一致。
代码测试:
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = JDBCUtils.getConnection();
// 关闭数据库的事务自动提交模式,自动会开启事务
// 自动提交的时候每条sql语句会被当作一个单独的事务自动执行
// 因此需要关系自动提交来保证数据的一致性
connection.setAutoCommit(false);
String sql1 = "update account set asset = asset - 100 where name = '小红' ";
// 预编译
preparedStatement = connection.prepareStatement(sql1);
preparedStatement.executeUpdate();
String sql2 = "update account set asset = asset + 100 where name = '小黄' ";
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();
// 提交事务(前面设置自动提交关闭,需手动提交)
connection.commit();
System.out.println("执行成功!");
connection.prepareStatement(sql2);
} catch (SQLException e) {
try {
connection.rollback(); // 如果失败就回滚事务
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
} finally {
try {
JDBCUtils.release(connection,preparedStatement,resultSet);
} catch (SQLException e) {
e.printStackTrace();
}
}
执行结果:
步骤:
1.开启事务。connection.setAutoCommit(false)
2.一组事务执行完毕,提交事务。
3.在catch中加回滚语句,默认失败回滚。