oracle 锁的概念

一 锁(Lock)

  01,锁的概念

数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数 据库中就会产生多个事务同时存取同一数据的状况。若对并发操做不加控制就可 能会读取和存储不正确的数据,破坏数据库的一致性。 加锁是实现数据库并发控制的一个很是重要的技术。当事务在对某个数据对 象进行操做前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了 必定的控制,在该事务释放锁以前,其余的事务不能对此数据对象进行更新操做。 在Oracle 数据库中,它并非对某个表加上锁或者某几行加上锁,锁是以 数据块的一个属性存在的。 也就是说,每一个数据块自己就存储着本身数据块中 数据的信息,这个地方叫ITL(Interested Transaction List),凡是在这个数据块上有活动的事务,它的信息就会记录在这里面供后续的操做查询,一保证事务的一 致性。 

二 ,锁的分类

  按用户与系统划分,能够分为自动锁与显示锁      

    a) 自动锁(Automatic Locks):

      当进行一项数据库操做时,缺省状况下,系统自动为此数据库操做得到全部有必要的锁。自动锁分DML锁,DDL锁,system  locks。    node

    b) 显示锁(Manual Data Locks):

            某些状况下,须要用户显示的锁定数据库操做要用到的数据,才能使数据库操做执行得更好,显示锁是用户为数据库对象设定的。sql

  按锁级别划分,可分为: 排它锁(Exclusive  Locks,即X锁)和共享锁(Share Locks,即S锁)

    a) 共享锁(  S  ):

      共享锁使一个事务对特定数据库资源进行共享访问——另外一事务也可对此资源进行访问或得到相同共享锁。共享锁为事务提供高并发性,但如拙劣的事务设计+共享锁容易形成死锁或数据更新丢失。数据库

              b) 排它锁(  X):

      事务设置排它锁后,该事务单独得到此资源,另外一事务不能在此事务提交以前得到相同对象的共享锁或排它锁。 缓存

   按操做划分,可分为DML锁(data  locks,数据锁)、DDL锁(data dictionary lock)和 System Locks。 

    a) DML锁

DML 锁用于控制并发事务中的数据操纵,保证数据的一致性和完整性。 DML锁主要用于保护并发状况下的数据完整性。 DML 语句可以自动地得到所需的表级锁(TM)与行级(事务)锁(TX)。 它又分为: ( 1) TM 锁(表级锁) ( 2) TX 锁( 事务锁或行级锁) 当 Oracle 执行 DML 语句时,系统自动在所要操做的表上申请 TM 类型的锁。当 TM 锁得到后,系统再自动申请 TX 类型的锁,
并将实际锁定的数据行的锁标志位进行置位。 这样在事务加锁前检查 TX锁相容性时就不用再逐行检查锁标志,而只需检查 TM 锁模式的相容性便可,大大提升了系统的效率。 在数据行上只有 X 锁(排他锁)。 在 Oracle 数据库中,当一个事务首次发起一个 DML 语句时就得到一个 TX 锁,该锁保持到事务被提交或回滚。
当两个或多个会话在表的同一条记录上执行 DML 语句时,第一个会话在该条记录上加锁,其余的会话处于等待状态。当第一个会话提交后, TX 锁被释放,
其余会话才能够加锁。 当 Oracle 数据库发生 TX 锁等待时,若是不及时处理经常会引发 Oracle 数据库挂起,或致使死锁的发生,产生ORA
-600 的错误。
这些现象都会对实际应用产生极大的危害,如长时间未响应,大量事务失败等。

    A,1)TM锁(表锁)

TM 锁用于确保在修改表的内容时,表的结构不会改变,例如防止在 DML 语句执行期间相关的表被移除。当用户对表执行 DDL 或 DML 操做时,
将获取一个此表的表级锁。 当事务得到行锁后,此事务也将自动得到该行的表锁(共享锁),以防止其它事务进行 DDL 语句影响记录行的更新。 事务也能够在进行过程当中得到共享锁或排它锁,只有当事务显示使用 LOCK TABLE 语 句显示的定义一个排它锁时,事务才会得到表上的排它锁,
也可以使用 LOCK TABLE 显示的定义一个表级的共享锁。 TM 锁包括了 SS、 SX、 S、 X 等多种模式,在数据库中用
06 来表示。不一样的 SQL 操做产生不一样类型的 TM 锁

    A,2) TX 锁( 事务锁或行级锁)

当事务执行数据库插入、更新、删除操做时,该事务自动得到操做表中操做行的排它锁。 事务发起第一个修改时会获得TX 锁(事务锁),并且会一直持有这个锁,直至事务执行提交(COMMIT)或回滚(ROLLBACK)。 对用户的数据操纵, Oracle 能够自动为操纵的数据进行加锁,但若是有操纵受权,则为知足并发操纵的须要另外实施加锁。 DML 锁可由一个用户进程以显式的方式加锁,也可经过某些 SQL 语句隐含方式实现。 这部分属于 Manual Data Locks。 原理:一个事务要修改块中的数据,必须得到该块中的一个itl,经过itl和undo segment header中的transaction table,
能够知道事务是否处于活动阶段。事务在修改块时(其实就是在修改行)会检查行中row header中的标志位,若是该标志位为0(该行没有被活动的事务锁住),
就把该标志位修改成事务在该块得到的itl的序号,这样当前事务就得到了对记录的锁定,而后就能够修改行数据了,这也就是oracle行锁实现的原理。 DML 锁有以下三种加锁方式: 共享锁方式( SHARE) 独占锁方式( EXCLUSIVE) 共享更新锁( SHARE UPDATE)
其中: SHARE, EXCLUSIVE 用于 TM 锁(表级锁) SHARE UPDATE 用于 TX 锁( 行级锁)

(1)共享锁方式( SHARE)

共享方式的表级锁是对表中的全部数据进行加锁,该锁用于保护查询数据的一致性,防止其它用户对已加锁的表进行更新。session

其它用户只能对该表再施加共享方式的锁,而不能再对该表施加独占方式的锁,共享更新锁能够再施加,但不容许持有共享更新封锁的进程作更新。数据结构

共享该表的全部用户只能查询表中的数据,但不能更新。并发

共享方式的表级锁只能由用户用 SQL 语句来设置.oracle

LOCK TABLE <表名>[,<表名>]...   IN SHARE MODE [NOWAIT]   函数

执行该语句,对一个或多个表施加共享方式的表封锁。当指定了选择项  NOWAIT,若该锁暂时不能施加成功,则返回并由用户决定是进行等待,仍是先去执行别的语句。  高并发

持有共享锁的事务,在出现以下之一的条件时,便释放其共享锁: 
A、执行COMMIT或ROLLBACK语句。
B、退出数据库(LOG OFF)。
C、程序中止运行。
 
共享方式表级锁经常使用于一致性查询过程,即在查询数据期间表中的数据不发生改变。

 
(2)独占方式表级锁(Exclusive)

独占方式表级锁是用于加锁表中的全部数据,拥有该独占方式表封锁的用户,便可以查询该表,又能够更新该表,其它的用户不能再对该表施加任何加锁
(包括共享、独占或共享更新封锁)。其它用户虽然不能更新该表,但能够查询该表。

独占方式的表封锁可经过以下的SQL语句来显示地得到:
LOCK TABLE <表名>[,<表名>].... IN EXCLUSIVE MODE [NOWAIT]
独占方式的表级锁也能够在用户执行DML语句INSERT、UPDATE、DELETE时隐含得到。
拥有独占方式表封锁的事务,在出现以下条件之一时,便释放该封锁:
(1)、执行COMMIT或ROLLBACK语句。
(2)、退出数据库(LOG OFF)
(3)、程序中止运行。

独占方式封锁一般用于更新数据,当某个更新事务涉及多个表时,可减小发生死锁。

 
(3)共享更新加锁方式(Share Update)

共享更新加锁是对一个表的一行或多行进行加锁,于是也称做行级加锁。表级加锁虽然保证了数据的一致性,但却减弱了操做数据的并行性。行级加锁确保
在用户取得被更新的行到该行进行更新这段时间内不被其它用户所修改。于是行级锁便可保证数据的一致性又能提升数据操做的迸发性。
可经过以下的两种方式来得到行级封锁:
(1)、执行以下的SQL封锁语句,以显示的方式得到:
LOCK  TABLE  <表名>[,<表名>]....  IN  SHARE  UPDATE  MODE
[NOWAIT]
 
