[oracle],ORACLE鎖詳細介紹,你不知道的真相

Oracle中鎖分為這麼幾種類型(阻塞、一致性讀、當前讀),按照類型分為(排它鎖(X鎖)、共享鎖(S鎖)),按鎖定對象分為(DML鎖、DDL鎖、內存鎖(Latch))

1. DML鎖 又分為兩種:

l TX 鎖:即事務鎖,如果 insert,update,delete,merge

select …..for update ,會對所操作的行加TX鎖,TX鎖是行級別鎖。

l TM鎖:進行DML操作時加在表級對象上的鎖,防止其他對象對錶結構加X類型鎖,分如下級別:

2(RS,row share) 3(RX,row exclusive) 4(S,share)

5(SRX,share row exclusive) 6(X, exclusive)

例如 for update 阻塞 X 類型的DDL語句

Session 1: select * from test where a=100 for update;

Session 2: truncate table test;

會報如下錯誤:ORA—00054:resource busy and acquire with NOWAIT specified

注意:在一個session 中,TX鎖一般只會有一個,因為只有一個事務,而TM鎖可以有多個,因為在一個會話中,可能更新多張表。

2. DDL 鎖主要分兩類:

l X 類型DDL :多發生在 truncate,drop,alter table drop/add/modify

等絕大部分DDL上,操作期間會給表加X類型TM鎖。

l S類型DDL:如online操作,會在表上加一個RS(2級)類型的TM鎖,因為RS類型鎖可以在加RX(3級)鎖,所以 online 操作不阻塞 DML語句。

例:創建索引和online創建索引的差別

l 當執行下列SQL: create index idx_test1 on test(object_id);

創建索引時在 test 上會加級別為 4的 S鎖,會阻塞級別為3的RX鎖所以創建索引時不能正常DML,因為DML要加RX鎖。

l 執行下列SQL: create index idx_test1 on test(object_id) online;

如果添加 online ,在test上面會加最低級別(2級)的RS鎖,這個類型的TM鎖允許加更高級別的RX鎖,所以online操作時可以執行DML。

3. 內存鎖:

也叫 latch ,是一個運行在內存中,保護內存結構的輕量級鎖,latch資源很寶貴,如果處理不好,將浪費很大的cpu來管理內存鎖,比較典型的就是硬解析。

4. Oracle阻塞分三類: TX 阻塞, TM阻塞, Latch 阻塞

l TX 阻塞:行級阻塞,比如一個會話對一行加了TX鎖,另外會話在對這個行加TX鎖時失敗,於是產生了阻塞。

l 行級別的等待與TX鎖都不太耗費資源,事務記錄在數據塊的事務槽內(ITL)。

l TM阻塞:表級鎖 ,下面用 lock模擬一下表創建索引的情況。

Session 1: SQL> lock table test in share mode;

Session 2: SQL> update test set b=100 where a=5;

當 session2 執行update時發生阻塞, 當執行update時加 TX鎖之前,加TM鎖(update應該加 級別為 3的RX類型鎖)加不上,導致等待,因為 session1已經添加了更高級別4(S)級的TM鎖

除了 TX 和 TM阻塞外,latch 也會發生阻塞,並且可以阻塞 select 語句。

例:在一個大表上創建約束,oracle 自動創建索引,從而導致表屬性變化,如果創建索引時間很長將導致 select 阻塞在 library cache lock 上,不能獲得句柄(handle)信息,從而不能分析語句。

所以證明並不是所有oracle 操作都是不阻塞的,大數據量高併發環境在線維護應儘量避免鎖和阻塞。

5. 併發控制(一致性讀)

l 讀已提交(read commited) 和一致性讀(serializable read)

l 例如:

T1 session 1:update test set b=100 where a=‘tom’; not commit;

T2 session 2:select * from test; 看不到 session1 修改的數據

T3 session 1:commit;

T4 session2:

還在執行 select,儘管session1 在T3已經提交,但是查詢出的還是沒修改前的數據,這個叫做 “一致性讀”(oracle 支持)。如果能看到提交後的結果叫做 “讀已提交”。

l 一致性讀原理:oracle 會根據undo重構以前的一致性塊,如果select時間太長undo的數據被覆蓋,或者undo事務表被覆蓋,導致無法重構一致性塊,返回 ORA-01555錯誤。

l 例如:假設 dept只有一條記錄

session 1: select * from dept; logical reads 為 1

session 2:循環 update dept set loc=‘abc’ where deptno=40;修改1000次後不提交

session 1:select * from dept; logical reads 為 1008

這裡發生的 consistent gets 其實是發生在一個數據塊上的,只不過是被rollback多次,重複讀了多次。

6. 併發控制(當前讀)

l 當前讀,只在DML的時候產生,當修改數據時,完成當前最新數據的獲取並在最新的數據上更新,oracle 必須保證更新的連續性。

l 例如:表 test中只有一列,一行數據

session 1:

SQL> select * from test 結果為 1000

SQL> update test set a=a+1 where a=1000 not commit

session 2:

SQL> update test set a=a+1 where a=1000 操作被阻塞

session 1:

SQL> commit; 執行後看到 session 2也更新成功

最後的更新結果為 1001

7. 併發控制

l 悲觀鎖:在更新數據之前會把數據先鎖定,例如:

SQL> select * from test where id=100 for update nowait; 更新行加 RX鎖

SQL> update test set status=‘Y’ where id=100;

SQL> commit;

l 樂觀鎖:利用 oracle 當前讀的 特性,在更新數據時,不是跟 select 一樣發生一致性讀,而是當前讀。例如:

SQL> update test set status=‘Y’ where id=100 and status=‘Y’;

(Tx)


分享到:


相關文章: