案例学习Oracle错误:ORA-00060

原文: ORA-00060 deadlock detected while waiting for resource.
  Cause: Your session and another session are waiting for a resource locked by the other. This condition is known as a deadlock. To resolve the deadlock, one or more statements were rolled back for the other session to continue work.

  Action Either: 1.Enter a ROLLBACK statement and re-execute all statements since the last commit or 2.Wait until the lock is released, possibly a few minutes, and then re-execute the rolled back statements.

ORA-00060:等待资源的时候检测到死锁。

  原因:A进程和B进程同时等待彼此所占用的资源,这就是所谓的死锁。解决死锁的思路是,回滚A进程的一条或多条语句,等待B进程完成后再执行。

  方案(两者皆可):回滚至最近一次提交,重新执行所有语句。或者,等待自动解锁,这个可能需要一些时间,解锁后,再执行语句。

      其实,Oracle提供的方案,多少有点保守,一般惯用方法:找到这个进程,直接kill掉!

  实验室:模拟死锁

  1.模拟死锁实验:

  1.1 主表

  -- Create table

  create table WDZ1

  (

  WDZ1ID NUMBER not null,

  MEMO VARCHAR2(20)

  )

  ;

  alter table WDZ1

  add constraint XXXXXX primary key (WDZ1ID);

  1.2 从表(没有外健的索引)

  -- Create table

  create table WDZ2

  (

  WDZ2ID NUMBER not null,

  WDZ1ID NUMBER,

  MEMO VARCHAR2(20)

  )

  ;

  -- Create/Recreate primary, unique and foreign key constraints

  alter table WDZ2

  add constraint XXXXX primary key (WDZ2ID)

  ;

  alter table WDZ2

  add constraint XXX foreign key (WDZ1ID)

  references WDZ1 (WDZ1ID);

  1.3 插入数据表到住表

  begin

  insert into wdz1 values (1,'aa');

  insert into wdz1 values(2,'aa2');

  insert into wdz1 values (3,'aa3');

  insert into wdz2 values(10,3,'wdz3--1');

  commit;

  end;

  1.4 在一个数据库seeesion里面插入数到从表,但是不提交事务

  begin

  update wdz2 set memo='update wdz2 momo'

  where wdz2id=10;

  insert into wdz2 values(20,2,'wdz2--1');

  end;

  对从表进行插入/修改记录,施加的锁也就是行级锁

  1.5 在另外一个数据库seeesion里面删除 主表数据

  delete from wdz1 where wdz1id=1

  这时候,程序会死锁,报错ORA-00060,除非上面的对从表的数据操作提交事务或者回滚事务。

  2. 具体原因分析

  一个数据表的外键主要有3种方式来维护它自己和主表数据的一致性。

  (1)delete cascade

  例子如下:

  alter table WDZ2

  add constraint XXX foreign key (WDZ1ID)

  references WDZ1 (WDZ1ID) on delete cascade;

  (2)Set null

  例子如下:

  alter table WDZ2

  add constraint XXX foreign key (WDZ1ID)

  references WDZ1 (WDZ1ID) on delete set null;

  (3)No action

  注意,这是oracle外键使用时候的默认选项。

  例子如下:

  alter table WDZ2

  add constraint XXX foreign key (WDZ1ID)

  references WDZ1 (WDZ1ID);

  以前出现死锁主要是我们认为,在 1。4。会对数据表wdz2进行施加行级锁,但是从表(wdz2)的外健是No action,删除主表(wdz1)不会去访问从表,更不会去锁定 wdz2表的记录或者对整个数据从表(wdz2)施加表级锁。事实上 oralce的No action 选项的字面意思欺骗了我们,oracle在删除主表的时候会去寻找所有以主表的主键作为外键的数据表,然后看去看从表是否有该外键的索引,如果没有则会对整个从表施加表级锁,然后对从表进行全表扫描。当然如果从表存在外键的索引,会去访问对应的索引,而不会对从表本身进行加锁。

  案例:并行运行某个特定的批处理时发生死锁错误

  描述:我的E10000 SUn /Solaris 机器有24个处理器。当并行运行某个特定的批处理的时候,总是在同一个时间点上发生死锁的错误(ora-60)。看起来,毫无疑问这是itl的问题(两个进程在等待共享锁的时候,都持有排他锁,因为initrans等于1)。我们有20个处理器在并行工作,但是Oracle总是在同一个更新语句上停滞不前。所以,解决方案看起来就是删除掉这个表,然后重新创建拥有更高initrans 的n个initrans 的表(高到什么程度?)。一些人说这可能是锁的密度带来的负面影响,所以解决方法就是增加pctfree 。你认为这个主意怎么样?选择prctfree 或者是initrans ,在哪种情况下密度会由于这些选项而产生问题。还有,我想要知道更多有关如何读取Oracle在发生死锁的时候创建的dump的信息。我如何解释这些dump,特别是,如何识别被停止的进程拥有,同时又被其他会话等待的资源?我觉得这可能会帮助我区别资源的竞争和中断的语句明显显示出来的现象。

  解答:ITL用于控制那些想要修改块的事务。有两个参数可以控制ITL。他们分别是INITRANS 和 MAXTRANS 。INITRANS 制定了ITL可以追踪的起始事务数量。对于表来说,这个参数的默认值是1。对于索引来说,这个参数默认值是2。MAXTRANS 制定了ITL可以追踪的最大的事务数量。对于表和索引来说,默认值都是255。

  由于越来越多的事务都要修改块(表或者索引),ITL的长度从INITRANS 个项增长到MAXTRANS 个项。除了在最极端的情况下,你不需要改变这些参数的默认值。在一些很罕见的情况下,有大量的事务争夺同一个块,你可以通过增加INITRANS 来加速事务的执行。通过这种方式,ITL不必增长,因为它已经被分配得更大了。但是就像我说的,这是很少见的情况,我怀疑这个是否会对你有帮助。

  设置一个较高的PCTFREE 意味着在你的块中存储的行数更少了。这会将你的数据行分配在更多的块中。同时它还意味着你要浪费更多的空间。通过将行分配到更多的块中去,你的事务也会跨越更多个块。

  我怀疑修改INITRANS 或 PCTFREE 的值并且重新构建表能否解决你的死锁问题。

  出现死锁的情况是因为事务A持有一个资源(resource_1)的锁,同时还在请求另一个资源(resource_2)的锁。事务B持有第二个资源(resource_2)的锁,同时 申请 第一个资源(resource_1)的锁。事务A正在等待事务B放开它的锁。与此同时(这是个关键,“与此同时”),事务B也在等待事务A释放它的锁。这两个事务就叫做死锁。换句话说,他们都在等待对方释放锁。同时他们在没有完成之前,又不会释放自己的锁。他们只有当获得另外一个锁的时候,才会完成。此时,Catch 22就会起作用了。Oracle的关系型数据 管理 系统自动的检测死锁,并且回滚第一个检测到死锁的过程。

  所以,你现在可以看到,当试图获得表中数据行或者索引中条目的锁的时候,死锁就发生了。这与ITL(还有INITRANS)或者块中剩余空间的大小(还有PCTFREE)毫无关系。调整这些数值不会解决你的死锁问题。并且这是非常容易测试的。重新构建具有不同数值的表并以与以前完全相同的方式重新运行你的应用程序。你还会看到死锁。这通常发生在并行运行同一个操作的时候。

  但是不要担心,因为你现在已经赢了一半了!!!你已经确定了发生死锁状况的特定的地点。这是进行追踪的最困难的事情。现在你可以看一下你的应用程序,看看它是如何引起死锁的。你也许想要实现不同的事务控制(例如串行化事务)来防止死锁情况的再一次发生。你可以在Oracle 8 Concepts Guide中阅读更多有关事务控制的内容(特别是第24章的数据并发性和一致性)。

你可能感兴趣的:(oracle,Solaris,sun)