日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Select For update语句浅析

發(fā)布時(shí)間:2024/8/26 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Select For update语句浅析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Select …forupdate語句是我們經(jīng)常使用手工加鎖語句。通常情況下,select語句是不會(huì)對數(shù)據(jù)加鎖,妨礙影響其他的DMLDDL操作。同時(shí),在多版本一致讀機(jī)制的支持下,select語句也不會(huì)被其他類型語句所阻礙。

?

借助for update子句,我們可以在應(yīng)用程序的層面手工實(shí)現(xiàn)數(shù)據(jù)加鎖保護(hù)操作。本篇我們就來介紹一下這個(gè)子句的用法和功能。

?

下面是采自Oracle官方文檔《SQLLanguage Reference》中關(guān)于for update子句的說明:(請雙擊點(diǎn)開圖片查看)

?

?

for update子句的語法狀態(tài)圖中,我們可以看出該子句分為兩個(gè)部分:加鎖范圍子句和加鎖行為子句。下面我們分別針對兩個(gè)方面的進(jìn)行介紹。

?

加鎖范圍子句

?

select…for update之后,可以使用of子句選擇對select的特定數(shù)據(jù)表進(jìn)行加鎖操作。默認(rèn)情況下,不使用of子句表示在select所有的數(shù)據(jù)表中加鎖。

?

//采用默認(rèn)格式for update

SQL> select * from emp where rownum<2 for update;

?

EMPNO ENAME?????JOB????????MGR HIREDATE?????????SAL?????COMM DEPTNO

----- ---------- --------- ----- ----------- --------- --------- ------

?7369 SMITH?????CLERK?????79021980-12-17????800.00??????????????20

?

?

此時(shí),我們觀察v$lockv$locked_object視圖,可以看到鎖信息。

//事務(wù)信息視圖

SQL> select addr,xidusn,xidslot,xidsqn from v$transaction;

?

ADDR????????XIDUSN???XIDSLOT????XIDSQN

-------- ---------- ---------- ----------

377DB5D0?????????7????????19???????808

//鎖對象信息

SQL> select xidusn,xidslot,xidsqn,object_id,session_id, oracle_username from v$locked_object;

?

???XIDUSN???XIDSLOT????XIDSQN?OBJECT_ID SESSION_ID ORACLE_USERNAME

---------- ---------- ---------- ---------- ---------- ------------------------------

????????7????????19???????808?????73181????????36 SCOTT

//

SQL> select owner,object_name from dba_objects where object_id=73181;

?

OWNER?????????????????????????OBJECT_NAME

------------------------------ ------------------------------------------------------------

SCOTT?????????????????????????EMP

?

//

SQL> select addr, sid, type, id1,id2,lmode, request, block from v$lock where sid=36;

?

ADDR?????SID TYPE???????ID1???????ID2?????LMODE???REQUEST?BLOCK

-------- ---------- ---- ---------- ---------- ---------- ---------- ----------

37E808F0???36 AE?????????100?????????0?????????4?????????0???0

B7DE8A44??36 TM???????73181?????????0?????????3?????????0??0

377DB5D0??36 TX??????458771???????808?????????6?????????0???0

?

?

從上面的情況看,默認(rèn)情況下的for update語句,效果相當(dāng)于啟動(dòng)了一個(gè)會(huì)話級(jí)別的事務(wù),在對應(yīng)的數(shù)據(jù)表(select所涉及的所有數(shù)據(jù)表)上加入一個(gè)數(shù)據(jù)表級(jí)共享鎖(TMlmode=3)。同時(shí),在對應(yīng)的數(shù)據(jù)行中加入獨(dú)占鎖(TXlmode=6)。

?

根據(jù)我們以前的知識(shí),如果此時(shí)有另一個(gè)會(huì)話視圖獲取對應(yīng)數(shù)據(jù)行的獨(dú)占權(quán)限(無論是用update/delete還是另一個(gè)for update),都會(huì)以block而告終。

?

SQL> select sid from v$mystat where rownum<2;

?

??????SID

----------

???????37

?

SQL> select * from emp where empno=7369 for update;

?

//系統(tǒng)blocking

?

此時(shí)系統(tǒng)中狀態(tài),切換到另一個(gè)用戶下進(jìn)行觀察:

?

SQL> select addr, sid, type, id1,id2,lmode, request, block from v$lock where sid in (36,37);

?

ADDR??SID TYPE???????ID1???????ID2?????LMODE???REQUEST?????BLOCK

-------- ---------- ---- ---------- ---------- ---------- ---------- ----------

37E808F0????????36 AE?????????100?????????0?????????4?????????0??0

37E80ED4????????37 AE?????????100?????????0?????????4?????????0??0

37E80F48????????37 TX??????458771???????808?????????0?????????6??0