(2)、用以下的SELECT ...FOR UPDATE语句得到:
SELECT  <列名>[,<列名>]...FROM  <表名>  WHERE  <条件>  FOR
UPDATE OF <列名>[,<列名>].....[NOWAIT]
一旦用户对某个行施加了行级加锁,则该用户能够查询也能够更新被加锁的数据行,其它用户只能查询但不能更新被加锁的数据行.若是其它用户想更新该
表中的数据行,则也必须对该表施加行级锁.即便多个用户对一个表均使用了共享更新,但也不容许两个事务同时对一个表进行更新,真正对表进行更新时,是
以独占方式锁表,一直到提交或复原该事务为止。行锁永远是独占方式锁。
 
当出现以下之一的条件,便释放共享更新锁:
(1)、执行提交(COMMIT)语句;
(2)、退出数据库(LOG OFF)
(3)、程序中止运行。
 
执行ROLLBACK操做不能释放行锁。

    b) DDL锁(dictionary locks)

       DDL锁用于保护数据库对象的结构,如表、索引等的结构定义。 DDL锁又能够分为:排它DDL锁、共享DDL锁、分析锁
          1) 排它DDL锁:

建立、修改、删除一个数据库对象的DDL语句得到操做对象的 排它锁。如使用alter  table语句时,为了维护数据的完成性、一致性、合法性,该事务得到一排
它DDL锁。

      (2) 共享DDL锁:

需在数据库对象之间创建相互依赖关系的DDL语句一般需共享得到DDL锁。如建立一个包,该包中的过程与函数引用了不一样的数据库表,当编译此包时, 该事务就得到了引用表的共享DDL锁。 

      (3) 分析锁:

ORACLE使用共享池存储分析与优化过的SQL语句及PL/SQL程序,使运行相同语句的应用速度更快。一个在共享池中缓存的对象得到它所引用数据库对 象的分析锁。分析锁是一种独特的DDL锁类型,ORACLE使用它追踪共享池对象及它所引用数据库对象之间的依赖关系。当一个事务修改或删除了共享池持有 分析锁的数据库对象时,ORACLE使共享池中的对象做废,下次在引用这条SQL/PLSQL语 句时,ORACLE从新分析编译此语句。 DDL级加锁也是由ORACLE RDBMS来控制,它用于保护数据字典和数据定义改变时的一致性和完整性。它是系统在对SQL定义语句做语法分析时自动 地加锁,无需用户干予。 字典/语法分析加锁共分三类: (1)字典操做锁: 用于对字典操做时,锁住数据字典,此封锁是独占的,从而保护任何一 个时刻仅能对一个字典操做。 (2)字典定义锁: 用于防止在进行字典操做时又进行语法分析,这样能够避免在查询字典 的同时改动某个表的结构。 (3)表定义锁: 用于一个SQL语句正当访问某个表时,防止字典中与该表有关的项目被 修改。 

  死锁

死锁 当两个用户但愿持有对方的资源时就会发生死锁. 即两个用户互相等待对方释放资源时,oracle认定为产生了死锁,在这种状况下,将以牺牲一个用户做为代价,另外一个用户继续执行,牺牲的用户的事务将回滚。 场景 1:用户 1 对 A 表进行 Update,没有提交。 2:用户 2 对 B 表进行 Update,没有提交。 此时双反不存在资源共享的问题。 3:若是用户 2 此时对 A 表做 update,则会发生阻塞,须要等到用户一的事物结束。 4:若是此时用户 1 又对 B 表做 update,则产生死锁。此时 Oracle 会选择其中一个用户进行会滚,使另外一个用户继续执行操做。

 

原由: Oracle的死锁问题实际上不多见,若是发生,基本上都是不正确的程序设计形成的,通过调整后,基本上都会避免死锁的发生。 在Oracle系统中能自动发现死锁,并选择代价最小的,即完成工做量最少的事务予以撤消,释放该事务所拥有的所有锁,记其它的事务继续工做下去。 从系统性能上考虑,应该尽量减小资源竞争,增大吞吐量,所以用户在给并发操做加锁时,应注意如下几点: 一、对于UPDATE和DELETE操做,应只锁要作改动的行,在完成修改后当即提交。 二、当多个事务正利用共享更新的方式进行更新,则不要使用共享封锁,而应采用共享更新锁,这样其它用户就能使用行级锁,以增长并行性。 
三、尽量将对一个表的操做的并发事务施加共享更新锁,从而可提升并行性。 四、在应用负荷较高的期间,不宜对基础数据结构(表、索引、簇和视图)进行修改 若是死锁不能自动释放,就须要咱们手工的kill session。

 

