淺談DML阻塞(上)
從資料庫系統DBMS概念提出開始,並行和序列一直是資料庫系統設計者不斷權衡的一個焦點問題。
1、從串並行到行級鎖
並行化是使DBMS支援多使用者同時訪問資料庫,提高整體效率的關鍵技術手段。不同使用者可以同時向DBMS提交執行資料庫操作語句。但是,一些場景下,對一些資源物件無控制的並行,是會引起一些問題,影響資料庫完整性等一些基本原則。在這種情況下,DBMS勢必會引入序列化機制,來保護特定的物件資源。於是Enqueue(Lock)和Latch等鎖物件就成為保護序列化訪問資源的重要手段。
作為當今企業級DBMS主流的Oracle,其成功很大一部分因素在於早期的系統架構設計和一些關鍵核心技術方案,如redo、行級鎖。這些在當時處在領先的理念技術,奠定了Oracle今天的市場和行業地位。
Oracle是一個典型的行級鎖系統。就是說,當我們進行DML操作的時候,操作會話只會將被操作記錄鎖定住。操作會話是不會阻塞其他會話對該資料表進行的DML操作的。這種機制就大大提升了會話間事務併發的效能。
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 – Production
--實驗資料表
SQL> select * from t;
ID NA
---------- ----------
1 Record 1
2 Record 2
--在session1中
SQL> select sid from v$mystat where rownum<2;
SID
----------
144
SQL> update t set na='dfs' where id=1;
1 row updated
(此時事務並沒有提交……)
--開啟第二個會話
SQL> select sid from v$mystat where rownum<2;
SID
----------
151
SQL> update t set na='df' where id=2;
1 row updated
就普通的DML(insert, update, delete)操作而言,Oracle會加設兩個鎖定機制。首先是資料表級別的TM共享鎖,防止在進行事務操作的時候,出現資料物件的DDL操作,修改資料表結構。同時,對指定的資料行使用一個獨佔的TX鎖定。這樣就保證了在進行DML操作的時候,既可以保證資料完整性要求,又可以最大程度的滿足多會話併發的要求。
那麼,我們在進行普通DML操作的時候,有哪些情況下,兩個會話會出現阻塞情況。筆者總結常見的有如下幾種。
2、常見DML阻塞
ü 修改相同記錄引起的阻塞
顯而易見的情況。如果會話A在對一條記錄進行修改,事務未提交。同時會話B啟動事務要求對相同記錄進行修改。這個時候,會出現阻塞現象。
--會話A
SQL> select sid from v$mystat where rownum<2;
SID
----------
151
SQL> update t set na=null where id=1;
1 row updated
--此時會話B
SQL> select sid from v$mystat where rownum<2;
SID
----------
149
SQL> update t set na='df' where id=1;
(會話Hang住)
此時,如果我們觀察兩個會話的鎖狀態,可以看出問題所在。
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where sid=151 or sid=149 order by sid;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---- ---------- ---------- ---------- ---------- ----------
149 TM 54736 0 3 0 0
149 TX 131080 1251 0 6 0
151 TX 131080 1251 6 0 1
151 TM 54736 0 3 0 0
兩個會話都試圖獲取到資源(131080, 1251)的獨佔權。該表示的是Undo段的地址空間位置,對應的是記錄前映象的儲存。
ü 主鍵列DML變化引起阻塞
主鍵primary key表示的是非空和唯一兩層約束保證。如果我們的DML操作涉及到主鍵列,如對主鍵列進行新增、修改和刪除,可能就會引起併發操作阻塞的情況。
--新增資料主鍵約束
SQL> alter table t add constraint pk_t primary key (id);
Table altered
SQL> select * from t;
ID NA
---------- ----------
1 dfs
2 df
如果此時,一個會話發起了修改某行主鍵列的操作。另一個會話就可能不會允許進行某些針對主鍵列的操作,即使是相同資料行。
--第一會話中
SQL> select sid from v$mystat where rownum<2;
SID
----------
151
SQL> update t set id=3 where id=1;
1 row updated
--在會話二中(sid=149)
SQL> update t set id=4 where id=2;
1 row updated
SQL> rollback;
Rollback complete
SQL> update t set id=1 where id=2;
(阻塞)
SQL> update t set id=3 where id=2;
(阻塞)
從效果看,如果我們對主鍵列進行一個事務,將主鍵列取值發生可能的變化。那麼,即使這個事務沒有提交,其他會話在涉及到對該主鍵列的取值時,如果使用到了可能的變化值,會話時會被block的。
此時鎖定情況如下:
SQL> select sid,type,id1,id2,lmode,request,block from v$lock where sid=151 or sid=149 order by sid;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ---- ---------- ---------- ---------- ---------- ----------
149 TX 458778 1293 0 4 0
149 TM 54736 0 3 0 0
149 TX 196650 1250 6 0 0
151 TX 458778 1293 6 0 1
151 TM 54736 0 3 0 0
同一般的鎖定情況,我們發現了一些差異。第二個會話(sid=149)要求以lmode=4的方式獲取事務段鎖,被阻塞。
從道理上分析,Oracle這樣做也是有其“為難之處”。預設情況下,Oracle對DML操作的約束檢查是在操作進行時,而非commit時檢查。當一個主鍵列從值A變化為B的時候,Oracle接收到了另一會話事務請求,要求將一個行主鍵列變為A。Oracle如果接受了第二會話的要求,那麼第一會話rollback的時候就違反約束。如果Oracle拒絕了第二個會話的要求,那麼第一會話commit的時候就無法處理了。兩難情況下的Oracle,只能選擇block第二個會話。
上面的兩種情況是比較常見的,那麼我們下篇介紹其他幾種可能的block情況。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-715796/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 淺談DML阻塞(下)
- 資料庫:淺談DML、DDL、DCL的區別資料庫
- 淺談exp/imp(上)
- SQLServer DML操作阻塞SELECT查詢SQLServer
- 淺談Flutter熱過載(上)Flutter
- 淺談醫學大資料(上)大資料
- 淺談JS阻塞方式怎麼實現非同步任務佇列?JS非同步佇列
- 外來鍵沒有索引哪些DML操作會被阻塞索引
- 淺談uCOS-II的任務(上)
- 談談對不同I/O模型的理解 (阻塞/非阻塞IO,同步/非同步IO)模型非同步
- 淺淺談ReduxRedux
- 對於同步、非同步、阻塞、非阻塞的幾點淺薄理解非同步
- 從JDK11新增HttpClient談談非阻塞模型JDKHTTPclient模型
- 淺談使用者研究那些事(上)定性研究
- 【原創】淺談指標(十二)關於static(上)指標
- 淺淺淺談JavaScript作用域JavaScript
- Celery淺談
- 淺談flutterFlutter
- 淺談JMM
- 淺談反射反射
- 淺談mockMock
- 淺談SYNPROXY
- 淺談Disruptor
- 淺談IHttpHandlerHTTP
- 淺談 PromisePromise
- 淺談PWA
- 淺談vuexVue
- 淺談JavaScriptJavaScript
- 淺談RMQMQ
- 淺談Zilliqa
- 淺談RxJavaRxJava
- 淺談NginxNginx
- 淺談 JavaScriptCoreJavaScript
- 淺談MVPMVP
- 淺談BitMap
- Jquery淺談jQuery
- 淺談CopyOnWriteArraySet
- ElasticSearch淺談Elasticsearch