【鎖機制】共享鎖、排它鎖、悲觀鎖、樂觀鎖、死鎖等等
鎖是防止在兩個事務操作同一個資料來源(表或行)時互動破壞資料的一種機制。Oracle採用封鎖技術保證併發操作的可序列性。Oracle的鎖分為兩大類:資料鎖(也稱DML鎖)和字典鎖。字典鎖是Oracle DBMS內部用於對字典表的封鎖。字典鎖包括語法分析鎖和DDL鎖,由DBMS在必要的時候自動加鎖和釋放鎖,使用者無機控制。
Oracle主要提供了5種資料鎖:共享鎖(Share Table
Lock,簡稱S鎖)、排它鎖(Exclusive Table Lock,簡稱X鎖)、行級鎖(Row Share Table
Lock,簡稱RS鎖)、行級排它鎖(Row Exclusive Table Lock,簡稱RX鎖)和共享行級排它鎖(Share Row
Exclusive Table Lock,簡稱SRX鎖)。其封鎖粒度包括行級和表級。
按照型別劃分,鎖可分為行級排他鎖和表級共享鎖及死鎖。按照物件劃分,鎖可分為事務鎖,DML鎖,DDL鎖,記憶體鎖(Latch)。
鎖相關測試
1.1. 更新丟失
1) 建立測試表
SYS@ORA11GR2>create table t_lock as select rownum as id,0 as type from dual connect by rownum <=3;
Table created.
SYS@ORA11GR2>select * from t_lock;
ID TYPE
---------- ----------
1 0
2 0
3 0
2) 會話1:查詢type為0的最小id
SYS@ORA11GR2>set time on;
18:58:22 SYS@ORA11GR2>
18:58:23 SYS@ORA11GR2>select min(id) from t_lock where type=0;
MIN(ID)
----------
1
3) 會話2:查詢type為0的最小id
SYS@ORA11GR2>set time on
18:59:31 SYS@ORA11GR2>select min(id) from t_lock where type=0;
MIN(ID)
----------
1
4) 會話1:將ID為1的這條記錄的type置為1
19:00:53 SYS@ORA11GR2>update t_lock set type=1 where id=1;
1 row updated.
19:01:21 SYS@ORA11GR2>commit;
Commit complete.
19:01:37 SYS@ORA11GR2>select * from t_lock;
ID TYPE
---------- ----------
1 1
2 0
3 0
5) 會話2:將ID為1的這條記錄的type置為2
19:02:47 SYS@ORA11GR2>update t_lock set type=2 where id=1;
1 row updated.
19:03:11 SYS@ORA11GR2>commit;
Commit complete.
19:03:17 SYS@ORA11GR2>select * from t_lock;
ID TYPE
---------- ----------
1 2
2 0
3 0
19:03:32 SYS@ORA11GR2>
6) 小結:
我們看到id為1的type現在的值為2,會話1將type更新為1的記錄已經“丟失”
1.2. 悲觀鎖
1) 會話1:查詢id為2的記錄並進行鎖定
19:05:43 SYS@ORA11GR2>select * from t_lock where id=2 and type =0 for update nowait;
ID TYPE
---------- ----------
2 0
2) 會話2:查詢id為2的記錄,此時查詢報錯
19:07:43 SYS@ORA11GR2>select * from t_lock where id=2 and type=0 for update nowait;
select * from t_lock where id=2 and type=0 for update nowait
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
3) 會話1:對id為2的記錄進行更新。
19:19:08 SYS@ORA11GR2>update t_lock set type=1 where id=2 and type=0;
1 row updated.
19:19:30 SYS@ORA11GR2>commit;
Commit complete.
19:19:39 SYS@ORA11GR2>select * from t_lock where id=2;
ID TYPE
---------- ----------
2 1
4) 會話2:查詢id為2的記錄,由於已經將id為2的type已經變為1,所以查不到資料了。
19:19:15 SYS@ORA11GR2>select * from t_lock where id=2 and type=0 for update nowait;
no rows selected
1.3樂觀鎖
1) 會話1:查詢id為3的偽列ora_rowscn的值
19:22:00 SYS@ORA11GR2>select id,type,ora_rowscn from t_lock where id = 3;
ID TYPE ORA_ROWSCN
---------- ---------- ----------
3 0 1246809
2) 會話2:查詢id為3的偽列ora_rowscn的值
19:23:01 SYS@ORA11GR2>select id,type,ora_rowscn from t_lock where id = 3;
ID TYPE ORA_ROWSCN
---------- ---------- ----------
3 0 1246809
3) 會話1:更新id為3的type為1
19:24:22 SYS@ORA11GR2>update t_lock set type=1 where ora_rowscn=1246809 and id = 3;
1 row updated.
19:25:29 SYS@ORA11GR2>commit;
Commit complete.
驗證:
19:28:22 SYS@ORA11GR2>select id,type,ora_rowscn from t_lock where id = 3;
ID TYPE ORA_ROWSCN
---------- ---------- ----------
3 1 1247164
4) 會話2:更新id為3的type為1
19:26:05 SYS@ORA11GR2>update t_lock set type=1 where ora_rowscn=1246809 and id =3;
0 rows updated.
驗證:
19:29:37 SYS@ORA11GR2>select id,type,ora_rowscn from t_lock where id = 3;
ID TYPE ORA_ROWSCN
---------- ---------- ----------
3 1 1247164
(因為會話1的事務更改了id=3的值,而且事務已經提交,事務的ora_rowscn已經變為1247164,原來的ora_rowscn=1246809已經不存在,所以沒有可更改的行了)
1.4死鎖
1) 建立測試表
19:35:46 SYS@ORA11GR2>create table t_lock_1 (id number(2),name varchar2(15));
Table created.
19:35:57 SYS@ORA11GR2>create table t_lock_2 as select * from t_lock_1;
Table created.
19:36:24 SYS@ORA11GR2>insert into t_lock_1 values(1,'liubei');
1 row created.
19:37:11 SYS@ORA11GR2>insert into t_lock_2 values (1,'guanyu');
1 row created.
19:37:38 SYS@ORA11GR2>commit;
Commit complete.
19:37:43 SYS@ORA11GR2>select * from t_lock_1;
ID NAME
---------- ---------------
1 liubei
19:38:01 SYS@ORA11GR2>select * from t_lock_2;
ID NAME
---------- ---------------
1 guanyu
2) 會話1:更新表t_lock_1的id欄位為1的name為“liuxuande”,不提交
19:39:55 SYS@ORA11GR2>update t_lock_1 set name='liuxuande' where id =1;
1 row updated.
3) 會話2:更新表t_lock_2的id欄位為1的name為“關雲長”,不提交
19:39:47 SYS@ORA11GR2>update t_lock_2 set name='guanyunchang' where id = 1;
1 row updated.
4) 會話1:更新表t_lock_2的id欄位為1的name為“guanyunchang”,此時掛起狀態
19:40:30 SYS@ORA11GR2>update t_lock_2 set name='guanyunchang' where id =1;
5) 會話2:更新表t_lock_1的id欄位為1的name為“liuxuande”,此時掛起狀態
19:44:14 SYS@ORA11GR2>update t_lock_1 set name='liuxuande' where id =1;
6) 會話1:此時回到會話1,出現死鎖錯誤
19:40:30 SYS@ORA11GR2>update t_lock_2 set name='guanyunchang' where id =1;
update t_lock_2 set name='guanyunchang' where id =1
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
會話1處於死鎖狀態,而會話2處於掛起狀態;
總結:悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿資料的時候都認為別人不會修改,所以不會上鎖。
樂觀鎖適用於寫比較少的情況下,即衝突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。但如果經常產生衝突,上層應用會不斷的進行retry,這樣反倒是降低了效能,所以這種情況下用悲觀鎖就比較合適。
定義:當兩個使用者希望持有對方的資源時就會發生死鎖.
即兩個使用者互相等待對方釋放資源時,oracle認定為產生了死鎖,在這種情況下,將以犧牲一個使用者作為代價,另一個使用者繼續執行,犧牲的使用者的事務將回滾.
起因:Oracle的死鎖問題實際上很少見,如果發生,基本上都是不正確的程式設計造成的,經過調整後,基本上都會避免死鎖的發生。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31397003/viewspace-2126924/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL/InnoDB中,樂觀鎖、悲觀鎖、共享鎖、排它鎖、行鎖、表鎖、死鎖概念的理解MySql
- MySQL鎖(樂觀鎖、悲觀鎖、多粒度鎖)MySql
- 悲觀鎖和樂觀鎖
- Java鎖最全詳解:樂觀鎖/悲觀鎖+公平鎖/非公平鎖+獨享鎖/共享鎖Java
- MySQL鎖(讀鎖、共享鎖、寫鎖、S鎖、排它鎖、獨佔鎖、X鎖、表鎖、意向鎖、自增鎖、MDL鎖、RL鎖、GL鎖、NKL鎖、插入意向鎖、間隙鎖、頁鎖、悲觀鎖、樂觀鎖、隱式鎖、顯示鎖、全域性鎖、死鎖)MySql
- laravel樂觀鎖和悲觀鎖Laravel
- mysql悲觀鎖以樂觀鎖MySql
- [轉帖]SQL Server 鎖機制 悲觀鎖 樂觀鎖 實測解析SQLServer
- Java中的鎖之樂觀鎖與悲觀鎖Java
- java-樂觀鎖與悲觀鎖Java
- MybatisPlus - [03] 樂觀鎖&悲觀鎖MyBatis
- MySQL樂觀鎖和悲觀鎖介紹MySql
- 面試必備之悲觀鎖與樂觀鎖面試
- Redis的事務、樂觀鎖和悲觀鎖Redis
- MySQL 悲觀鎖與樂觀鎖的詳解MySql
- 面試必備之樂觀鎖與悲觀鎖面試
- Java彌散系列 - 樂觀鎖與悲觀鎖Java
- SQLServer樂觀鎖定和悲觀鎖定例項SQLServer
- Java併發程式設計(05):悲觀鎖和樂觀鎖機制Java程式設計
- 自旋鎖、阻塞鎖、可重入鎖、悲觀鎖、樂觀鎖、讀寫鎖、偏向所、輕量級鎖、重量級鎖、鎖膨脹、物件鎖和類鎖物件
- 樂觀鎖與悲觀鎖及應用舉例
- 資料庫中的悲觀鎖和樂觀鎖資料庫
- JPA和Hibernate的樂觀鎖與悲觀鎖
- 利用MySQL中的樂觀鎖和悲觀鎖實現分散式鎖MySql分散式
- Java鎖?分散式鎖?樂觀鎖?行鎖?Java分散式
- 面試官:你說說互斥鎖、自旋鎖、讀寫鎖、悲觀鎖、樂觀鎖的應用場景面試
- Java 中15種鎖的介紹:公平鎖,可重入鎖,獨享鎖,互斥鎖,樂觀鎖,分段鎖,自旋鎖等等Java
- Java 中的悲觀鎖和樂觀鎖的實現Java
- 悲觀鎖與樂觀鎖的實現(詳情圖解)圖解
- 【每日鮮蘑】從資料庫看樂觀鎖、悲觀鎖資料庫
- 面試必備的資料庫悲觀鎖與樂觀鎖面試資料庫
- 小議“悲觀鎖和樂觀鎖”的原理、場景、示例
- 關於樂觀鎖與悲觀鎖的實際應用
- SSM (十五) 樂觀鎖與悲觀鎖的實際應用SSM
- 樂觀鎖和悲觀鎖策略的區別與實現
- SQL SERVER樂觀鎖定和悲觀鎖定使用例項SQLServer
- 解鎖你的資料庫:JPA和Hibernate的樂觀鎖與悲觀鎖資料庫
- 樂觀鎖和悲觀鎖在kubernetes中的應用