三,锁的操做

  01,建立锁

生成锁,即启动三个链接到oracle数据库,两台同时操做一个表,另外一台查看争用用状况

 

  02,查看死锁状况

SELECT   'alter system kill session ''' || sid || ',' || serial# || ''';' "Deadlock" FROM v$session WHERE   sid IN (SELECT sid FROM v$lock WHERE   block = 1);

须要注意的是id再100如下多是一个aplication,对应的是事务才能kill

  03,跟踪问题 的sql

SELECT s.sid, q.sql_text FROM v$sqltext q, v$session s WHERE   q.address = s.sql_address AND s.sid = &sid ORDER BY   piece;

 点击后要求输入id,这个为查询出来的id值

  04,查看谁锁了谁

SELECT s1.username || '@' 
         || s1.machine || ' ( SID=' 
         || s1.sid || ' ) is blocking ' 
         || s2.username || '@' 
         || s2.machine || ' ( SID=' 
         || s2.sid || ' ) ' 
            AS blocking_status FROM v$lock l1, v$session s1, v$lock l2, v$session s2 WHERE       s1.sid = l1.sid AND s2.sid = l2.sid AND l1.BLOCK = 1 
         AND l2.request > 0 
         AND l1.id1 = l2.id1 AND l2.id2 = l2.id2;

或者这样查看

SQL> col USER_NAME format a10; SQL> col OWNER format a10; SQL> col OBJECT_NAME format a10; SQL> col OBJECT_TYPE format a10; SQL>   SELECT LPAD (' ', DECODE (l.xidusn, 0, 3, 0)) || l.oracle_username User_name, o.owner, o.object_name, o.object_type, s.sid, s.serial# FROM   v$locked_obje  2    3    4    5    6    7    8    9   10 ct l, dba_objects o, v$session s WHERE   l.object_id = o.object_id AND l.session_id = s.sid ORDER BY   o.object_id, xidusn DESC  11   12 ; USER_NAME OWNER OBJECT_NAM OBJECT_TYP SID SERIAL# ---------- ---------- ---------- ---------- ---------- ----------
SYS       SYS          T      TABLE           276         6522 SYS SYS T TABLE            29        25094

 

四,锁与阻塞

  01,概念

  一般来说,系统若是平时运行正常,忽然会中止不动,多半是被阻塞(Blocked)住了。 咱们能够经过v$lock 这张视图,看查看阻塞的信息。
  锁的视图:

SQL> desc v$lock Name Null? Type ----------------------------------------- -------- ----------------------------
 ADDR                            RAW(8) KADDR RAW(8) SID NUMBER TYPE VARCHAR2(2) ID1 NUMBER ID2 NUMBER LMODE NUMBER REQUEST NUMBER CTIME NUMBER BLOCK NUMBER CON_ID NUMBER
