java事务运行的并发问题

 

对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题,这些并发问题可归纳为以下几类:

假设数据库中有如下一张表:


 第一类丢失更新(lost update)

在完全未隔离事务的情况下,两个事务更新同一条数据资源,某一事务异常终止,回滚造成第一个完成的更新也同时丢失。

T1时刻开启了事务1T2时刻开启了事务2,在T3时刻事务1从数据库中取出了 id="402881e535194b8f0135194b91310001"的数据,T4时刻事务2取出了同一条数据,T5时刻事务1age字段值更新为30T6时刻事务2更新age35并提交了数据,但是T7事务1回滚了事务age最后的值依然为20,事务2的更新丢失了,这种情况就叫做"第一类丢失更新(lost update)"

 

    如果在事务1完成之后事务2才能进行更改,则可以避免该问题。

 

•脏读(dirty read)- 未确认的相关性

如果第二个事务查询到第一个事务还未提交的更新数据,形成脏读。

T1时刻开启了事务1T2时刻开启了事务2,在T3时刻事务1从数据库中取出了id="402881e535194b8f0135194b91310001"的数据,在T5时刻事务1age的值更新为30,但是事务还未提交,T6时刻事务2读取同一条记录,获得age的值为30,但是事务1还未提交,若在T7时刻事务1回滚了事务2的数据就是错误的数据(脏数据),这种情况叫做" 脏读(dirty read)"

 

如果在事务1确定最终更改前任何人(事务2)都不能读取更改的文档,则可以避免该问题。

 

•虚读(phantom read)- 幻像读

一个事务读到另一个事务已提交的新插入的数据。

一个事务执行两次查询,第二次结果集包含第一次中没有或者某些行已被删除,造成两次结果不一致,只是另一个事务在这两次查询中间插入或者删除了数据造成的。

T1时刻开启了事务1T2时刻开启了事务2T3时刻事务1从数据库中查询所有记录,记录总共有一条,T4时刻事务2向数据库中插入一条记录,T6时刻事务2提交事务。T7事务1再次查询数据数据时,记录变成两条了。这种情况是"虚读(phantom read)"

 

如果在事务1完成对数据的处理之前,任何人都不能将新数据添加到表中,则可以避免该问题。

 

•不可重复读(unrepeated read)- 不一致的分析

一个事务读到另一个事务已提交的更新数据。

一个事务两次读取同一行数据,结果得到不同状态结果,如中间正好另一个事务更新了该数据,两次结果相异,不可信任。

T1时刻开启了事务1T2时刻开启了事务2,在T3时刻事务1从数据库中取出了 id="402881e535194b8f0135194b91310001"的数据,此时age=20T4时刻事务2查询同一条数据,T5事务2更新数据age=30T6时刻事务2提交事务,T7事务1查询同一条数据,发现数据与第一次不一致。这种情况就是"不可重复读(unrepeated read)"

 

如果只有在事务2全部完成编写后事务1才可以读取文档,则可以避免该问题。

 

•第二类丢失更新(second lost updates)

这是不可重复读中的特例,一个事务覆盖另一个事务已提交的更新数据。  

    是不可重复读的特殊情况,如果两个事务都读取同一行,然后两个都进行写操作,并提交,第一个事务所做的改变就会丢失。

 

T1时刻开启了事务1T2时刻开启了事务2T3时刻事务1更新数据age=25T5时刻事务2更新数据age=30T6时刻提交事务,T7时刻事务2提交事务,把事务1的更新覆盖了。这种情况就是"第二类丢失更新(second lost updates)"

 

并发问题对数据库进行读取、更新、删除和插入数据过程中得到不同的结果进行归类。假设用户在某一段时间内要求操作数据的正确性和一致性。

更新、插入 -- 脏读

更新       -- 非重复读

删除、插入 -- 幻像读

 

为了处理并发问题,可以采用适当的事务隔离级别进行控制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值