B7DE8A44????????37 TM???????73181?????????0?????????3?????????0?0

B7DE8A44????????36 TM???????73181?????????0?????????3?????????0?0

377DB5D0????????36 TX??????458771???????808?????????6?????????0?1

?

6 rows selected

?

SQL> select * from dba_waiters;

?

WAITING_SESSION HOLDING_SESSION LOCK_TYPE?????????????????MODE_HELD???????????????????????????????MODE_REQUESTED????????????????????????????LOCK_ID1??LOCK_ID2

--------------- --------------- -------------------------- ---------------------------------------- ---------------------------------------- ---------- ----------

????????????37?????????????36Transaction???????????????Exclusive???????????????????????????????Exclusive???????????????????????????????????458771???????808

?

?

由此,我們可以獲取到結(jié)論:for update子句的默認(rèn)行為就是自動(dòng)啟動(dòng)一個(gè)事務(wù),借助事務(wù)的鎖機(jī)制將數(shù)據(jù)進(jìn)行鎖定。

?

?

Of子句是配合for update語句使用的一個(gè)范圍說明標(biāo)記。從官方的語法結(jié)構(gòu)看,后面可以跟一個(gè)或者多個(gè)數(shù)據(jù)列列表。這種語法場景常常使用在進(jìn)行連接查詢的select中,對其中一張數(shù)據(jù)表數(shù)據(jù)進(jìn)行鎖定。

?

SQL> select empno,ename,job,mgr,sal from emp,dept where emp.deptno=dept.deptno and empno=7369 for update of emp.empno;

?

EMPNO ENAME?????JOB????????MGR??????SAL

----- ---------- --------- ----- ---------

?7369 SMITH?????CLERK?????7902???800.00

?

SQL>?select addr, sid, type, id1,id2,lmode, request, block from v$lock where sid=36;

?

ADDR??????SID TYPE???????ID1???????ID2?????LMODE???REQUEST BLOCK

-------- ---------- ---- ---------- ---------- ---------- ---------- ----------

37E808F0????????36 AE?????????100?????????0?????????4?????????0???0

B7E1C2E8????????36 TM???????73181?????????0?????????3????????0???0

377DBC0C????????36 TX???????65566???????747?????????6??????0??0

?

?

上面的語句中,我們看到使用for update of指定數(shù)據(jù)列之后,鎖定的范圍限制在了所在的數(shù)據(jù)表。也就是說,當(dāng)我們使用連接查詢配合of子句的時(shí)候,可以實(shí)現(xiàn)有針對性的鎖定。

?

同樣在連接查詢的時(shí)候,如果沒有of子句,同樣采用默認(rèn)的模式,會(huì)如何呢?

?

SQL> select empno,ename,job,mgr,sal from emp,dept where emp.deptno=dept.deptno and empno=7369 for update;

?

EMPNO ENAME?????JOB????????MGR??????SAL

----- ---------- --------- ----- ---------

?7369 SMITH?????CLERK?????7902???800.00

?

SQL>?select addr, sid, type, id1,id2,lmode, request, block from v$lock where sid=36;

?

ADDR????SID TYPE???????ID1???????ID2?????LMODE???REQUEST?BLOCK

-------- ---------- ---- ---------- ---------- ---------- ---------- ----------

37E808F0????????36 AE?????????100?????????0?????????4?????????0????0

B7E1C2E8????????36 TM???????73179?????????0?????????3?????????0??0

B7E1C2E8????????36 TM???????73181?????????0?????????3?????????0????0

377DBC0C????????36 TX??????458777???????805?????????6?????????0???0

?

SQL> select owner,object_name from dba_objects where object_id=73179;

?

OWNER?????????????????????????OBJECT_NAME

------------------------------ --------------------------------------------------------------------------------

SCOTT?????????????????????????DEPT

?

?

明顯可以看到,當(dāng)我們沒有使用of子句的時(shí)候,默認(rèn)就是對所有select的數(shù)據(jù)表進(jìn)行lock操作。

?

?

加鎖行為子句

?

加鎖行為子句相對比較容易理解。這里分別介紹。

?

Nowait子句

?

當(dāng)我們進(jìn)行for update的操作時(shí),與普通select存在很大不同。一般select是不需要考慮數(shù)據(jù)是否被鎖定,最多根據(jù)多版本一致讀的特性讀取之前的版本。加入for update之后,Oracle就要求啟動(dòng)一個(gè)新事務(wù),嘗試對數(shù)據(jù)進(jìn)行加鎖。如果當(dāng)前已經(jīng)被加鎖,默認(rèn)的行為必然是block等待。

?

使用nowait子句的作用就是避免進(jìn)行等待,當(dāng)發(fā)現(xiàn)請求加鎖資源被鎖定未釋放的時(shí)候,直接報(bào)錯(cuò)返回。