SQL> select * from v$lock; ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ----------
000000007DABD000 000000007DABD080     246 MR     21        0           4      0    165382        0       0 000000007DAC0640 000000007DAC06C0 7 KT      18972    5           4      0    510918        0       0 000000007DABCBA0 000000007DABCC20 247 XR      4        0           1      0         0        0       0 000000007DABCA88 000000007DABCB08 247 RD      1        0           1      0    693013        0       0 000000007DABC970 000000007DABC9F0 247 CF      0        0           2      0    693013        0       0 000000007DABCDD0 000000007DABCE50 10 RT      1        0           6      0    693009        0       0 000000007DABCCB8 000000007DABCD38 247 RS     25        1           2      0    693009        0       0 000000007DABD248 000000007DABD2C8 246 MR      3        0           4      0    693009        0       0 000000007DABDA08 000000007DABDA88 246 MR      5        0           4      0    693008        0       0 000000007DABE3F8 000000007DABE478 246 MR      6        0           4      0    693008        0       0 000000007DABF018 000000007DABF098 246 MR      9        0           4      0    692971        0       0 ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ----------
000000007DABDF80 000000007DABE000     246 MR      203      0           4      0    692971        0       0 000000007DABD590 000000007DABD610 246 MR      1        0           4      0    693009        0       0 000000007DABCEE8 000000007DABCF68 246 MR      4        0           4      0    693009        0       0 000000007DABD6A8 000000007DABD728 246 MR      7        0           4      0    693009        0       0 000000007DABD7C0 000000007DABD840 246 MR      201      0           4      0    693009        0       0 000000007DAC0DE8 000000007DAC0E68 246 MR     19        0           4      0    167393        0       0 000000007DABD478 000000007DABD4F8 248 TS      3        1           3      0    693009        0       1 000000007DABD8D8 000000007DABD958 7 KD      0        0           6      0    693009        0       0 000000007DABE1B0 000000007DABE230 246 MR      8        0           4      0    693008        0       0 000000007DABD360 000000007DABD3E0 16 AE      133      1           4      0    693008        0       0 000000007DABDD50 000000007DABDDD0 275 AE      133      1           4      0       451        0       0 ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ----------
000000007DABECD0 000000007DABED50     276 AE        133        1           4      0     14025        0       0 000000007DAC1260 000000007DAC12E0 29 AE        133        1           4      0     11965        0       0 000000007DAC0758 000000007DAC07D8 7 KT      18972        3           4      0     17990        0       0 000000007DABF130 000000007DABF1B0 246 MR         10        0           4      0    692971        0       0 000000007DABC858 000000007DABC8D8 246 MR        204        0           4      0    512035        0       0 000000007DABE2E0 000000007DABE360 246 MR        202        0           4      0    693008        0       0 000000007DABDC38 000000007DABDCB8 246 PW          1        0           3      0    693007        0       0 000000007DAC0870 000000007DAC08F0 246 MR         18        0           4      0    510918        0       0 000000007DABF248 000000007DABF2C8 246 MR         11        0           4      0    692971        0       0 000000007DABE628 000000007DABE6A8 7 KT      18972        2           4      0    693008        0       0 000000007DABFF98 000000007DAC0018 246 MR         22        0           4      0    165311        0       0 ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ----------
000000007DAC0BB8 000000007DAC0C38       7 KT      18972        4           4      0    512035        0       0 000000007DAC0988 000000007DAC0A08 246 MR         15        0           4      0    512035        0       0 000000007DABF360 000000007DABF3E0 246 MR         12        0           4      0    692971        0       0 000000007DABEDE8 000000007DABEE68 248 TS          3        1           3      0    689410        0       3 000000007DABF8F0 000000007DABF970 29 TX      65541     1671           0      6       397        0       1 000000007ADFBA08 000000007ADFBA90 276 TX      65541     1671           6      0       406        1       1 000000007DAC0AA0 000000007DAC0B20 7 KT      19005        1           4      0      3591        0       0 000000007DABF490 000000007DABF510 248 TS          3        1           3      0    513214        0       4 000000007DAC0510 000000007DAC0590 246 MR         17        0           4      0    510918        0       0 000000007DABEA88 000000007DABEB08 246 MR         13        0           4      0    512035        0       0 000000007DAC03F8 000000007DAC0478 246 MR         14        0           4      0    512035        0       0 ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK CON_ID ---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ----------
000000007DABFA08 000000007DABFA88     246 MR        205        0           4      0    510918        0       0 000000007DAC00B0 000000007DAC0130 246 MR         20        0           4      0    165939        0       0 000000007DABFC38 000000007DABFCB8 246 MR         16        0           4      0    510918        0       0 00007FD03B161448 00007FD03B1614B8 29 TM      75220        0           3      0       397        0       1 00007FD03B161448 00007FD03B1614B8 276 TM      75220        0           3      0     11897        0       1

49 rows selected.

 

 咱们关注的比较多的是request 和 block 字段。
若是某个request列是一个非0值,那么它就是在等待一个锁。  若是block列是1,这个SID 就持有了一个锁,而且阻塞别人得到这个锁。 这个锁的类型由TYPE 字段定义。锁的模式有LMODE 字段定义,ID1 和ID2 字段定义了这个锁的相关信息。ID1相同,就表明指向同一个资源。 这样就有可能有加锁者和等待者。 

参考下面的TM锁类型表。 

结合 v$lock 和 v$session 视图来查询相关的信息:

