在Oracle數(shù)據(jù)庫(kù)管理中,經(jīng)常會(huì)遇到ORA-00098錯(cuò)誤,該錯(cuò)誤通常是由于死鎖造成的。
死鎖是指兩個(gè)或多個(gè)事務(wù)同時(shí)鎖定資源,并且彼此等待對(duì)方釋放鎖引起的問(wèn)題。因此,Oracle數(shù)據(jù)庫(kù)發(fā)現(xiàn)死鎖并自動(dòng)終止其中一個(gè)事務(wù)以便釋放資源,這時(shí)就會(huì)出現(xiàn)ORA-00098錯(cuò)誤。以下是具體的幾種引起該錯(cuò)誤的情況:
鎖定模式:共享鎖 / 獨(dú)占鎖 鎖定對(duì)象:表 / 索引 / 表空間 / 等待事件 錯(cuò)誤類型:死鎖 / 重復(fù)加鎖
在實(shí)際的操作中,ORA-00098錯(cuò)誤常常在以下情況中出現(xiàn):
情況一:多個(gè)Session同時(shí)訪問(wèn)一張表
SQL>SELECT * FROM emp WHERE deptno = 10 FOR UPDATE; -- Session A SQL>UPDATE emp SET sal = sal + 1000 WHERE deptno = 10; -- Session B(等待Session A的共享鎖釋放,因?yàn)樗加昧舜藭r(shí)Session B需要的鎖) ORA-00098: 死鎖檢測(cè)到的死鎖,某個(gè)線程已經(jīng)被掛起
情況二:制表過(guò)程中并發(fā)調(diào)用
SQL>CREATE TABLE student (id NUMBER(8), name VARCHAR2(20)); -- Session A SQL>ALTER TABLE student ADD (age NUMBER(3)); -- Session B(等待Session A釋放表上的共享鎖,因?yàn)榇藭r(shí)它需要的是表空間上的獨(dú)占鎖) ORA-00098: 死鎖檢測(cè)到的死鎖,某個(gè)線程已經(jīng)被掛起
情況三:DDL語(yǔ)句并發(fā)執(zhí)行
SQL>CREATE TABLE student (id NUMBER(8), name VARCHAR2(20)); -- Session A SQL>DROP TABLE student; -- Session B(等待Session A釋放表上的鎖,因?yàn)榇藭r(shí)它需要的是表空間上的鎖) ORA-00098: 死鎖檢測(cè)到的死鎖,某個(gè)線程已經(jīng)被掛起
以上三種情況是最為常見(jiàn)的ORA-00098錯(cuò)誤的情況,解決方式也較為簡(jiǎn)單,如下所示:
情況一的解決方式:
-- 只需根據(jù)情況進(jìn)行不同的數(shù)據(jù)操作順序即可,例如: SQL>UPDATE emp SET sal = sal + 1000 WHERE deptno = 10; SQL>COMMIT; SQL>SELECT * FROM emp WHERE deptno = 10 FOR UPDATE;
情況二和情況三的解決方式:
-- 解決方法為:等待上一個(gè)操作完成或者手工殺掉鎖持有進(jìn)程(此方法不夠安全,需謹(jǐn)慎使用),例如: SQL>ALTER TABLE student ADD (age NUMBER(3)); -- 完成后再執(zhí)行下面的操作 SQL>DROP TABLE student;
總的來(lái)說(shuō),ORA-00098是老生常談的錯(cuò)誤之一,實(shí)際應(yīng)用中經(jīng)常會(huì)遇到。我們需要根據(jù)報(bào)錯(cuò)信息分析原因,然后針對(duì)不同情況采取不同的解決措施。千萬(wàn)不要因?yàn)檫@個(gè)錯(cuò)誤而輕易放棄操作,否則將會(huì)對(duì)業(yè)務(wù)產(chǎn)生嚴(yán)重影響。