《oracle的鎖》
在數據庫中必須要了解的幾點:
1、事務是數據庫的核心,他們是好東西
2、應該延遲到適當的時刻才提交。不要太快提交,以避免對系統帶來壓力,這是因為,即使事務很長或很大,也一般不會對系統造成壓力。相應的原則是: 在必要時才提交,不要提前。事務的大小只應該根據業務邏輯來定。
3、只要需要,就應該盡可能長時間的保持對數據所加的鎖。這些鎖是你能用的工具,而不是讓你退避三舍,鎖并不是什么稀有資源,恰恰相反,只要需要, 你就應該長期的保持數據上的鎖。鎖并不稀少,而且他們可以防止其他會話修改信息;
4、在Oracle中,行級鎖 沒有相關的開銷,一點都沒有。不論有一個行鎖,還是有10000個行鎖,專用于鎖定這個信息的資源數都是一樣的。當然,與修改一 行相比,修改10000行要做的工作肯定多得多,但是鎖住10000行所需的資源數與鎖住一行所需的資源數完全相同,這是一個固定的常量;
5、不要以為鎖升級會對系統更好(例如:使用表鎖而不是行鎖)。在Oracle中,鎖升級對系統沒有任何好處,也不會節省任何資源。有時候我們會使用表 鎖,例如在批處理中,使用表鎖是為了確保在這種情況下你能訪問你的批處理程序所需的所有資源;
6、可以同時得到并發性和一致性。數據讀取器不會被數據寫入器阻塞。數據寫入器也不會被數據讀取器阻塞。這是Oracle與大多數其他關系數據庫之間的根 本區別之一;
一、Oracle鎖的種類:
1.1、悲觀鎖:
這種方式在用戶修改數值之前就已經生效了,例如:用戶打算對他選擇的且在屏幕上可見的某個特定行執行更新(比如通過點擊某個按鈕),該行就會被加上一個鎖,這個行鎖會一直持續應用到應用程序在數據庫中執行用戶的修改并提交的時候;
注意:悲觀鎖僅適用于有狀態或有連接的環境。也就是說你的應用與數據庫直接有一個持續的連接,而且只有你一個人在使用這條連接(至少是在你的事務的生命周期內);
1.2、樂觀鎖:
即把所有鎖定的動作都延遲到即將執行更新之前才進行,換句話說,我們會修改屏幕上的信息而不需要先鎖住他,;(這種鎖方法在所有環境下都可以,但是采用這種方法,更新失敗的可能性就會加大)也就說,用戶要更新他的數據行時,卻發現數據已經被修改過,那他就必須從頭再來;
①:使用版本列的樂觀鎖
這個方法很容易實現,如果你想保護數據庫表不出現丟失更新問題,就在對應的每個表上增加一列,這一列一般是number 或 date/timestamp類型的列,通常通過表上的一個行觸發器來維護。(最佳的方式是通過update語句本身來維護)
②:使用總和檢驗的樂觀鎖
這版本列方法很相似,不過他是基于數據本身來計算得出一個“虛擬”的版本列,為了幫助解釋有關總和檢驗或散列函數的目標和概念;
注意:對大多數應用來說,都建議采用樂觀并發控制,而在樂觀并發控制的方法中,更傾向于使用版本列方法,來增加一個時間戳列(而不只是一個number)
2、阻塞:
數據中有5個常見的DML語句可能會引起阻塞,他們是:insert update delete merge 和 select for update;
對于一個阻塞的seelct for update 解決方案:只需要增加nowait字句,他就不會阻塞了;
2.1、阻塞的insert
insert阻塞的情況不多見,最常見的的情況是:你有一個帶主鍵的表,或者表上有唯一性約束,單有兩個回話試圖用同樣的值插入一行,如果這樣,其中就有一個會話就會被阻塞;
注意:發生insert阻塞通常是因為應用允許最終用戶生成主鍵/唯一列值。為了避免這種情況,最容易的做法就是使用一個序列或sys_guid()內置函數來生成主鍵/唯一列值;
2.2、阻塞的merge update delete
在一個交互式應用中,可以從數據庫查詢數據,允許最終用戶處理這些數據,再把它放回到數據庫中,此時如果發生update或delete阻塞,就說明你的代碼中可能存在一個丟失更新問題;可以通過使用select for update nowait查詢來避免這個問題。這個查詢能做到:驗證自從你查詢數據之后數據未被修改(防止丟失更新);鎖住行(防止update或delete被阻塞)
不論是悲觀鎖還是樂觀鎖都可以利用select for update nowait查詢來驗證行未被修改。悲觀鎖會在用戶有意修改數據那一刻使用這條語句。樂觀鎖則在即將在數據庫中更新數據時使用這條語句。這樣不僅能解決應用中的阻塞問題,還可以修正數據完整性問題;
注意:merge本質上其實就是insert 和 update
3、死鎖
導致死鎖的重要原因就是:外鍵未加索引,第二個原因是表上的位圖索引遭到并發更新
4、Oracle的鎖類型
Oracle主要有3種類型的鎖:
4.1、DML鎖:DML數據操縱語言,一般是指:select insert update merge delete
DML鎖機制允許并發執行數據修改,例如:DML鎖可能是特定數據行上的鎖,或者是鎖定表中所有行的表級鎖;
4.2、DDL鎖:DDL數據定義語言,一般是指:create alter語句
DDL鎖可以保護對象結構定義
注意:內部鎖和閂:Oracle使用這些鎖來保護其內部數據結構。(閂是Oracle采用的一種輕量級的低級串行化設備,功能上類似于鎖)其實,閂是數據庫中導致競爭的一個常見的原因;
5、DML鎖:用于確保一次只有一個人能修改某一行,而且這時別人不能刪除這個表;
①:TX鎖----事務鎖
事務的發動是自動的,TX鎖會被一直持有,直至事務執行提交(commit)或回滾(rollback)。TX鎖被用作一種排隊機制,使得其他回話可以等待這個事務完成;
②:TM鎖----
TM鎖用于確保在修改表的內容時,表的結構不會改變。例如:如果你已經更新了一個表中的行,那同時也會得到這個表的一個TM鎖,這會防止另一個用戶在該表上執行DROP或ALTER命令;
(在Oracle11G R2及更高的版本中,可以設置ddl_lock_timeout當DDL等待)
6、DDL鎖:在DDL操作中會自動為對象加鎖,從而保護這些對象不會被其他會話所修改;
例如,如果我執行一個DDL操作alter table t,通常表T上就會有一個排他DDL鎖,以防止其他會話得到這個表的DDL鎖和TM鎖;
有3鐘類型的DDL鎖:
①:排他DDL鎖:
這會防止其他會話得到它們自己的DDL鎖或TM(DML)鎖,這說明,在DDL操作期間可以查詢一個表,但是無法以任何方式修改這個表;
②:共享DDL鎖:
這些鎖會保護鎖引用的對象的結構,使之不會被其他會話修改,但是允許修改數據;
③:可中斷解析鎖:
這些鎖允許一個對象(如共享池中緩存的一個查詢計劃)向其他對象注冊其依賴性。
7、閂:閂是輕量級的串行設備,用于協調對共享數據結構、對象和文件的多用戶訪問;(閂是一種輕量級的鎖)
8、互斥鎖:是一種與閂非常類似的串行化設備,互斥鎖是數據庫中使用另一種串行化設備;
查看鎖定的對象、用戶名和會話
SQL> select lo.oracle_username,do.object_name,s.logon_time,lo.process,s.sid as session_id from v$locked_object lo,v$session s,dba_objects do where lo.session_id = s.sid and do.object_id = lo.OBJECT_ID;
Oracle的Select For Update語句可以實現在讀取數據后馬上鎖定相關資源,防止被其他session修改數據的目的
手動鎖定:select ... for update語句
select * from table_sfu where a = 1 for update; ----鎖定第一行數據(只有commit后才會解鎖)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。