java web事务控制_JavaWeb学习之事务

一、事务(Transaction):其实是一组操作(包含许多个单一的逻辑)。只要有一个逻辑没有执行成功,那么都算失败。 所有的数据都回归到最初的状态(回滚)

例如:银行转账

A用户向B用户转账,这样的话转账中就有两个逻辑操作,1、A用户账户金额要减少  2、B用户账户金额要增加,此时就需要把这两个逻辑操作放入事务中

代码格式:

@Testpublic voidtestTransaction(){

Connection conn= null;

PreparedStatement ps= null;

ResultSet rs= null;try{

conn=JDBCUtil.getConn();//连接,事务默认就是自动提交的。 关闭自动提交。

conn.setAutoCommit(false);

String sql= "update account set money = money - ? where id = ?";

ps=conn.prepareStatement(sql);//扣钱, 扣ID为1 的100块钱

ps.setInt(1, 100);

ps.setInt(2, 1);

ps.executeUpdate();//加钱, 给ID为2 加100块钱

ps.setInt(1, -100);

ps.setInt(2, 2);

ps.executeUpdate();//成功: 提交事务。

conn.commit();

}catch(SQLException e) {try{//事变: 回滚事务

conn.rollback();

}catch(SQLException e1) {

e1.printStackTrace();

}

e.printStackTrace();

}finally{

JDBCUtil.release(conn, ps, rs);

}

}

二、事务的特性

①、原子性:事务中包含的逻辑,不可分割。

②、一致性:事务执行前后。数据完整性

③、隔离性:事务在执行期间不应该受到其他事务的影响

④、持久性:事务执行成功,那么数据应该持久保存到磁盘上。

三、隔离级别

①、读未提交(read uncommitted)

引发问题: 脏读

②、读已提交(read committed)

解决: 脏读 , 引发: 不可重复读,SQL Server没有这个问题

③、可重复读(repeatable-read)

解决: 脏读 、 不可重复读 , 引发: 幻读

④、可串行化(SERIALIZABLE)

解决: 脏读、 不可重复读 、 幻读

mySql 默认的隔离级别是 可重复读

Oracle 默认的隔离级别是  读已提交

Sql Server 默认的隔离级别是  读已提交

四、事务的安全隐患

不考虑隔离级别设置,那么会出现以下问题

①、读

脏读:一个事务读到了另一个事务未提交的数据

事务A:

USEBankGO

--使用默认隔离级别

BEGIN TRANSACTION

UPDATE ACCOUNT SET Money=Money-300 WHERE Id=1

WAITFOR DELAY '00:00:10'

ROLLBACK TRANSACTION

事务B:

USEBankGO

--设置隔离级别:未提交读

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

BEGIN TRANSACTION

--发生在事务回滚前

SELECT * FROM ACCOUNT WHERE Id=1

WAITFOR DELAY '00:00:10'

--发生在事务回滚后

SELECT * FROM ACCOUNT WHERE Id=1

COMMIT TRANSACTION

先执行事务A再执行事务B结果:

89e2777dcd7b9670e3b4ec5add081314.png

不可重复读:一个事务读到了另一个事务已提交的数据,造成前后两次查询结果不一致

事务A:

USEBankGO

--使用默认隔离级别

BEGIN TRANSACTION

UPDATE ACCOUNT SET Money=Money-300 WHERE Id=1

WAITFOR DELAY '00:00:10'

COMMIT TRANSACTION --注意

事务B:

USEBankGO

--设置隔离级别:读已提交

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

BEGIN TRANSACTION

--发生在事务回滚前

SELECT * FROM ACCOUNT WHERE Id=1

WAITFOR DELAY '00:00:10'

--发生在事务回滚后

SELECT * FROM ACCOUNT WHERE Id=1

COMMIT TRANSACTION

先执行事务B再执行事务A结果:

79605456f8c36c09a30a657f4fa9f318.png

幻读:一个事务读到了另一个事务insert的数据 ,造成前后查询结果不一致

事务A

USE Bank

GO

--使用默认隔离级别

BEGIN TRANSACTION

INSERT INTO ACCOUNT VALUES('Kimi',1000)

COMMIT TRANSACTION

事务B

USEBankGO

--设置隔离级别:读已提交

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ

BEGIN TRANSACTION

--发生在事务提交前

SELECT * FROMACCOUNTWAITFOR DELAY '00:00:10'

--发生在事务提交后

SELECT * FROMACCOUNTCOMMIT TRANSACTION

先执行事务B再执行事务A结果不一致,为幻读:

a1ca4a81cebd2838f2ff8c4c04f95d82.png

②、写

丢失更新

5fa5ec6917c214ec1645c241bcd30c11.png

5decf73c557590ee855b8efd29eaf984.png

数据丢失更新可以通过锁机制,来加以控制

五、总结

脏读

更新丢失

不可重复读

幻读

Read Uncommitted

可能

可能

可能

可能

Read Committed

不可能

可能

可能

可能

Repeatable Read

不可能

不可能

不可能

可能

Serializable

不可能

不可能

不可能

不可能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值