HelloDBA [English]
搜索Internet 搜索 HelloDBABA
  Oracle技术站。email: fuyuncat@gmail.com  MSN: fuyuncat@hotmail.com   acoug  acoug 

事务队列等待(Tx Enqueue)深入分析——外键约束

[English]

作者: fuyuncat

来源: www.HelloDBA.com

日期: 2009-11-02 09:13:51

分享到  新浪微博 腾讯微博 人人网 i贴吧 开心网 豆瓣 淘宝 推特 Facebook GMail Blogger Orkut Google Bookmarks

    如果2个表之间建立了主外键关系,那么对它们的数据操作就会受到外键约束,以保证数据完整性:子表插入数据时,外键键值在主表中必须存在;主表删除时,子表中必须已经没有该键值的数据。如果进行这样的数据操作时,相应数据约束在另外事务里面已经满足(或正导致违反约束),但事务未完成,那么这样的数据操作的事务就会进入等待队列:

SQL代码
  1. HELLODBA.COM>create table tx_parent (p_id number, a varchar2(20));   
  2.   
  3. Table created.   
  4.   
  5. HELLODBA.COM>alter table tx_parent   
  6.   2    add constraint tx_parent_pk primary key (p_id);   
  7.   
  8. Table altered.   
  9.   
  10. HELLODBA.COM>create table tx_child (c_id number, p_id number, b varchar2(20));   
  11.   
  12. Table created.   
  13.   
  14. HELLODBA.COM>alter table tx_child   
  15.   2    add constraint tx_child_fk foreign key (p_id) references tx_parent (p_id);   
  16.   
  17. Table altered.   
  18.   
  19. HELLODBA.COM>create index tx_child_idx on tx_child (p_id);   
  20.   
  21. Index created.   
  22.   
  23. --session 1   
  24. HELLODBA.COM>insert into tx_parent values (1, 'AAA');   
  25.   
  26. 1 row created.   
  27.   
  28. --session 2   
  29. HELLODBA.COM>insert into tx_child values(1, 1, 'BBB');  

等待队列分析

    这种情况下的锁也是共享锁,等待事件为"enq: TX - row lock contention":

SQL代码
  1. HELLODBA.COM>select WAITING_SESSION, HOLDING_SESSION, MODE_HELD, MODE_REQUESTED from dba_waiters where lock_type='Transaction';   
  2.   
  3. WAITING_SESSION HOLDING_SESSION MODE_HELD     MODE_REQUESTED   
  4. --------------- --------------- ------------- --------------------------   
  5.             304             300 Exclusive     Share   
  6.   
  7. HELLODBA.COM>select s.sid, s.event, s.row_wait_obj#, o.object_name   
  8.   2    from v$session s, v$enqueue_lock l, dba_objects o   
  9.   3   where l.sid = s.sid   
  10.   4     and s.row_wait_obj# = o.object_id(+)   
  11.   5     and s.sid =304;   
  12.   
  13.        SID EVENT                            ROW_WAIT_OBJ#  OBJECT_NAME   
  14. ---------- -------------------------------- -------------- ----------------   
  15.        300 enq: TX - row lock contention    53844          ERROR_INFO   

    这种等待也是因为应用引起的,同样,需要排除其它可能(过程可以参考唯一性约束等待分析过程):

  • 找到被阻塞的语句;
  • 找到锁对象表;
  • 找出对应表上的主外键约束、唯一约束和Bitmap索引。

    如果仍然无法定位,则需要找到阻塞事务和被阻塞事务的逻辑代码进行分析。

死锁分析

    对这一类等待导致的死锁的分析,也是要先确认锁的类型和等待事件类型:

SQL代码
  1. Deadlock graph:   
  2.                        ---------Blocker(s)--------  ---------Waiter(s)---------   
  3. Resource Name          process session holds waits  process session holds waits   
  4. TX-00010025-00017965        29     304     X             13     300           S   
  5. TX-00080019-000213b0        13     300     X             29     304           S   
  6. ...   
  7.     last wait for 'enq: TX - row lock contention' blocking sess=0x1EDD0244 seq=167 wait_time=2999826 seconds since wait started=15   
  8.                 name|mode=54580004, usn<<16 | slot=80019, sequence=213b0  

    可以知道这是由于应用引起的死锁,然后获取相关语句进行逻辑分析:

SQL代码
  1. Current SQL statement for this session:   
  2. insert into tx_child values(2, 2, 'aaw')   
  3. ...   
  4.   Current SQL Statement:   
  5.   delete from tx_parent where p_id=1  

    对于外键约束引起的锁和死锁问题,要注意的是,在外键是否有索引,不仅会影响约束检查的性能,而且会导致关联表上被加载TM锁,增加死锁风险。
 

    此外,还需要注意的是,外键的DELETE CASCADE(SET NULL)属性,如果设置了该属性,主表数据删除时,会自动执行一条对子表对于键值数据的删除语句。

解决方法

    如果锁或者死锁是由于外键约束TX锁引起的,则解决方法就是需要调整应用,消除死锁陷阱,而如果是TM锁引起的,则需要在外键上建立索引。

Top

Copyright ©2005,HelloDBA.Com 保留一切权利

申明
by fuyuncat