首页 > 代码库 > 锁


锁类型
例子

update
select type,name from v$lock_type;

SQL> create table t(id int primary key);

表已创建。

SQL> insert into t values(1);

已创建 1 行。

SQL> commit;

提交完成。

SQL> update t set id=2 where id =1;

已更新 1 行。

SQL> select distinct sid from v$mystat;

       SID
----------
        71

SQL>

C:\Users\Administrator>sqlplus / as sysdba

SQL*Plus: Release 11.2.0.1.0 Production on 星期六 1228 09:52:04 2013

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


连接到:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> update t set id=2 where id=1;


连接到:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> select distinct sid from v$mystat;

       SID
----------
       140

SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in(‘TM‘,‘TX‘) order by 1,2;

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
        13 TM      76350          0          3          0          0
        13 TX     327703       7274          0          6          0
        71 TM      76350          0          3          0          0
        71 TX     327703       7274          6          0          1

SQL> select object_name from dba_objects where object_id =76350;

OBJECT_NAME
--------------------------------------------------------------------------------
T

ID1 + ID2就是回滚段上的那个号

SQL> select sid,event from v$session_wait where sid in(13,71);

       SID EVENT
---------- ----------------------------------------------------------------
        13 enq: TX - row lock contention
        71 SQL*Net message from client

insert 
SQL> select * from t;

        ID
----------
         2

SQL> insert into t values(3);

已创建 1 行。

SQL>

SQL> insert into t values(1);

已创建 1 行。

SQL> insert into t values(3);

SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in(‘TM‘,‘TX‘) order by 1,2;

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
        13 TM      76350          0          3          0          0
        13 TX     196620       7299          0          4          0
        13 TX     655364       7058          6          0          0
        71 TM      76350          0          3          0          0
        71 TX     196620       7299          6          0          1

select ... for update
SQL> select * from t;

        ID
----------
         2
         3
         1

SQL> select * from t where id=1 for update;

        ID
----------
         1

SQL> update t set id=4 where id=1;

SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in(‘TM‘,‘TX‘) order by 1,2;

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
        71 TM      76350          0          3          0          0
        71 TX     196622       7299          6          0          0

SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in(‘TM‘,‘TX‘) order by 1,2;

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
        13 TM      76350          0          3          0          0
        13 TX     196622       7299          0          6          0
        71 TM      76350          0          3          0          0
        71 TX     196622       7299          6          0          1

主外键导致主从表的关系
SQL> create table p(id int primary key);

表已创建。

SQL> create table c(id references p(id));

表已创建。

SQL> select sid,type,id1,id2,lmode,request,block from v$lock where type in(‘TM‘,‘TX‘) order by 1,2;

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ---------- ---------- ----------
        71 TM      76354          0          3          0          0
        71 TM      76356          0          3          0          0
        71 TX      65540       7128          6          0          0

SQL> select object_name from dba_objects where object_id in (76354,76356);

OBJECT_NAME
--------------------------------------------------------------------------------
P
C

死锁

两个会话互相持有对方资源导致死锁。


许多Oracle锁又被称为"enqueue locks"。从英文一般的构词规则来看,enqueue应该是动词(翻译成"排队"或"加入队列"),但在这里,经常被用做形容词(可以翻译成"队列式的")、甚至是名词(可以翻译成"队列")。计算机软件中的"锁"往往是用来解决稀缺资源的争用问题,而此种问题更完善的解决还会用到排队机制(如同人类社会解决稀缺资源争用问题一样,比如众多顾客到银行办理各种业务),所以"锁"(lock)与"队列"(enqueue)这两个词在这一领域的某些场合可以互换。下面还是看一个具体的例子:
SESS#1>update dept set loc=loc where deptno=10;
SESS#2> lock table dept in share mode;
该事务被阻塞,采用第三个监控脚本。
SESS#0>@showlockorder
resource           SID LOCK_TYPE           REQUEST              CTIME BLOCK
--------------- ------ ------------------- --------------- ---------- ------
TM-30137-0          10 Row Exclusive       None                   227      1
                    12 None                Share                  181      0
TX-196618-524       10 Exclusive           None                   227      0

在SESS#1(SID为10)在DEPT表上获得Row Exclusive锁,而SESS#2(SID为12)在DEPT表上申请Share锁,被SESS#1阻塞。
SESS#3>update dept set loc=loc where deptno=20;
该事务也被阻塞。
SESS#0>@showlockorder
resource           SID LOCK_TYPE           REQUEST              CTIME BLOCK
--------------- ------ ------------------- --------------- ---------- ------
TM-30137-0          10 Row Exclusive       None                   357      1
                    12 None                Share                  311      0
                    13 None                Row Exclusive            3      0
TX-196618-524       10 Exclusive           None                   357      0
SESS#3(SID为13)申请DEPT表的Row Exclusive锁,虽然与SESS#1所持有的Row Exclusive锁相容,但由于SESS#2(SID为12)在之前已被阻塞,SESS#3也被阻塞。
SESS#1>rollback;
SESS#0>@showlockorder
resource           SID LOCK_TYPE           REQUEST              CTIME BLOCK
--------------- ------ ------------------- --------------- ---------- ------
TM-30137-0          13 None                Row Exclusive          635      0
                    12 Share               None                    56      1
SESS#1回滚后,SESS#2(SID为12)获得Share,SESS#3(SID为13)申请的Row Exclusive锁被其阻塞。
由此例可以看出,一旦某一事务阻塞于某一资源(如上例的SESS#2),其后向该资源新申请锁的事务都将被阻塞,而不论新申请的封锁类型是否相容于已获得的封锁类型。
表面上看,这样的处理方法好象不是很合理,但深入分析一下,这样做是有道理的,它主要是要避免数据库理论中所谓的"活锁"(英文为starvation直译为"饥饿")问题。所谓"活锁",是指:如果事务T1封锁了数据D,事务T2又请求封锁D,于是T2等待。T3也请求封锁D,当T1释放了D上的封锁之后系统首先批准了T3的请求,T2仍然等待。然后T4又请求封锁D,当T3释放了D上的封锁后系统又批准了T4的请求……则T2可能永远等待,这就是所谓的"活锁"。避免"活锁"的简单方法是采用先来先服务的策略。当多个事务请求封锁同一数据对象时,系统按请求的先后顺序对事务排队,数据对象上的锁一旦释放就批准申请队列中第1个事务获得锁。
可见,Oracle也采用了上述原则,否则的话,在有大量并发事务的情况下,高强度的锁(如本例SESS#2申请表级的Share锁)申请有可能长时间无法得到满足。

来源: <http://hi.baidu.com/irphzqgscabnoqd/item/67a0939d02dd98df1b49dfd4>


 























来自为知笔记(Wiz)