///session1

SQL> select * from emp for update;

?

EMPNO ENAME?????JOB????????MGR HIREDATE?????????SAL?????COMM DEPTNO

----- ---------- --------- ----- ----------- --------- --------- ------

?7369 SMITH?????CLERK?????79021980-12-17????800.00??????????????20

?7499 ALLEN?????SALESMAN??76981981-2-20????1600.00???300.00????30

?7521 WARD??????SALESMAN??76981981-2-22????1250.00???500.00????30

?7566 JONES?????MANAGER???78391981-4-2?????2975.00??????????????20

?

//變換session,進(jìn)行執(zhí)行。

SQL> select * from emp for update nowait;

?

select * from emp for update nowait

?

ORA-00054:資源正忙,但指定以NOWAIT方式獲取資源,或者超時(shí)失效

?

?

對應(yīng)的還有就是wait子句,也就是默認(rèn)的for update行為。一旦發(fā)現(xiàn)對應(yīng)資源被鎖定,就等待blocking,直到資源被釋放或者用戶強(qiáng)制終止命令。

?

?

wait子句還存在一個(gè)數(shù)據(jù)參數(shù)位,表示當(dāng)出現(xiàn)blocking等待的時(shí)候最多等待多長時(shí)間。單位是秒級(jí)別。

//接上面的案例

SQL> select * from emp for update wait 3;

?

select * from emp for update wait 3

?

ORA-30006:資源已被占用;執(zhí)行操作時(shí)出現(xiàn)WAIT超時(shí)

?

?

?

Skip locked參數(shù)

?

Skip locked參數(shù)是最新引入到for update語句中的一個(gè)參數(shù)。簡單的說,就是在對數(shù)據(jù)行進(jìn)行加鎖操作時(shí),如果發(fā)現(xiàn)數(shù)據(jù)行被鎖定,就跳過處理。這樣for update就只針對未加鎖的數(shù)據(jù)行進(jìn)行處理加鎖。

?

//session1中,對一部分?jǐn)?shù)據(jù)加鎖;

SQL> select * from emp where rownum<4 for update;

?

EMPNO ENAME?????JOB????????MGR HIREDATE?????????SAL?????COMM DEPTNO

----- ---------- --------- ----- ----------- --------- --------- ------

?7369 SMITH?????CLERK?????79021980-12-17????800.00??????????????20

?7499 ALLEN?????SALESMAN??76981981-2-20????1600.00???300.00????30

?7521 WARD??????SALESMAN??76981981-2-22????1250.00???500.00????30

?

//session2中;

SQL> select * from emp for update skip locked;

?

EMPNO ENAME?????JOB????????MGR HIREDATE?????????SAL?????COMM DEPTNO

----- ---------- --------- ----- ----------- --------- --------- ------

(篇幅原因,省略)

7934 MILLER????CLERK?????77821982-1-23????1300.00??????????????10

?

11 rows selected

?

?

總數(shù)據(jù)一共14行。Session1中,先lock住了3行數(shù)據(jù)。之后的seesion2中,由于使用的skip locked子句參數(shù),將剩下的11條數(shù)據(jù)進(jìn)行讀取到并且加鎖。

?

?

for update的使用

?

在日常中,我們對for update的使用還是比較普遍的,特別是在如pl/sql developer中手工修改數(shù)據(jù)。此時(shí)只是覺得方便,而對for update真正的含義缺乏理解。

?

For updateOracle提供的手工提高鎖級(jí)別和范圍的特例語句。Oracle的鎖機(jī)制是目前各類型數(shù)據(jù)庫鎖機(jī)制中比較優(yōu)秀的。所以,Oracle認(rèn)為一般不需要用戶和應(yīng)用直接進(jìn)行鎖的控制和提升。甚至認(rèn)為死鎖這類鎖相關(guān)問題的出現(xiàn)場景,大都與手工提升鎖有關(guān)。所以,Oracle并不推薦使用for update作為日常開發(fā)使用。而且,在平時(shí)開發(fā)和運(yùn)維中,使用了for update卻忘記提交,會(huì)引起很多鎖表故障。

?

那么,什么時(shí)候需要使用for update?就是那些需要業(yè)務(wù)層面數(shù)據(jù)獨(dú)占時(shí),可以考慮使用for update。場景上,比如火車票訂票,在屏幕上顯示郵票,而真正進(jìn)行出票時(shí),需要重新確定一下這個(gè)數(shù)據(jù)沒有被其他客戶端修改。所以,在這個(gè)確認(rèn)過程中,可以使用for update。這是統(tǒng)一的解決方案方案問題,需要前期有所準(zhǔn)備


總結(jié)

以上是生活随笔為你收集整理的Select For update语句浅析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。