天天看點

ORA-00060的示例與若幹場景

create table eg_60 ( num number, txt varchar2(10) );

insert into eg_60 values ( 1, 'First' );

insert into eg_60 values ( 2, 'Second' );

SQL> select rowid, num, txt from eg_60;

ROWID                     NUM TXT

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

AAAQT2AAHAAAEdYAAA          1 First

AAAQT2AAHAAAEdYAAB          2 Second

Session1:

update eg_60 set txt='ses1' where num=1;

Session2:

update eg_60 set txt='ses2' where num=2;

update eg_60 set txt='ses2' where num=1;

update eg_60 set txt='ses1' where num=2;

此時Session2報的錯:

update eg_60 set txt='ses2' where num=1

       *

ERROR at line 1:

ORA-00060: deadlock detected while waiting for resource

Session1的update eg_60 set txt='ses1' where num=2;仍處hang狀态,此時Session2執行exit正常退出,則

1 row updated.

原因就是正常退出,Oracle的PMON會自動rollback所做的未Commit操作,釋放了num=2的資源,是以Session1可以執行。

出現60錯誤會産生一個trace檔案,檢視trace檔案位置:

show parameter user_dump

NAME                                  TYPE       VALUE

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

user_dump_dest                 string      /opt/app/ora10g/admin/petest/udump

檢視trace檔案:

Deadlock graph:

                       ---------Blocker(s)--------  ---------Waiter(s)---------

Resource Name          process session holds waits  process session holds waits

TX-00090004-00019887        25     478     X             24     459           X

TX-000a002d-00032a8d        24     459     X             25     478           X

session 478: DID 0001-0019-00027AEC     session 459: DID 0001-0018-000CDDD8

session 459: DID 0001-0018-000CDDD8     session 478: DID 0001-0019-00027AEC

Rows waited on:

Session 459: obj - rowid = 000104F6 - AAAQT2AAHAAAEdYAAB

  (dictionary objn - 66806, file - 7, block - 18264, slot - 1)

Session 478: obj - rowid = 000104F6 - AAAQT2AAHAAAEdYAAA

  (dictionary objn - 66806, file - 7, block - 18264, slot - 0)

Information on the OTHER waiting sessions:

Session 459:

  pid=24 serial=34722 audsid=899246 user: 65/DCSOPEN

  O/S info: user: dcsopen, term: pts/0, ospid: 8838, machine: vm-vmw4131-t

            program: sqlplus@vm-vmw4131-t (TNS V1-V3)

  application name: SQL*Plus, hash value=3669949024

  Current SQL Statement:

  update eg_60 set txt='ses1' where num=2

End of information on OTHER waiting sessions.

Current SQL statement for this session:

===================================================

這裡66806代表的OBJECT_ID對應object是eg_60。目前執行的SQL是update eg_60 set txt='ses2' where num=1,是這條SQL報的60錯誤,原因是由于update eg_60 set txt='ses1' where num=2這條SQL。因為這裡是在同一台機器開的兩個session,如果是不同機器用戶端通路資料庫做的這個實驗,就可以根據machine: vm-vmw4131-t知道是哪個用戶端執行的這條SQL。

通過PROCESS STATE節中O/S info: user: dcsopen, term: pts/1, ospid: 13112, machine: vm-vmw4131-t也可以知道是哪個用戶端執行SQL報的60錯誤。

以上是同一張表不同session之間産生的死鎖。還有另外一種場景,也是之前這邊應用碰到的問題,即不同表之間的死鎖,剛剛初步得解的,其實上述兩種都屬于事務級别的死鎖,這裡可能說的不準确,就是因為執行一個SQL後沒有commit或rollback,再執行另外一個SQL,這兩個SQL形成一個事務,造成可能的死鎖。

關于事務,Concept中的解釋:

A transaction is a logical unit of work that contains one or more SQL statements. A transaction is an atomic unit. The effects of all the

SQL statements in a transaction can be either all committed (applied to the database) or all rolled back (undone from the database).

A transaction begins with the first executable SQL statement. A transaction ends when it is committed or rolled back, either explicitly

with a COMMIT or ROLLBACK statement or implicitly when a DDL statement is issued.

比如:

UPDATE TABLE1,UPDATE TABLE2 ...

DELETE TABLE2, DELETE TABLE1 ...

此時碰巧可能出現互相持有對方需要的資源,導緻deadlock。

對于這種情況,可能的解決方法就是:将表的順序改為一緻,或者拆分更小的事務,避免較差更新的情況。

另外,對于批量更新,和上面一個事務中多個表操作的原理相同,并發大則也會導緻deadlock。要麼減少并發,要麼不用批量更新。其實出現deadlock,此時報錯的SQL會自動執行rollback,但注意這裡是語句級rollback,即隻會rollback出錯的SQL,之前的SQL不會rollback,是以上述第一個例子中Session2中的SQL報錯,但Session1中的第二條SQL仍舊處于hang狀态,除非Session2中對應的資源釋放。