SQL> SELECT sn.username, m.SID, sn.SERIAL#, m.TYPE, DECODE(m.lmode, 0, 'None', 1, 'Null', 2, 'Row Share', 3, 'Row Excl.',  2    3    4    5    6    7    8    9   10   11   12   13
              4, 'Share', 5, 'S/Row Excl.', 6, 'Exclusive', lmode, LTRIM(TO_CHAR(lmode, '990'))) lmode, DECODE(m.request, 0, 14   15   16   17   18   19   20   21   22   23   24     'None', 1, 'Null', 2, 'Row Share', 3, 'Row Excl.', 4, 'Share', 5, 'S/Row Excl.', 6, ' 25 26 27 28 29 30 31 32 33 34 35 36 Exclusive', request, LTRIM(TO_CHAR(m.request, '990'))) request, m.id1, m.id2 FROM v$session sn, v$lock m WHERE (sn.SID = m.SID AND m.request != 0) --存在锁请求,即被阻塞
    OR (sn.SID = m.SID 37   38   39   40   41   42   43   44   45       --不存在锁请求,可是锁定的对象被其余会话请求锁定
       AND m.request = 0 AND lmode != 4 AND (id1, id2) IN (SELECT s.id1, s.id2 FROM v$lock s WHERE request != 0
                          AND s.id1 = m.id1 AND s.id2 = m.id2)) ORDER BY id1, id2, m.request; 46   47   48   49   50   51   52 USERNAME SID SERIAL# TY LMODE REQUEST ID1 ID2 -------------------------------------------------------------------------------------------------------------------------------- ---------- ---------- -- ----------- ----------- ---------- ----------
SYS                                                                276      6522 TX Exclusive   None           65541       1671 SYS29 25094 TX None          Exclusive        65541       1671 SQL>

或者经过下面查询

SQL> SELECT /*+ rule */ s.username, DECODE(l.TYPE, 'TM', 'TABLE LOCK', 'TX', 'ROW LOCK', NULL) lock_level, o.owner, o.object_name, o.object_type, s.sid, s.serial#, s.terminal, s.machine, s.program, s.osuser FROM v$session s, v$lock l, dba_objects o 2 3 4 5 6 7 8 9 10 11 12 13 WHERE l.sid = s.sid AND l.id1 = o.object_id(+) AND s.username IS NOT NULL; 14 15 16 USERNAMELOCK_LEVEL OWNER OBJECT_NAM OBJECT_TYP SID SERIAL# TERMINAL MACHINE PROGRAM OSUSER -------------------------------------------------------------------------------------------------------------------------------- ---------- ---- SYS SYS ORA$BASE EDITION 29 25094 pts/3 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle SYSROW LOCK PUBLIC oracle/ord SYNONYM 29 25094 pts/3 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle /media/jai /io/Memory CacheSeeka bleOutputS tream SYSTABLE LOCK SYS T TABLE 29 25094 pts/3 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle SYSTABLE LOCK SYS T TABLE 276 6522 pts/0 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle SYSROW LOCK PUBLIC oracle/ord SYNONYM 276 6522 pts/0 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle USERNAMELOCK_LEVEL OWNER OBJECT_NAM OBJECT_TYP SID SERIAL# TERMINAL MACHINE PROGRAM OSUSER -------------------------------------------------------------------------------------------------------------------------------- ---------- --- CacheSeeka bleOutputS tream SYS SYS ORA$BASE EDITION 276 6522 pts/0 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle SYS SYS ORA$BASE EDITION 275 12753 pts/4 node12c01 sqlplus@node12c01 (TNS V1-V3) oracle 7 rows selected. SQL>

引发阻塞的几种常见状况  

 (1)DML语句引发阻塞

