Oracle鎖的基本機制

来源:http://www.cnblogs.com/yzyi/archive/2017/07/13/7158732.html
-Advertisement-
Play Games

1.什麼是鎖 鎖(LOCK)用於管理對共用資源的併發控制。通過建立鎖,可以保護資源(數據)的完整性和一致性。 通過一個經典的資料庫問題(丟失更新)就可以看到鎖的意義: 1)針對同一個資料庫,有表 Student,表結構如下: ID、姓名、年齡 2)用戶A登錄到資料庫中,查詢Student表的數據,此 ...


1.什麼是鎖

  鎖(LOCK)用於管理對共用資源的併發控制。通過建立鎖,可以保護資源(數據)的完整性和一致性。

  通過一個經典的資料庫問題(丟失更新)就可以看到鎖的意義:

  1)針對同一個資料庫,有表 Student,表結構如下: ID、姓名、年齡

  2)用戶A登錄到資料庫中,查詢Student表的數據,此時標記A的會話為Session1

  3)用戶B登錄到資料庫中,查詢Student表的數據,此時標記B的會話為session2

  4)用戶A將Student表中姓名為張三的學生姓名修改為李四,並提交

  5)用戶B將Student表中姓名為張三的學生的年齡修改為18,並提交

  當B提交數據時,他看到的數據是最初提取出來的數據,並做出修改,此時資料庫中會存在一條姓名為張三年齡為18的記錄。但是在操作4中,用戶A明明將張三的姓名修改為了李四,這樣明顯可以看出,用戶A做的修改並沒用生效,這種情況稱之為丟失更新。雖然整個過程僅僅涉及了Select和Update簡單的操作,但產生的問題是很明顯的。為此,我們應該對數據共用進行一定的保護,也就引入了鎖機制。

2.鎖機制

 悲觀鎖定

  悲觀鎖定就如同他的名字一樣,資料庫“悲觀”地認為併發情況下準備修改的數據隨時有可能已經被他人修改。因此在用戶獲取某些數據並有意做出修改時,資料庫就對這些數據加上鎖,並一直將鎖保持至用戶提交或回滾當前事務,在此期間其他用戶不能對這些數據或數據結構做出修改。正是因為悲觀鎖定的這種特性,用戶必須要保持與資料庫的有效的連接狀態,而且至少在事務生存期中只有一個用戶。一般來說悲觀鎖定對數據的一致性管理是較為有效的,但是其缺點也較為明顯:當併發量較大時,很容易造成阻塞,同時在一些特定的應用環境下,如Web應用,因為很難保證事務生存期中只有一個用戶,當多個用戶進入這個連接,那麼鎖的作用就會失效。

 樂觀鎖定

  與悲觀鎖定不同,資料庫“樂觀”地認為併發情況下準備被修改的數據不會被他人修改,直到最後做提交修改時才加鎖並驗證數據是否正確。樂觀鎖定事務開始於最終提交修改,因此對連接的要求幾乎沒有。但是因為在事務開始前,有可能修改的數據已經被他人修改過,此時會回滾當前的事務,用戶做的修改將會失敗。採用樂觀鎖定的要求比悲觀鎖定要低很多,並且阻塞的時間也非常的短。但因為有可能事務被回退,就需要為此做其他的彌補措施。

 阻塞

  阻塞發生在用戶之間對資源的控制權爭奪中,如果一個用戶A已經對某個數據持有了鎖,另一個用戶B又請求獲取這個數據的控制權,那麼就會產生阻塞。在此期間,用戶B的操作會被擱置, 直到用戶A提交或回滾當前事務,用戶B才能獲取到數據的控制權。

 死鎖

  死鎖同樣發生在資源的控制權爭奪中,但是與阻塞最大的區別是:

  阻塞是由於資源不足引起的排隊等待現象。
  死鎖是由於兩個對象在擁有一份資源的情況下申請另一份資源,而另一份資源恰好又是這兩對象正持有的,導致兩對象無法完成操作,且所持資源無法釋放。

 

  下麵通過一個簡單的例子介紹死鎖產生的一個原因:

  1)資料庫中存在A、B兩表,且兩表都只有一條數據

  2)用戶A進入資料庫,此時標記A的會話為Session1

  3)用戶B進入資料庫,此時標記B的會話為Session2

  4)用戶A修改A表的數據,用戶B修改B表的數據

  5)用戶A再修改B表的數據,用戶B再修改A表的數據

  進行到操作5時,將產生死鎖現象。用戶A在等待用戶B釋放對A表數據的控制權,而用戶B又在等待用戶A釋放對B表數據的控制權,這就引發了死鎖的現象。

  需要註意的是,Oracle資料庫本身幾乎不會發生死鎖現象,一旦你的應用中出現了死鎖的問題,那麼一般是設計上存在Bug(如外鍵中沒有創建索引等)。

 

  因為外鍵上沒有創建索引導致死鎖問題

  大部分的死鎖問題都是由外鍵上沒有索引導致,下麵通過一個簡單的案例進行說明。

  1.創建兩個簡單的表並插入數據

