Oracle中的锁(LOCK)机制(四)

2014-11-24 15:37:55 · 作者: · 浏览: 12

所以只要想要并发的修改表中相同的行,在第一个获取锁的事务没有结束前,后面的时候都会发生阻塞

_dexter@FAKE>select * from tun2_tab ;

ID NAME

--------------------------------------------------

1 dexter

2 dexter

3 NN

session1 session_id=144 :

_dexter@FAKE>delete from tun2_tab where id =1 ;

1 rowdeleted.

session2 session_id=18 :

_dexter@FAKE>delete tun2_tab where id >1 ;

2 rowsdeleted.

session3 session_id=9 :

_dexter@FAKE>delete tun2_tab ;

waiting...

_sys@FAKE>/

SID TYPE ID1 LMODE REQUEST BLOCK

-------------- ---------- ---------- ---------- ----------

9 TX 524317 0 6 0

9 TM 82618 3 0 0

18 TX 655383 6 0 0

18 TM 82618 3 0 0

144 TX 524317 6 0 1

144 TM 82618 3 0 0

6 rowsselected.

发生了阻塞,只有当session 1 和session 2 的事务结束后,session 3 才可以顺利完成。

Session1

Session2

Session3

Description

T1

delete from tun2_tab where id =1 ;

T2

delete tun2_tab where id >1 ;

session2 delete 操作因为不包括session 1 中的id=1的记录,所以可以顺利执行

T3

delete tun2_tab ;

waiting …

session3 delete操做,因为需要获取id=1,id>1记录的事务锁,所以发生了等待。可以看到它首先是在等待id=1的事务锁。

下面有两个有趣的实验

有趣小实验1

_dexter@FAKE>select * from tun2_tab ;

ID NAME

--------------------------------------------------

1 dexter

2 dexter

3 NN

session1 session_id=22:

_dexter@FAKE>delete from tun2_tab where id =2 ;

1 rowdeleted.

session2 session_id=18:

_dexter@FAKE>update tun2_tab set name ='dexter' where id>1 ;

waiting...

session3 session_id=9:

_dexter@FAKE>delete tun2_tab where id = 3 ;

1 rowdeleted.

查看一下锁的情况:

_sys@FAKE>/

SID TYPE ID1 LMODE REQUEST BLOCK

-------------- ---------- ---------- ---------- ----------

9 TX 393228 6 0 0

9 TM 82618 3 0 0

18 TX 131089 0 6 0

18 TM 82618 3 0 0

22 TX 131089 6 0 1

22 TM 82618 3 0 0

6 rowsselected.

这里比较有趣了,因为session 2 update 的记录包括id=2这一行,所以在id=2这一行加锁的时候,这里发生了transaction enqueue,它还没来得及对任何记录加锁,就已经进入了等待中。

而session3执行的时候发现id=3 的这一行还没有锁标示,所以它顺利的对id=3 的记录加了锁。

这个时候我们rollback 第一条记录后

session1 :

_dexter@FAKE>rollback ;

Rollbackcomplete.

发现session2 依然处于等待状态中

再看一下锁的情况:

_sys@FAKE>/

SID TYPE ID1 LMODE REQUEST BLOCK

-------------- ---------- ---------- ---------- ----------

9 TX 393228 6 0 1

9 TM 82618 3 0 0

18 TX 589840 6 0 0

18 TX 393228 0 6 0

18 TM 82618 3 0 0

这个时候我们可以看到session2又在等待session3的事务结束以便获取id=3这条记录的锁。

Session1

Session2

Session3

Description

T1

delete from tun2_tab where id =2 ;

T2

update tun2_tab set name ='dexter' where id>1 ;

waiting…

session 2 因为要获取id=2的记录的事务锁所以发生阻塞,等待session1 中的事务释放。

T3

delete tun2_tab where id = 3 ;

按照正常人的思维,比如说我。这一句应该等待session2中的事务才对。但是事实不是如此。因为session2陷入了阻塞,没还没有对id=3的记录加上事务锁,所以session3可以顺利执行。

T4

commit;

T5

still waiting

因为需要id=3的记录的事务锁,所以又被阻塞。

有趣小实验2

session1session_id=144:

_dexter@FAKE>delete from tun2_tab where id =3 ;

1 rowdeleted.

session2session_id=18:

_dexter@FAKE> update tun2_tab set name ='dexter' whereid>1 ;

waiting..

session3session_id=9:

_dexter@FAKE>delete tun2_tab where id = 2 ;

waiting..

看一下锁情况:

_sys@FAKE>/

SID TYPE ID1 LMODE REQUEST BLOCK

-------------- ---------- ---------- ---------- ----------

9 TX 196635 0 6 0

9 TM 82618 3 0 0

18 TX 196635 6 0 1

18 TM 82618 3 0 0

18 TX 458767 0 6 0

144 TM 82618 3 0 0

144 TX 458767 6 0 1

7 rowsselected.

session 3 也进入了等待中,因为session2 先获取了id=2 的行锁,然后等待id=3 的行锁。

Session1

Session2

Session3

Description

T1

delete from tun2_tab where id =3 ;

T2

update tun2_tab set name ='dexter' where id>1 ;

session 2 因为要获取id=3的记录的事务锁所以发生阻塞,但是在阻塞之前,以及对id=1|2的