Oracle瑣
2024-08-29 13:39:40
供稿:網友
預備知識:
DDL(DATABASE DEFINITION LANGUAGE):數據庫定義語言,如create table、drop table.....
DML(DATABASE MODIFICATION LANGUAGE):數據庫修改語言,如insert、delete、update......
參考資料:Oracle8 Administrator's Guide, Release 8.0
Oracle8 Tuning, Release 8.0
ORACLE鎖具體分為以下幾類:
1.按用戶與系統劃分,可以分為自動鎖與顯示鎖
自動鎖:當進行一項數據庫操作時,缺省情況下,系統自動為此數據庫操作獲得所有有必要的鎖。
顯示鎖:某些情況下,需要用戶顯示的鎖定數據庫操作要用到的數據,才能使數據庫操作執行得更好,顯示鎖是用戶為數據庫對象設定的。
2.按鎖級別劃分,可分為共享鎖與排它鎖
共享鎖:共享鎖使一個事務對特定數據庫資源進行共享訪問——另一事務也可對此資源進行訪問或獲得相同共享鎖。共享鎖為事務提供高并發性,但如拙劣的事務設計+共享鎖輕易造成死鎖或數據更新丟失。
排它鎖:事務設置排它鎖后,該事務單獨獲得此資源,另一事務不能在此事務提交之前獲得相同對象的共享鎖或排它鎖。
3.按操作劃分,可分為DML鎖、DDL鎖
+DML鎖又可以分為,行鎖、表鎖、死鎖
-行鎖:當事務執行數據庫插入、更新、刪除操作時,該事務自動獲得操作 表中操作行的排它鎖。
-表級鎖:當事務獲得行鎖后,此事務也將自動獲得該行的表鎖(共享鎖),以 防止其它事務進行DDL語句影響記錄行的更新。事務也可以在進行 過程中獲得共享鎖或排它鎖,只有當事務顯示使用LOCK TABLE語 句顯示的定義一個排它鎖時,事務才會獲得表上的排它鎖,也可使用
LOCK TABLE顯示的定義一個表級的共享鎖(LOCK TABLE具體用法請參 考相關文檔)。
-死鎖:當兩個事務需要一組有沖突的鎖,而不能將事務繼續下去的話,就 出現死鎖。
如事務1在表A行記錄#3中有一排它鎖,并等待事務2在表A中記錄#4 中排它鎖的釋放,而事務2在表A記錄行#4中有一排它鎖,并等待事務 1在表A中記錄#3中排它鎖的釋放,事務1與事務2彼此等待,因此就造 成了死鎖。死鎖一般是因拙劣的事務設計而產生。
死鎖只能使用SQL下:alter system kill session 'sid,serial#';
或者使用相關操作系統kill進程的命令,如UNIX下kill -9 sid,或者 使用其它工具殺掉死鎖進程。
+DDL鎖又可以分為:排它DDL鎖、共享DDL鎖、分析鎖-排它DDL鎖:創建、修改、刪除一個數據庫對象的DDL語句獲得操作對象的 排它鎖。
如使用alter table語句時,為了維護數據的完成性、一致性、
合法性,該事務獲得一排它DDL鎖。
-共享DDL鎖:需在數據庫對象之間建立相互依靠關系的DDL語句通常需共享獲得DDL鎖。
如創建一個包,該包中的過程與函數引用了不同的數據庫表,當編譯此包時,該事務就獲得了引用表的共享DDL鎖。
-分析鎖:ORACLE使用共享池存儲分析與優化過的SQL語句及PL/SQL程序,使運行相同語句的應用速度更快。一個在共享池中緩存的對象獲得
它所引用數據庫對象的分析鎖。分析鎖是一種獨特的DDL鎖類型,
ORACLE使用它追蹤共享池對象及它所引用數據庫對象之間的依靠 關系。當一個事務修改或刪除了共享池持有分析鎖的數據庫對象
時,ORACLE使共享池中的對象作廢,下次在引用這條SQL/PLSQL語 句時,ORACLE重新分析編譯此語句。
4.內部閂鎖
內部閂鎖:這是ORACLE中的一種非凡鎖,用于順序訪問內部系統結構。
當事務需向緩沖區寫入信息時,為了使用此塊內存區域, ORACLE首先必須取得這塊內存區域的閂鎖,才能向此塊內存寫入
信息。
以上是 本人對ORACLE鎖的一些總結,不足之處還望大家海涵,同時也希望大家多提出自己對ORACLE鎖的一些看法。
好文章!
更正一點:
真正的死鎖,包括相互死鎖及循環死鎖,oracle會自動監測到,并使得最后申請鎖的請求失敗。
只有非正常終止的session所申請的鎖(我們平時經常講的死鎖實際上值的就是這種類型),才需要手工kill.
第二部分
tonnyluo
(newbie)
12/28/00 11:36 AM
Re: ORACLE技術專題4 ORACLE瑣 [re: oldwain]
非正常終止的session,ORACLE會自動回滾其事物(前提是該事物已終止)。包括相互死鎖及循環死鎖ORACLE雖會處理,但好象這方面ORACLE處理不是很好,常需自己動手解決掉造成死鎖的進程。
網上飄
easyfree
(journeyman)
12/28/00 01:14 PM
Re: ORACLE技術專題4 ORACLE瑣 [re: tonnyluo]
是否可以介紹一下如何定位死鎖的SID,在應用過程中,同樣操作的client很多,往往是一臺機器造成死鎖后,從v$session中看到的terminal都是一樣的(比如:Windows PC),無法分清,那么這時候怎樣確定呢?
一沙一世界
一水一天堂
oldwain
(member)
12/28/00 01:26 PM
Re: ORACLE技術專題4 ORACLE瑣 [re: tonnyluo]
tonnyluo:
我作過試驗, 在網絡斷掉(通過拔掉網線)或非正常終止進程(通過task manager強行關閉sql*plus)時,oracle在有限的時間內(我只觀查了5-10分)內,oracle未能對該進程作任何處理。
但是, 假如是相互死鎖或循環死鎖,oracle會即時檢測到,并立即使該進程失敗。
以下為相互死鎖時的情形:
[SQL*PLUS (1)]
SQL> SELECT * FROM TEST FOR UPDATE;
C1 C2
--------- ------------------------------
1 中文
[SQL*PLUS (2)]
SQL> SELECT * FROM TEMP FOR UPDATE;
KIND S EMAIL
--------- - ------------------------------
1 a asd
[SQL*PLUS (1)]
SQL> SELECT * FROM TEMP FOR UPDATE;
[... 處于等待狀態]
[SQL*PLUS (2)]
SQL> SELECT * FROM TEST FOR UPDATE;
[... 處于等待狀態]
[此時SQL*PLUS (1)退出等待狀態,且產生以下錯誤]
SQL> SELECT * FROM TEMP FOR UPDATE;
SELECT * FROM TEMP FOR UPDATE
*
ERROR 位于第1行:
ORA-00060: 等待資源時檢測到死鎖
---------
半瓶醋 -- 比空瓶多一點, 比滿瓶少一點......
easyfree
(journeyman)
12/28/00 02:04 PM
Re: ORACLE技術專題4 ORACLE瑣 [re: oldwain]
我也一直對ORACLE自動處理所謂死鎖的時間間隔感到迷惑:一是這個時間間隔是可以設定的么?二是如何確定這樣的SESSION呢?
oldwain:
能否給我介紹一下我上面一個帖子涉及的問題,象你這樣兩個client端使用SQLPLUS發生互鎖或死鎖時,如何確定kill哪個session呢?
一沙一世界
一水一天堂
oldwain
(member)
12/28/00 02:33 PM
Re: ORACLE技術專題4 ORACLE瑣 [re: easyfree]
正如上面的實驗,互鎖或死鎖時,ORACLE已經解除了這種鎖,所以只要等待某一占有資源的進程打開鎖(通過ROLLBACK/COMMIT)即可。
對于非正常終止進程占有的鎖,把握以前在內部網站上法的一片貼子轉貼在下面:
鎖等待的診斷及排除
=====================================
在ORACLE中,為了保證數據的一致性,在對數據庫中的數據進行操作時,系統會進行對數據相應的鎖定。
當程序對所做的修改進行提交(commit)或回滾后(rollback)后,鎖住的資源便會得到釋放,從而答應其它用戶進行操作。
但是,有時,由于程序中的原因,鎖住資源后長時間未對其工作進行提交;或是由于用戶的原因,如調出需要修改的數據后,未及時修改并提交,而是放置于一旁;或是由于客戶服務器方式中客戶端出現"死機",而服務器端卻并未檢測到,從而造成鎖定的資源未被及時釋放,影響到其它用戶的操作。
這時,我們需要迅速地診斷出鎖住資源的用戶并解決其鎖定。
1. 診斷系統中的鎖
為了找出系統中那些用戶鎖住資源以及那些用戶在等待相應的資源,可使用以下語句(其中的/*+ NO_MERGE(..) */千萬不可省略, 否則會很慢):
-- looklock.sql
-- use the NO_MERGE hints can speed up the query
select /*+ NO_MERGE(a) NO_MERGE(b) NO_MERGE(c) */ 'Wait' "Status", a.username, a.machine, a.sid, a.serial#, a.last_call_et "Seconds", b.id1, c.sql_text "SQL"
from v$session a, v$lock b, v$sqltext c
where a.username is not null
and a.lockwait = b.kaddr
and c.hash_value =a.sql_hash_value
union
select /*+ NO_MERGE(a) NO_MERGE(b) NO_MERGE(c) */ 'Lock' "Status", a.username, a.machine, a.sid, a.serial#, a.last_call_et "Seconds", b.id1, c.sql_text "SQL"
from v$session a, v$lock b, v$sqltext c
where b.id1 in
(select /*+ NO_MERGE(d) NO_MERGE(e) */ distinct e.id1
from v$session d, v$lock e
where d.lockwait = e.kaddr)
and a.username is not null
and a.sid = b.sid
and b.request=0
and c.hash_ right">(出處:清風軟件下載學院)