create table 父表(id VARCHAR2(2) Primary Key);
create table 子表(子id VARCHAR2(2) ,父id VARCHAR2(2) References 父表(id));

Insert into 父表  values(1); 
Insert into 父表 values(2);
Insert into 父表 values(3); insert into 子表 values(1,1);
insert into 子表 values(2,1);
insert into 子表 values(3,1); insert into 子表 values(4,2);
insert into 子表 values(5,2);
insert into 子表 values(5,3);

  2.會話1嘗試修改子表數據

update 子表 set 子id=10 where 子id = 1

  3.會話2刪除一條父表數據

delete from  父表 where id=2;

  4.查看鎖類型  

1 Select b.Object_Name, a.Session_Id,
2        Decode(a.Locked_Mode, 0, 'None', 1, 'Null', 2, 'Row-S (SS)', 3, 'Row-X (SX)', 4, 'Share', 5, 'S/Row-X (SSX)', 6,
3                'Exclusive', To_Char(a.Locked_Mode)) Lock_Type
4 From V$locked_Object A, Dba_Objects B
5 Where b.Object_Id = a.Object_Id

  結果如下:

      

  5.查看執行語句的sid

1 select UserENV('sid') sid from dual

--查詢結果:執行修改子表操作會話1的Sid=11,執行刪除父表數據操作的會話2的Sid=199

 

  

  通過實驗即使子表修改的數據和父表刪除的數據沒有關聯,但是仍產生了死鎖。

  原因如下:修改子表數據時,會對子表申請一個Row-X鎖(行級排他鎖),此時刪除父表數據,因為沒有索引,為了檢測是否有關聯數據,會請求子表的一個全表排它鎖,而此時,子表事務未提交,存在一個行級排它鎖,阻止了全表排它鎖的獲取,造成了死鎖的現象。

  同理,因為沒有索引,每次對父表數據進行操作,一旦同時有其他會話已經獲得了子表的鎖,都會引發死鎖。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近在找工作,面試時很多企業會問到關於資料庫優化的問題,今天在這裡總結一下資料庫優化問題,以MySQL資料庫為例進行講解。 為什麼要優化: 隨著實際項目的啟動,資料庫經過一段時間的運行,最初的資料庫設置,會與實際資料庫運行性能會有一些差異,這時我們 就需要做一個優化調整。 資料庫優化這個課題較大,可 ...
  • 使用動態視圖: sys.dm_os_buffer_descriptors 這個視圖返回一個8K data page的下列屬性: (1)該頁屬於哪個資料庫 (2)該頁屬於資料庫哪個文件 (3)該頁的Page_ID (4)該頁的類型。可以根據這個來判斷此頁時索引頁還是數據頁 (5)該頁內有多少行數據 ( ...
  • ## ##pt-osc之工作流程:1、檢查更改表是否有主鍵或唯一索引,是否有觸發器2、檢查修改表的表結構,創建一個臨時表,在新表上執行ALTER TABLE語句3、在源表上創建三個觸發器分別對於INSERT UPDATE DELETE操作4、從源表拷貝數據到臨時表,在拷貝過程中,對源表的更新操作會寫 ...
  • 1.選取適當的欄位屬性。例如,在定義郵政編碼這個欄位時,如果將其設置為CHAR(255),顯然給資料庫增加了不必要的空間,甚至使用VARCHAR這種類型也是多餘的,因為CHAR(6)就可以很好的完成任務了。或者使用MEDIUMINT來定義整型欄位。 2.應該儘量把欄位設置為NOTNULL。 3.使用 ...
  • 安裝目錄:C:\Program Files\MongoDB\Server\3.2Bin:..\..\Program Files\MongoDB\Server\3.2\bin啟動命令:mongod鏈接命令:mongo 或者 mongo 主機:埠號/資料庫 mongo -nodb 或者mongo XX ...
  • 因為項目第一次接觸postgresql,有個問題搞死我了,如果初學,估計大家也會遇見這樣的問題,希望可以節約時間。 用戶postgres的口令不顯示啊!服! ...
  • CentOS 6.9 升級MySQL 5.6.36到5.7.18 MySQL 5.6.36 安裝過程:http://www.cnblogs.com/imweihao/p/7156754.html 升級方法很簡單 1、安全關閉資料庫 [root@001 ~]# service mysqld stop ...
  • SELECT request_session_id spid, OBJECT_NAME(resource_associated_entity_id) tableName FROM sys.dm_tran_locksWHERE resource_type = 'OBJECT' KILL spid 如: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...