当一个会话保持另外一个会话正在请求的资源上的锁定时,就会发生阻塞。被阻塞的会话将一直挂起,直到持有锁的会话放弃锁定的资源为止。 4个常见的dml语句会产生阻塞: (1INSERT2UPDATE3DELETE4SELECTFOR UPDATE  
INSERT   
Insert 发生阻塞的惟一状况就是用户拥有一个建有主键约束的表。当2个的会话同时试图向表中插入相同的数据时,其中的一个会话将被阻塞,直到另一个会话提交或会滚。 一个会话提交时,另外一个会话将收到主键重复的错误。回滚时,被阻塞的会话将继续执行。 UpdateDelete UPDATE 和DELETE当执行Update和delete操做的数据行已经被另外的会话锁定时,将会发生阻塞,直到另外一个会话提交或会滚。 Selectfor update 当一个用户发出select..for update的错做准备对返回的结果集进行修改时,若是结果集已经被另外一个会话锁定,此时Oracle已经对返回的结果集上加了排它 的行级锁,全部其余对这些数据进行的修改或删除操做都必须等待这个锁的释放(操做commit或rollback.),产生的外在现象就是其余的操做将发生阻塞. 一样这个查询的事务将会对该表加表级锁,不容许对该表的任何ddl操做,不然将会报出Ora-00054:resource busy and acquire with nowait specified. 能够经过发出 selectfor  update  nowait的语句来避免发生阻塞,若是资源已经被另外一个会话锁定,则会返回如下错误:Ora-00054:resource busy and acquire with nowait specified. 

 

  (2)外键没有建立索引

 若是系统中有主,外键引用关系,而且知足一下三个条件中的任意一个,那么就应该考虑给外键字段建立索引,不然系统的性能可能会降低甚至阻塞。 (1) 主表上有频繁的删除操做 (2) 主键上有频繁的修改操做。 (3) 业务上常常会出现主表和从表作关联查询的状况。 第一和第二个条件操做的时候,主表会在从表上建立一个锁定,以保证主表主键的修改不会致使从表的数据在引用上出现问题,这是一个数据引用完整性的 要求。 若是主表上常常出现这样的删除或者是对主键列进行修改的操做,或者每次操做的记录数不少,都将会形成从表长时间被锁定,而影响其余用户的正常 操做。 好比主表每次删除1000行数据,它就须要扫描从表1000次,以肯定每一行记录的改变都不会形成从表数据在引用上的不完整。 特别是在OLAP 系统中,从表常常会是很是巨大的表,在这种状况下,若是从表没有索引,那么查询几乎是不可想象的。 

 

Latch是内存中的资源锁,数据库对象(表,索引等)的锁叫Lock。 Latch和Lock的区别: (1). Latch 是对内存数据结构提供互斥访问的一种机制,而Lock是以不一样 的模式来套取共享资源对象,各个模式间存在着兼容或排斥,从这点看出,Latch 的访问,包括查询也是互斥的,任什么时候候,只能有一个进程能pin住内存的某一 块,幸亏这个过程是至关的短暂,不然系统性能将没的保障,从9I开始,容许 多个进程同时查询相同的内存块。 (2). Latch 只做用于内存中,他只能被当前实例访问,而Lock做用于数据 库对象,在RAC体系中实例间容许Lock检测与访问 (3). Latch 是瞬间的占用,释放,Lock的释放须要等到事务正确的结束, 他占用的时间长短由事务大小决定 (4). Latch 是非入队的,而Lock是入队的 (5). Latch 不存在死锁,而Lock中存在。 

V$SESSION:  表明数据库活动的开始,视为源起。
V$SESSION_WAIT:  视图用以实时记录活动SESSION的等待状况,是当前信
息。
V$SESSION_WAIT_HISTORY:  是对V$SESSION_WAIT的简单加强,记录活
动SESSION的最近10次等待。
V$SQLTEXT:  当数据库出现瓶颈时,一般能够从V$SESSION_WAIT找到那
些正在等待资源的SESSION,经过SESSION 的SID,联合V$SESSION和
V$SQLTEXT视图就能够捕获这些SESSION正在执行的SQL语句。
V$ACTIVE_SESSION_HISTORY: 是ASH的核心,用以记录活动SESSION的历
史等待信息,每秒采样一次,这部份内容记录在内存中,指望值是记录一个小时
的内容。
WRH#_ACTIVE_SESSION_HISTORY : 是V$ACTIVE_SESSION_HISTORY在
AWR的存储地。  
V$ACTIVE_SESSION_HISTORY: 中的信息会被按期(每小时一次)的刷新到负载
库中,并缺省保留一个星期用于分析。
DBA_HIST_ACTIVE_SESS_HISTORY:  视图是 WRH#_ACTIVE_SESSION_HISTORY视图和其余几个视图的联合展示,一般通
过这个视图进行历史数据的访问。
V$SYSTEM_EVENT  因为V$SESSION记录的是动态信息,和SESSION的生命
周期相关,而并不记录历史信息,因此ORACLE提供视图V$SYSTEM_EVENT
来记录数据库自启动以来全部等待事件的汇总信息。经过这个视图,用户能够迅
速得到数据库运行的整体概况。

 来自书籍>>

相关文章
相关标签/搜索