oracle数据库并发二

阅读更多

阻塞

如果一个会话持有某个资源的锁,而另一个会话在请求这个资源,就会出现阻塞(blocking )。这样一来,请求的会话会被阻塞,它会“挂起”,直至持有锁的会话放弃锁定的资源。

数据库中有5 条常见的DML 语句可能会阻塞,具体是:INSERTUPDATEDELETEMERGESELECT FOR UPDATE 。对于一个阻塞的SELECT FOR UPDATE ,解决方案很简单:只需增加NOWAIT 子句,它就不会阻塞了。

例子

时间点

Session1

Session2

T1

开始事务

 

T2

 

开始事务

T3

Update A set col1=2 where id=1

获得id1 的行的排它锁(X

 

T4

 

Update A set col1=5 where id=1

等待session1 释放id1 的行的排它锁(X

T5

commit

 

T6

 

commit

在上面的例子中

Session1 T3 时刻获得id1 的行的排它锁(X),T4 时刻,session2 也要更新该行,也要在行上加排它锁(X ),由于session1 的事务还没有提交,因此session2 这个时候就被阻塞了,只到session1 的事务提交或回滚后session2 也获得此行的排它锁(X )使事务得以进行。

死锁

       如果你有两个会话,每个会话都持有另一个会话想要的资源,此时就会出现死锁(deadlock )。

例子

时间点

Session1

Session2

T1

开始事务

 

T2

 

开始事务

T3

Update A set col1=2 where id=1

获得id1 的行的排它锁(X

 

T4

 

Update B set col1=5 where id=4

获得id4 的行的排它锁(X

T5

Update B set col1=6 where id=4

等待session2 释放id4 的行的排它锁(X

 

T6

 

Update A set col1=8 where id=1

等待session1 释放id1 的行的排它锁(X

T7

commit

 

T8

 

commit

在上面的例子中

    Session1 T3 时刻获得表Aid1 的行的排它锁(X),T4 时刻,session2 获得表Bid4 的行的排它锁(X),T5 时刻,session1 要更新表Bid4 的行,要在行上加排它锁(X ),由于session2 的事务还没有提交,因此session1 这个时候就被阻塞了,T6 时刻session2 要更新表Aid1 的行,要在行上加排它锁(X ),由于session1 的事务还没有提交,因此session2 这个时候就被阻塞了,这时两个会话都被对方阻塞了于是死锁就发生了。

    oracle 中,oracle 会自己检测死锁,一旦检测到就会回滚该语句,在这个例子中oracle 会在T6 时刻检测到死锁并回滚该语句,但session2T4 上仍然保持着锁,因此session1 还是不能继续进行。

    即使对同一个表操作也会出现死锁的情况

时间点

Session1

Session2

T1

开始事务

 

T2

 

开始事务

T3

Update A set col1=2 where id=1

获得id1 的行的排它锁(X

 

T4

 

Update A set col1=5 where id=4

获得id4 的行的排它锁(X

T5

Update A set col1=6 where id=4

等待session2 释放id4 的行的排它锁(X

 

T6

 

Update A set col1=8 where id=1

等待session1 释放id1 的行的排它锁(X

T7

commit

 

T8

 

commit

 

你可能感兴趣的:(Oracle)