Oracle 共享锁和排它锁、 DML和DDL锁、 for update 锁表的问题
生活随笔
收集整理的這篇文章主要介紹了
Oracle 共享锁和排它锁、 DML和DDL锁、 for update 锁表的问题
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
共享鎖和排它鎖
oracle有兩種模式的鎖:排他鎖(exclusive lock,即X鎖)和共享鎖(share lock,即S鎖)。 共享鎖:如果事務(wù)T對(duì)數(shù)據(jù)A加上共享鎖后,則其他事務(wù)只能對(duì)A再加共享鎖,不能加排他鎖。獲準(zhǔn)共享鎖的事務(wù)只能讀數(shù)據(jù),不能修改數(shù)據(jù)。(注:共享鎖是表級(jí)的,比如Select會(huì)對(duì)表加共享鎖) 排他鎖:如果事務(wù)T對(duì)數(shù)據(jù)A加上排他鎖后,則其他事務(wù)不能再對(duì)A加任任何類型的鎖。獲準(zhǔn)排他鎖的事務(wù)既能讀數(shù)據(jù),又能修改數(shù)據(jù)。(注:排他鎖一般是行級(jí)的,比如DML操作 insert update delete,在執(zhí)行DML操作時(shí)分兩步加鎖,先加共享鎖,后加排他鎖。在添加排他鎖后,不能添加任何鎖直至鎖釋放 commit或者rollback) 數(shù)據(jù)庫(kù)利用這兩種基本的鎖類型來(lái)對(duì)數(shù)據(jù)庫(kù)的事務(wù)進(jìn)行并發(fā)控制。 共享鎖無(wú)法阻止其他用戶讀取和修改表中的數(shù)據(jù),只能阻止其他用戶使用ALTER TABLE命令改變指定表的結(jié)構(gòu)或用DROP TABLE命令刪除指定表。多個(gè)用戶可以同時(shí)獲得相同數(shù)據(jù)上的共享鎖。 執(zhí)行DML語(yǔ)句時(shí)可以獲得排他鎖,并且正在被修改的所有記錄都會(huì)獲得排他鎖。在你啟動(dòng)的事務(wù)內(nèi),排他鎖阻止其他用戶獲得正在處理的數(shù)據(jù)上的排他鎖,直至執(zhí)行COMMIT或ROLLBACK語(yǔ)句。這樣,兩個(gè)用戶就無(wú)法同時(shí)更新相同的數(shù)據(jù)。某個(gè)用戶試圖更新被另一個(gè)用戶鎖定的數(shù)據(jù)時(shí),第一個(gè)用戶必須等待至去除排他鎖后才能進(jìn)行操作。 通過(guò)DML語(yǔ)句對(duì)一張表的某一行數(shù)據(jù)進(jìn)行修改,一個(gè)事務(wù)開(kāi)始,背后的步驟是: 1.對(duì)這張表加一個(gè)共享鎖。這么做是為了防止別的會(huì)話通過(guò)DDL語(yǔ)句修改這張表的表結(jié)構(gòu)。DDL語(yǔ)句要修改了這張表,就必須給表加上排他鎖。但是現(xiàn)在給表加了共享鎖了,也就排斥了DDL去加排他鎖; 2.對(duì)修改的那一行加一個(gè)排他鎖,別的會(huì)話不能修改這一行。但是我對(duì)整張表加的是共享鎖而不是排他鎖,所以別的會(huì)話還是可以修改其他行(也經(jīng)歷1、2兩個(gè)步驟)。默認(rèn)情況下的select … for update語(yǔ)句與DML語(yǔ)句相似,效果相當(dāng)于啟動(dòng)了一個(gè)會(huì)話級(jí)別的事務(wù),在對(duì)應(yīng)的數(shù)據(jù)表(select所涉及的所有數(shù)據(jù)表)上加入一個(gè)數(shù)據(jù)表級(jí)共享鎖(TM,lmode=3)。同時(shí),在對(duì)應(yīng)的數(shù)據(jù)行中加入獨(dú)占鎖(TX,lmode=6)。注意:只有表級(jí)的共享鎖沒(méi)有行級(jí)共享鎖。的確,也是有row share的鎖的,只是這個(gè)不是代表行的,是代表表鎖的種類。指的是在行上加排他鎖,在表上加共享鎖,表級(jí)共享、行級(jí)排他。 ------------------------------------------------------------- mysql鎖機(jī)制分為表級(jí)鎖和行級(jí)鎖,本文就和大家分享一下我對(duì)mysql中行級(jí)鎖中的共享鎖與排他鎖進(jìn)行分享交流。共享鎖又稱為讀鎖,簡(jiǎn)稱S鎖,顧名思義,共享鎖就是多個(gè)事務(wù)對(duì)于同一數(shù)據(jù)可以共享一把鎖,都能訪問(wèn)到數(shù)據(jù),但是只能讀不能修改。排他鎖又稱為寫鎖,簡(jiǎn)稱X鎖,顧名思義,排他鎖就是不能與其他所并存,如一個(gè)事務(wù)獲取了一個(gè)數(shù)據(jù)行的排他鎖,其他事務(wù)就不能再獲取該行的其他鎖,包括共享鎖和排他鎖,但是獲取排他鎖的事務(wù)是可以對(duì)數(shù)據(jù)就行讀取和修改。對(duì)于共享鎖大家可能很好理解,就是多個(gè)事務(wù)只能讀數(shù)據(jù)不能改數(shù)據(jù),對(duì)于排他鎖大家的理解可能就有些差別,我當(dāng)初就犯了一個(gè)錯(cuò)誤,以為排他鎖鎖住一行數(shù)據(jù)后,其他事務(wù)就不能讀取和修改該行數(shù)據(jù),其實(shí)不是這樣的。排他鎖指的是一個(gè)事務(wù)在一行數(shù)據(jù)加上排他鎖后,其他事務(wù)不能再在其上加其他的鎖。mysql InnoDB引擎默認(rèn)的修改數(shù)據(jù)語(yǔ)句,update,delete,insert都會(huì)自動(dòng)給涉及到的數(shù)據(jù)加上排他鎖,select語(yǔ)句默認(rèn)不會(huì)加任何鎖類型,如果加排他鎖可以使用select ...for update語(yǔ)句,加共享鎖可以使用select ... lock in share mode語(yǔ)句。所以加過(guò)排他鎖的數(shù)據(jù)行在其他事務(wù)種是不能修改數(shù)據(jù)的,也不能通過(guò)for update和lock in share mode鎖的方式查詢數(shù)據(jù),但可以直接通過(guò)select ...from...查詢數(shù)據(jù),因?yàn)槠胀ú樵儧](méi)有任何鎖機(jī)制。 ----------------------------------------------在 MySQL 中的行級(jí)鎖、表級(jí)鎖和頁(yè)級(jí)鎖中,咱們介紹過(guò),行級(jí)鎖是 MySQL 中鎖定粒度最細(xì)的一種鎖,行級(jí)鎖能大大減少數(shù)據(jù)庫(kù)操作的沖突。行級(jí)鎖分為共享鎖和排他鎖兩種,本文將詳細(xì)介紹共享鎖和排他鎖的概念、使用方式及注意事項(xiàng)。共享鎖(Share Lock) 共享鎖又稱讀鎖,是讀取操作創(chuàng)建的鎖。其他用戶可以并發(fā)讀取數(shù)據(jù),但任何事務(wù)都不能對(duì)數(shù)據(jù)進(jìn)行修改(獲取數(shù)據(jù)上的排他鎖),直到已釋放所有共享鎖。如果事務(wù)T對(duì)數(shù)據(jù)A加上共享鎖后,則其他事務(wù)只能對(duì)A再加共享鎖,不能加排他鎖。獲準(zhǔn)共享鎖的事務(wù)只能讀數(shù)據(jù),不能修改數(shù)據(jù)。用法SELECT ... LOCK IN SHARE MODE;在查詢語(yǔ)句后面增加LOCK IN SHARE MODE,MySQL 就會(huì)對(duì)查詢結(jié)果中的每行都加共享鎖,當(dāng)沒(méi)有其他線程對(duì)查詢結(jié)果集中的任何一行使用排他鎖時(shí),可以成功申請(qǐng)共享鎖,否則會(huì)被阻塞。其他線程也可以讀取使用了共享鎖的表,而且這些線程讀取的是同一個(gè)版本的數(shù)據(jù)。排他鎖(Exclusive Lock) 排他鎖又稱寫鎖、獨(dú)占鎖,如果事務(wù)T對(duì)數(shù)據(jù)A加上排他鎖后,則其他事務(wù)不能再對(duì)A加任何類型的封鎖。獲準(zhǔn)排他鎖的事務(wù)既能讀數(shù)據(jù),又能修改數(shù)據(jù)。用法SELECT ... FOR UPDATE;在查詢語(yǔ)句后面增加FOR UPDATE,MySQL 就會(huì)對(duì)查詢結(jié)果中的每行都加排他鎖,當(dāng)沒(méi)有其他線程對(duì)查詢結(jié)果集中的任何一行使用排他鎖時(shí),可以成功申請(qǐng)排他鎖,否則會(huì)被阻塞。 ------------------------------------------------------------ 共享鎖(S鎖):共享 (S) 用于不更改或不更新數(shù)據(jù)的操作(只讀操作),如 SELECT 語(yǔ)句。如果事務(wù)T對(duì)數(shù)據(jù)A加上共享鎖后,則其他事務(wù)只能對(duì)A再加共享鎖,不能加排他鎖。獲準(zhǔn)共享鎖的事務(wù)只能讀數(shù)據(jù),不能修改數(shù)據(jù)。排他鎖(X鎖):用于數(shù)據(jù)修改操作,例如 INSERT、UPDATE 或 DELETE。確保不會(huì)同時(shí)同一資源進(jìn)行多重更新。如果事務(wù)T對(duì)數(shù)據(jù)A加上排他鎖后,則其他事務(wù)不能再對(duì)A加任任何類型的封鎖。獲準(zhǔn)排他鎖的事務(wù)既能讀數(shù)據(jù),又能修改數(shù)據(jù)。簡(jiǎn)要說(shuō)明為什么會(huì)發(fā)生死鎖?解決死鎖的主要方法是什么? 若干事務(wù)相互等待釋放封鎖,就陷入無(wú)限期等待狀態(tài),系統(tǒng)就進(jìn)入死鎖解決死鎖的方法應(yīng)從預(yù)防和解除的兩個(gè)方面著手: (1)死鎖的預(yù)防方法: a、要求每一個(gè)事務(wù)必須一次封鎖所要使用的全部數(shù)據(jù)(要么全成功,要么全不成功) b、規(guī)定封鎖數(shù)據(jù)的順序,所有事務(wù)必須按這個(gè)順序?qū)嵭蟹怄i。 (2)允許死鎖發(fā)生,然后解除它,如果發(fā)現(xiàn)死鎖,則將其中一個(gè)代價(jià)較小的事物撤消,回滾這個(gè)事務(wù),并釋放此事務(wù)持有的封鎖,使其他事務(wù)繼續(xù)運(yùn)行。oracle:共享鎖LOCK TABLE 表 IN SHARE MODE ;排他鎖:LOCK TABLE 表 IN EXCLUSIVE MODE ;加鎖后其它人不可操作,直到加鎖用戶解鎖,用commit或rollback解鎖行排他鎖不阻止其他Session申請(qǐng)表共享鎖和其他行的排他鎖,但阻止申請(qǐng)表排他鎖和鎖定行的任何鎖。 表排他鎖阻止其他Session的申請(qǐng)的所有鎖。 表共享鎖不阻止其他Session申請(qǐng)行排他鎖和表共享鎖,但阻止申請(qǐng)表排他鎖。一道相關(guān)的試題:User SCOTT executes the following command on the EMP table but has not issued COMMIT,ROLLBACK, or any data definition language (DDL)ommand: SQL> SELECT job FROM emp WHERE job=’CLERK’ FOR UPDATE OF empno; SCOTT has opened another session to work with the database. Which three operations would wait when issued in SCOTT’s second session?(Choose three.) A. LOCK TABLE emp IN SHARE MODE;(阻止申請(qǐng)行的共享鎖) B. LOCK TABLE emp IN EXCLUSIVE MODE;(阻止申請(qǐng)表的排他鎖) C. DELETE FROM emp WHERE job=’MANAGER’; D. INSERT INTO emp(empno,ename) VALUES(1289,’Dick’); E. SELECT job FROM emp WHERE job=’CLERK’ FOR UPDATE OF empno;(阻止申請(qǐng)行的排他鎖)SELECT …… FROM …… FOR UPDATE 語(yǔ)句申請(qǐng)的是相應(yīng)行的排他鎖以及行所在表的共享鎖。上題答案給的是A、B、E -------------------------------------------------------- 共享鎖:(讀取)操作創(chuàng)建的鎖。其他用戶可以并發(fā)讀取數(shù)據(jù),但任何事物都不能獲取數(shù)據(jù)上的排它鎖,直到已釋放所有共享鎖。 共享鎖(S鎖)又稱為讀鎖,若事務(wù)T對(duì)數(shù)據(jù)對(duì)象A加上S鎖,則事務(wù)T只能讀A;其他事務(wù)只能再對(duì)A加S鎖,而不能加X(jué)鎖,直到T釋放A上的S鎖。這就保證了其他事務(wù)可以讀A,但在T釋放A上的S鎖之前不能對(duì)A做任何修改。排它鎖 排它鎖:排它鎖又稱為寫鎖((eXclusive lock,簡(jiǎn)記為X鎖)),若事物T對(duì)數(shù)據(jù)對(duì)象A加上X鎖,則只允許T讀取和修改A,其它任何事務(wù)都不能再對(duì)A加任何類型的鎖,直到T釋放A上的鎖。它防止任何其它事務(wù)獲取資源上的鎖,直到在事務(wù)的末尾將資源上的原始鎖釋放為止。 獨(dú)占鎖和共享鎖的區(qū)別 1.共享鎖(S鎖):如果事務(wù)T對(duì)數(shù)據(jù)A加上共享鎖后,則其他事務(wù)只能對(duì)A再加共享鎖,不能加排它鎖。獲準(zhǔn)共享鎖的事務(wù)只能讀數(shù)據(jù),不能修改數(shù)據(jù)。 排他鎖(X鎖):如果事務(wù)T對(duì)數(shù)據(jù)A加上排他鎖后,則其他事務(wù)不能再對(duì)A加任任何類型的封鎖。獲準(zhǔn)排他鎖的事務(wù)既能讀數(shù)據(jù),又能修改數(shù)據(jù)。 2.共享鎖下其它用戶可以并發(fā)讀取,查詢數(shù)據(jù)。但不能修改,增加,刪除數(shù)據(jù)。資源共享.共享鎖的使用 在第一個(gè)連接中執(zhí)行以下語(yǔ)句 begin tran select * from table1 holdlock -holdlock人為加鎖 where B='b2' waitfor delay '00:00:30' --等待30秒 commit tran 在第二個(gè)連接中執(zhí)行以下語(yǔ)句 begin tran select A,C from table1 where B='b2' update table1 set A='aa' where B='b2' commit tran 若同時(shí)執(zhí)行上述兩個(gè)語(yǔ)句,則第二個(gè)連接中的select查詢可以執(zhí)行 而update必須等待第一個(gè)事務(wù)釋放共享鎖轉(zhuǎn)為排它鎖后才能執(zhí)行 即要等待30秒 ----------------------------------------------------------------------DML和DDL鎖
DML鎖,也叫做數(shù)據(jù)鎖(data lock),用于保證在多用戶操作數(shù)據(jù)時(shí)數(shù)據(jù)的完整。DML鎖防止相互沖突的DML和DDL操作同時(shí)發(fā)生。 DML鎖有行鎖(Row Locks,TX)和表鎖(Table Locks,TM),不同的DML操作會(huì)自動(dòng)請(qǐng)求對(duì)應(yīng)的鎖。行鎖(Row Locks,TX) 行鎖也叫TX鎖,用于鎖表的一行數(shù)據(jù)。當(dāng)一個(gè)事務(wù)對(duì)一行數(shù)據(jù)做INSERT、UPDATE、DELETE、MERGE或SELECT ... FOR UPDATE操作時(shí),數(shù)據(jù)將為行添加行鎖,直到事務(wù)執(zhí)行了commit或roll back操作后,行鎖才釋放。 行鎖防止兩個(gè)事務(wù)修改同一行數(shù)據(jù),當(dāng)一個(gè)事務(wù)修改一行數(shù)據(jù)時(shí),數(shù)據(jù)庫(kù)總是為修改的行加一個(gè)排它鎖以至于其它事務(wù)無(wú)法修改該行,只有當(dāng)事務(wù)執(zhí)行了commit或者roll back操作后,數(shù)據(jù)庫(kù)才會(huì)釋放對(duì)應(yīng)的鎖。行鎖是小粒度的鎖,為應(yīng)用提供了最大限度的并行修改數(shù)據(jù)的能力。 當(dāng)一個(gè)事務(wù)獲取了一個(gè)行鎖,那么這個(gè)事務(wù)也需要獲取這行數(shù)據(jù)所在表的表鎖,表鎖阻止有沖突的DDL操作,即數(shù)據(jù)庫(kù)會(huì)自動(dòng)的為更新的行添加一個(gè)排它鎖,并為行所在的表添加一個(gè)子排它鎖。 行鎖和并發(fā) 下面通過(guò)一個(gè)例子來(lái)理解行鎖和并發(fā)的關(guān)系。 首先創(chuàng)建下面的表格,并初始化數(shù)據(jù): create table employees(employee_id number(10),salary number(10)); insert into employees(employee_id,salary) values(100,512); insert into employees(employee_id,salary) values(101,600); ...... 步驟一:三個(gè)Session同時(shí)查詢ID為100和101的雇員,查詢結(jié)果一致 Session 1: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600Session 2: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600Session 3: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600 步驟二:Session 1執(zhí)行更新操作,更新id為100的雇員,在這個(gè)更新中,寫者將請(qǐng)求一個(gè)行鎖,阻止其它寫者更新這行數(shù)據(jù),如果其它寫者更新該行數(shù)據(jù)將被阻塞,直到Session 1提交或者回滾數(shù)據(jù) Session 1: update employees set salary = 612 where employee_id = 100 步驟三:再次執(zhí)行步驟一的操作 Session 1: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 612 101 600Session 2: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600Session 3: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600 Session 1的結(jié)果是它更新后的數(shù)據(jù),而其他兩個(gè)session任然是舊數(shù)據(jù)。 步驟四:Session 2更新101雇員的薪水,并且不提交數(shù)據(jù),這樣Session 2獲取了對(duì)雇員101的行鎖 UPDATE hr.employees SET salary = salary + 100 WHERE employee_id = 101; 步驟五:再次執(zhí)行步驟1的查詢 Session 1: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 612 101 600Session 2: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 700Session 3: SELECT employee_id, salary FROM employees WHERE employee_id IN (100, 101); EMPLOYEE_ID SALARY ------------------------- 100 512 101 600 行鎖的存儲(chǔ) Oracle將鎖信息存儲(chǔ)在data block中。數(shù)據(jù)庫(kù)用一個(gè)隊(duì)列機(jī)制處理行鎖請(qǐng)求,如果一個(gè)事務(wù)請(qǐng)求一個(gè)未鎖定的行,那么事務(wù)將放一個(gè)鎖到data block,被事務(wù)修改的每一行都指向存儲(chǔ)在block header中的事務(wù)ID的一個(gè)拷貝。 當(dāng)一個(gè)事務(wù)結(jié)束時(shí),事務(wù)ID保留在block header中,如果另一個(gè)事務(wù)想修改一行數(shù)據(jù),那么它用這個(gè)事務(wù)ID判定這個(gè)鎖是否是激活的。如果鎖是激活的,那么當(dāng)鎖被釋放時(shí),該事務(wù)的session將被通知,否則,事務(wù)獲取這個(gè)鎖。 表鎖(Table Locks,TM) 表鎖,也叫TM鎖,當(dāng)對(duì)表執(zhí)行以下操作時(shí)將被請(qǐng)求:INSERT、UPDATE、DELETE、MERGE、SELECT ... FOR UPDATE和LOCK TABLE。請(qǐng)求表鎖的DML操作將阻止其它沖突的DDL操作。 表鎖有以下的模式: Row Share(RS) 該鎖也叫subshare table lock(SS),表示事務(wù)持有表上的鎖已鎖定表中的行,并打算對(duì)其進(jìn)行更新。Row share鎖是最小限制的表鎖,為表的行數(shù)據(jù)的高并發(fā)修改提供了支持。 Row Exclusive Table Lock(RX) 該所也叫subexclusive table lock(SX),通常表示持有鎖的事務(wù)更新了表的行或者執(zhí)行了SELECT ... FOR UPDATE。SX鎖允許其它事務(wù)查詢、插入、更新、刪除或者在同一個(gè)表上鎖定多行數(shù)據(jù),因此,SX鎖允許多個(gè)事務(wù)在同一個(gè)表上同時(shí)獲取SX和RS鎖。 Share Table Lock(S) 一個(gè)事務(wù)持有了表的S鎖,任然允許其他事務(wù)查詢?cè)摫砀?#xff08;除了用SELECT ... FOR UPDATE),但只有持有了S鎖的事務(wù)被允許更新表格。由于多個(gè)事務(wù)可以同時(shí)持有S鎖,獲取S鎖并不能保證事務(wù)能夠修改表格。 Share Row Exclusive Table Lock(SRX) 該鎖也叫share-subexclusive table lock(SSX),比S鎖限制更強(qiáng)。在一個(gè)表上一個(gè)時(shí)間點(diǎn)只能有一個(gè)事務(wù)能獲取SSX鎖。SSX鎖允許其它事務(wù)查詢表(除了用SELECT ... FOR UPDATE),但是不能更新表。 Exclusive Table Lock(X) 這個(gè)鎖限制最強(qiáng),禁止其它事務(wù)執(zhí)行任何類型的DML操作或?qū)Ρ矸乐谷魏捂i。 --------------------- DML鎖 DML鎖用于確保一次只有一個(gè)人能修改一行,而且這時(shí)別人不能刪除這個(gè)表。 1.TX鎖 A row lock, also called a TX lock, is alock on a single row of table. A transaction acquires a row lock for each rowmodified by an INSERT, UPDATE, DELETE,MERGE, or SELECT ... FOR UPDATEstatement. The row lock exists until the transaction commits or rolls back.一個(gè)行鎖,也被稱為TX lock,是對(duì)于表中一行的一個(gè)鎖。當(dāng)對(duì)行進(jìn)行INSERT, UPDATE, DELETE,MERGE, or SELECT ... FOR UPDATE等操作時(shí)事務(wù)需要獲取一個(gè)TX鎖。這個(gè)鎖會(huì)持續(xù)到事務(wù)提交或者rollback。If a transaction obtains a lock for a row,then the transaction also acquires a lock for the table containing the row. Thetable lock prevents conflicting DDL operations that would override data changesin a current transaction.可以防止DDL操作覆蓋當(dāng)前事務(wù)的數(shù)據(jù)。2.TM鎖 TM鎖用于確保在修改表的內(nèi)容時(shí),表的結(jié)構(gòu)不會(huì)被改變。A table lock, also called a TM lock, isacquired by a transaction when a table is modified by an INSERT, UPDATE,DELETE, MERGE, SELECT with the FOR UPDATE clause, or LOCK TABLE statement. DMLoperations require table locks to reserve DML access to the table on behalf ofa transaction and to prevent DDL operations that would conflict with thetransaction.一個(gè)表鎖,也被稱為TM鎖,被用于一個(gè)事務(wù)中當(dāng)表被通過(guò)INSERT, UPDATE, DELETE, MERGE, SELECT with theFOR UPDATE clause修改或者進(jìn)行了LOCK TABLE操作。被用來(lái)防止DDL操作導(dǎo)致事務(wù)沖突影響了自身的事務(wù)。DDL鎖 在DDL操作中會(huì)自動(dòng)為對(duì)象加DDL鎖,從而保護(hù)這些對(duì)象不會(huì)被其他會(huì)話所修改。在DDL語(yǔ)句執(zhí)行期間會(huì)一直持有DDL鎖,一旦操作執(zhí)行完畢就會(huì)立即釋放。排他DDL鎖(exclusive DDL lock):這會(huì)防止其他會(huì)話得到他們自己的DDL鎖或TM鎖。這說(shuō)明,在DDL操作期間可以查詢一個(gè)表,但是無(wú)法以任何方式修改這個(gè)表。 共享DDL鎖(share DDL lock):這些鎖會(huì)保護(hù)所引用的對(duì)象的結(jié)構(gòu),使之不會(huì)被其他會(huì)話修改,但是允許修改數(shù)據(jù)。 可中斷解析鎖(breakable parse lock):這些鎖允許一個(gè)對(duì)象向其他對(duì)象注冊(cè)其依賴性。???--參考來(lái)源《Oracle編程藝術(shù)深入理解數(shù)據(jù)庫(kù)體系結(jié)構(gòu)(第三版)》 -------------------------------------------------------------?for update 鎖表的問(wèn)題
數(shù)據(jù)庫(kù)是一個(gè)多用戶使用的共享資源。當(dāng)多個(gè)用戶并發(fā)地存取數(shù)據(jù)時(shí),在數(shù)據(jù)庫(kù)中就會(huì)產(chǎn)生多個(gè)事務(wù)同時(shí)存取同一數(shù)據(jù)的情況。若對(duì)并發(fā)操作不加控制就可能會(huì)讀取和存儲(chǔ)不正確的數(shù)據(jù),破壞數(shù)據(jù)庫(kù)的一致性。 加鎖是實(shí)現(xiàn)數(shù)據(jù)庫(kù)并發(fā)控制的一個(gè)非常重要的技術(shù)。當(dāng)事務(wù)在對(duì)某個(gè)數(shù)據(jù)對(duì)象進(jìn)行操作前,先向系統(tǒng)發(fā)出請(qǐng)求,對(duì)其加鎖。加鎖后事務(wù)就對(duì)該數(shù)據(jù)對(duì)象有了一定的控制,在該事務(wù)釋放鎖之前,其他的事務(wù)不能對(duì)此數(shù)據(jù)對(duì)象進(jìn)行更新操作。 在數(shù)據(jù)庫(kù)中有兩種基本的鎖類型:排它鎖(Exclusive Locks,即X鎖)和共享鎖(Share Locks,即S鎖)。當(dāng)數(shù)據(jù)對(duì)象被加上排它鎖時(shí),其他的事務(wù)不能對(duì)它讀取和修改。加了共享鎖的數(shù)據(jù)對(duì)象可以被其他事務(wù)讀取,但不能修改。數(shù)據(jù)庫(kù)利用這兩種基本的鎖類型來(lái)對(duì)數(shù)據(jù)庫(kù)的事務(wù)進(jìn)行并發(fā)控制。 Oracle數(shù)據(jù)庫(kù)的鎖類型 根據(jù)保護(hù)的對(duì)象不同,Oracle數(shù)據(jù)庫(kù)鎖可以分為以下幾大類:DML鎖(data locks,數(shù)據(jù)鎖),用于保護(hù)數(shù)據(jù)的完整性;DDL鎖(dictionary locks,字典鎖),用于保護(hù)數(shù)據(jù)庫(kù)對(duì)象的結(jié)構(gòu),如表、索引等的結(jié)構(gòu)定義;內(nèi)部鎖和閂(internal locks and latches),保護(hù) 數(shù)據(jù)庫(kù)的內(nèi)部結(jié)構(gòu)。 DML鎖的目的在于保證并發(fā)情況下的數(shù)據(jù)完整性,。在Oracle數(shù)據(jù)庫(kù)中,DML鎖主要包括TM鎖和TX鎖,其中TM鎖稱為表級(jí)鎖,TX鎖稱為事務(wù)鎖或行級(jí)鎖。當(dāng)Oracle執(zhí)行DML語(yǔ)句時(shí),系統(tǒng)自動(dòng)在所要操作的表上申請(qǐng)TM類型的鎖。當(dāng)TM鎖獲得后,系統(tǒng)再自動(dòng)申請(qǐng)TX類型的鎖,并將實(shí)際鎖定的數(shù)據(jù)行的鎖標(biāo)志位進(jìn)行置位。這樣在事務(wù)加鎖前檢查TX鎖相容性時(shí)就不用再逐行檢查鎖標(biāo)志,而只需檢查TM鎖模式的相容性即可,大大提高了系統(tǒng)的效率。TM鎖包括了SS、SX、S、X 等多種模式,在數(shù)據(jù)庫(kù)中用0-6來(lái)表示。不同的SQL操作產(chǎn)生不同類型的TM鎖。在數(shù)據(jù)行上只有X鎖(排他鎖)。在Oracle數(shù)據(jù)庫(kù)中,當(dāng)一個(gè)事務(wù)首次發(fā)起一個(gè)DML語(yǔ)句時(shí)就獲得一個(gè)TX鎖,該鎖保持到事務(wù)被提交或回滾。當(dāng)兩個(gè)或多個(gè)會(huì)話在表的同一條記錄上執(zhí)行 DML語(yǔ)句時(shí),第一個(gè)會(huì)話在該條記錄上加鎖,其他的會(huì)話處于等待狀態(tài)。當(dāng)?shù)谝粋€(gè)會(huì)話提交后,TX鎖被釋放,其他會(huì)話才可以加鎖。當(dāng)Oracle數(shù)據(jù)庫(kù)發(fā)生TX鎖等待時(shí),如果不及時(shí)處理常常會(huì)引起Oracle數(shù)據(jù)庫(kù)掛起,或?qū)е滤梨i的發(fā)生,產(chǎn)生ORA-60的錯(cuò)誤。這些現(xiàn)象都會(huì)對(duì)實(shí)際應(yīng)用產(chǎn)生極大的危害,如長(zhǎng)時(shí)間未響應(yīng),大量事務(wù)失敗等。 悲觀封鎖和樂(lè)觀封鎖 一、悲觀封鎖 鎖在用戶修改之前就發(fā)揮作用: Select ..for update(nowait) Select * from tab1 for update 用戶發(fā)出這條命令之后,oracle將會(huì)對(duì)返回集中的數(shù)據(jù)建立行級(jí)封鎖,以防止其他用戶的修改。 如果此時(shí)其他用戶對(duì)上面返回結(jié)果集的數(shù)據(jù)進(jìn)行dml或ddl操作都會(huì)返回一個(gè)錯(cuò)誤信息或發(fā)生阻塞。 1:對(duì)返回結(jié)果集進(jìn)行update或delete操作會(huì)發(fā)生阻塞。 2:對(duì)該表進(jìn)行ddl操作將會(huì)報(bào):Ora-00054:resource busy and acquire with nowait specified. 原因分析 此時(shí)Oracle已經(jīng)對(duì)返回的結(jié)果集上加了排它的行級(jí)鎖,所有其他對(duì)這些數(shù)據(jù)進(jìn)行的修改或刪除操作都必須等待這個(gè)鎖的釋放,產(chǎn)生的外在現(xiàn)象就是其他的操作將發(fā)生阻塞,這個(gè)這個(gè)操作commit或rollback. 同樣這個(gè)查詢的事務(wù)將會(huì)對(duì)該表加表級(jí)鎖,不允許對(duì)該表的任何ddl操作,否則將會(huì)報(bào)出ora-00054錯(cuò)誤::resource busy and acquire with nowait specified. 二、樂(lè)觀封鎖 樂(lè)觀的認(rèn)為數(shù)據(jù)在select出來(lái)到update進(jìn)取并提交的這段時(shí)間數(shù)據(jù)不會(huì)被更改。這里面有一種潛在的危險(xiǎn)就是由于被選出的結(jié)果集并沒(méi)有被鎖定,是存在一種可能被其他用戶更改的可能。因此Oracle仍然建議是用悲觀封鎖,因?yàn)檫@樣會(huì)更安全。 阻塞 定義: 當(dāng)一個(gè)會(huì)話保持另一個(gè)會(huì)話正在請(qǐng)求的資源上的鎖定時(shí),就會(huì)發(fā)生阻塞。被阻塞的會(huì)話將一直掛起,直到持有鎖的會(huì)話放棄鎖定的資源為止。4個(gè)常見(jiàn)的dml語(yǔ)句會(huì)產(chǎn)生阻塞 INSERT UPDATE DELETE SELECT…FOR UPDATE INSERT Insert發(fā)生阻塞的唯一情況就是用戶擁有一個(gè)建有主鍵約束的表。當(dāng)2個(gè)的會(huì)話同時(shí)試圖向表中插入相同的數(shù)據(jù)時(shí),其中的一個(gè)會(huì)話將被阻塞,直到另外一個(gè)會(huì)話提交或會(huì)滾。一個(gè)會(huì)話提交時(shí),另一個(gè)會(huì)話將收到主鍵重復(fù)的錯(cuò)誤。回滾時(shí),被阻塞的會(huì)話將繼續(xù)執(zhí)行。 UPDATE 和DELETE當(dāng)執(zhí)行Update和delete操作的數(shù)據(jù)行已經(jīng)被另外的會(huì)話鎖定時(shí),將會(huì)發(fā)生阻塞,直到另一個(gè)會(huì)話提交或會(huì)滾。 Select …for update 當(dāng)一個(gè)用戶發(fā)出select..for update的錯(cuò)作準(zhǔn)備對(duì)返回的結(jié)果集進(jìn)行修改時(shí),如果結(jié)果集已經(jīng)被另一個(gè)會(huì)話鎖定,就是發(fā)生阻塞。需要等另一個(gè)會(huì)話結(jié)束之后才可繼續(xù)執(zhí)行。可以通過(guò)發(fā)出 select… for update nowait的語(yǔ)句來(lái)避免發(fā)生阻塞,如果資源已經(jīng)被另一個(gè)會(huì)話鎖定,則會(huì)返回以下錯(cuò)誤:Ora-00054:resource busy and acquire with nowait specified. 死鎖-deadlock 定義:當(dāng)兩個(gè)用戶希望持有對(duì)方的資源時(shí)就會(huì)發(fā)生死鎖. 即兩個(gè)用戶互相等待對(duì)方釋放資源時(shí),oracle認(rèn)定為產(chǎn)生了死鎖,在這種情況下,將以犧牲一個(gè)用戶作為代價(jià),另一個(gè)用戶繼續(xù)執(zhí)行,犧牲的用戶的事務(wù)將回滾. 例子: 1:用戶1對(duì)A表進(jìn)行Update,沒(méi)有提交。 2:用戶2對(duì)B表進(jìn)行Update,沒(méi)有提交。 此時(shí)雙反不存在資源共享的問(wèn)題。 3:如果用戶2此時(shí)對(duì)A表作update,則會(huì)發(fā)生阻塞,需要等到用戶一的事物結(jié)束。 4:如果此時(shí)用戶1又對(duì)B表作update,則產(chǎn)生死鎖。此時(shí)Oracle會(huì)選擇其中一個(gè)用戶進(jìn)行會(huì)滾,使另一個(gè)用戶繼續(xù)執(zhí)行操作。 起因: Oracle的死鎖問(wèn)題實(shí)際上很少見(jiàn),如果發(fā)生,基本上都是不正確的程序設(shè)計(jì)造成的,經(jīng)過(guò)調(diào)整后,基本上都會(huì)避免死鎖的發(fā)生。 DML鎖分類表 表1Oracle的TM鎖類型 鎖模式 鎖描述 解釋 SQL操作 0 none 1 NULL 空 Select 2 SS(Row-S) 行級(jí)共享鎖,其他對(duì)象 只能查詢這些數(shù)據(jù)行 Select for update、Lock for update、Lock row share 3 SX(Row-X) 行級(jí)排它鎖, 在提交前不允許做DML操作 Insert、Update、 Delete、Lock row share 4 S(Share) 共享鎖 Create index、Lock share 5 SSX(S/Row-X) 共享行級(jí)排它鎖 Lock share row exclusive 6 X(Exclusive) 排它鎖 Alter table、Drop able、Drop index、Truncate table 、Lock exclusive oracle 鎖問(wèn)題的解決 可以用Spotlight軟件對(duì)數(shù)據(jù)庫(kù)的運(yùn)行狀態(tài)進(jìn)行監(jiān)控。 當(dāng)出現(xiàn)session鎖時(shí),我們要及時(shí)進(jìn)行處理. 1. 查看哪些session鎖: SQL語(yǔ)句:select 'alter system kill session '''||sid||','||serial#||''';' from v$session where sid in (select sid from v$lock where block = 1); SQL> select 'alter system kill session '''||sid||','||serial#||''';' from v$session where sid in (select sid from v$lock where block = 1); 'ALTERSYSTEMKILLSESSION'''||SID||','||SERIAL#||''';' -------------------------------------------------------------------------------- alter system kill session '132,731'; alter system kill session '275,15205'; alter system kill session '308,206'; alter system kill session '407,3510'; 2. 查看session鎖. sql語(yǔ)句:select s.sid, q.sql_text from v$sqltext q, v$session s where q.address = s.sql_address and s.sid = &sid order by piece; SQL> select s.sid,q.sql_text from v$sqltext q, v$session s where q.address = s.sql_address and s.sid in (select sid from v$lock where block = 1) order by piece; SID SQL_TEXT ---------- ---------------------------------------------------------------- 77 UPDATE PROFILE_USER SET ID=1,COMPANY_ID=2,CUSTOMER_ID=3,NAMED 77 _INSURED_ID=4,LOGIN=5,ROLE_ID=6,PASSWORD=7,EMAIL=8,TIME_ZON 77 E=9 WHERE PROFILE_USER.ID=:34 3 rows selected. 3. kill鎖的進(jìn)程. SQL語(yǔ)句:alter system kill session '77,22198'; SQL> alter system kill session '391,48398'; System altered. 對(duì)for update的使用在日常中,我們對(duì)for update的使用還是比較普遍的,特別是在如pl/sql developer中手工修改數(shù)據(jù)。此時(shí)只是覺(jué)得方便,而對(duì)for update真正的含義缺乏理解。For update是Oracle提供的手工提高鎖級(jí)別和范圍的特例語(yǔ)句。Oracle的鎖機(jī)制是目前各類型數(shù)據(jù)庫(kù)鎖機(jī)制中比較優(yōu)秀的。所以,Oracle認(rèn)為一般不需要用戶和應(yīng)用直接進(jìn)行鎖的控制和提升。甚至認(rèn)為死鎖這類鎖相關(guān)問(wèn)題的出現(xiàn)場(chǎng)景,大都與手工提升鎖有關(guān)。所以,Oracle并不推薦使用for update作為日常開(kāi)發(fā)使用。而且,在平時(shí)開(kāi)發(fā)和運(yùn)維中,使用了for update卻忘記提交,會(huì)引起很多鎖表故障。那么,什么時(shí)候需要使用for update?就是那些需要業(yè)務(wù)層面數(shù)據(jù)獨(dú)占時(shí),可以考慮使用for update。場(chǎng)景上,比如火車票訂票,在屏幕上顯示郵票,而真正進(jìn)行出票時(shí),需要重新確定一下這個(gè)數(shù)據(jù)沒(méi)有被其他客戶端修改。所以,在這個(gè)確認(rèn)過(guò)程中,可以使用for update。這是統(tǒng)一的解決方案方案問(wèn)題,需要前期有所準(zhǔn)備Select …forupdate語(yǔ)句是我們經(jīng)常使用手工加鎖語(yǔ)句。通常情況下,select語(yǔ)句是不會(huì)對(duì)數(shù)據(jù)加鎖,妨礙影響其他的DML和DDL操作。同時(shí),在多版本一致讀機(jī)制的支持下,select語(yǔ)句也不會(huì)被其他類型語(yǔ)句所阻礙。借助for update子句,我們可以在應(yīng)用程序的層面手工實(shí)現(xiàn)數(shù)據(jù)加鎖保護(hù)操作。本篇我們就來(lái)介紹一下這個(gè)子句的用法和功能。下面是采自O(shè)racle官方文檔《SQLLanguage Reference》中關(guān)于for update子句的說(shuō)明:(請(qǐng)雙擊點(diǎn)開(kāi)圖片查看)從for update子句的語(yǔ)法狀態(tài)圖中,我們可以看出該子句分為兩個(gè)部分:加鎖范圍子句和加鎖行為子句。下面我們分別針對(duì)兩個(gè)方面的進(jìn)行介紹。加鎖范圍子句在select…for update之后,可以使用of子句選擇對(duì)select的特定數(shù)據(jù)表進(jìn)行加鎖操作。默認(rèn)情況下,不使用of子句表示在select所有的數(shù)據(jù)表中加鎖。//采用默認(rèn)格式for updateSQL> 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$lock和v$locked_object視圖,可以看到鎖信息。//事務(wù)信息視圖SQL> select addr,xidusn,xidslot,xidsqn from v$transaction;ADDR XIDUSN XIDSLOT XIDSQN-------- ---------- ---------- ----------377DB5D0 7 19 808//鎖對(duì)象信息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 0B7DE8A44 36 TM 73181 0 3 0 0377DB5D0 36 TX 458771 808 6 0 0從上面的情況看,默認(rèn)情況下的for update語(yǔ)句,效果相當(dāng)于啟動(dòng)了一個(gè)會(huì)話級(jí)別的事務(wù),在對(duì)應(yīng)的數(shù)據(jù)表(select所涉及的所有數(shù)據(jù)表)上加入一個(gè)數(shù)據(jù)表級(jí)共享鎖(TM,lmode=3)。同時(shí),在對(duì)應(yīng)的數(shù)據(jù)行中加入獨(dú)占鎖(TX,lmode=6)。根據(jù)我們以前的知識(shí),如果此時(shí)有另一個(gè)會(huì)話視圖獲取對(duì)應(yīng)數(shù)據(jù)行的獨(dú)占權(quán)限(無(wú)論是用update/delete還是另一個(gè)for update),都會(huì)以block而告終。SQL> select sid from v$mystat where rownum<2;SID----------37SQL> 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 037E80ED4 37 AE 100 0 4 0 037E80F48 37 TX 458771 808 0 6 0B7DE8A44 37 TM 73181 0 3 0 0B7DE8A44 36 TM 73181 0 3 0 0377DB5D0 36 TX 458771 808 6 0 16 rows selectedSQL> 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語(yǔ)句使用的一個(gè)范圍說(shuō)明標(biāo)記。從官方的語(yǔ)法結(jié)構(gòu)看,后面可以跟一個(gè)或者多個(gè)數(shù)據(jù)列列表。這種語(yǔ)法場(chǎng)景常常使用在進(jìn)行連接查詢的select中,對(duì)其中一張數(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.00SQL> 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 0B7E1C2E8 36 TM 73181 0 3 0 0377DBC0C 36 TX 65566 747 6 0 0上面的語(yǔ)句中,我們看到使用for update of指定數(shù)據(jù)列之后,鎖定的范圍限制在了所在的數(shù)據(jù)表。也就是說(shuō),當(dāng)我們使用連接查詢配合of子句的時(shí)候,可以實(shí)現(xiàn)有針對(duì)性的鎖定。同樣在連接查詢的時(shí)候,如果沒(méi)有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.00SQL> 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 0B7E1C2E8 36 TM 73179 0 3 0 0B7E1C2E8 36 TM 73181 0 3 0 0377DBC0C 36 TX 458777 805 6 0 0SQL> select owner,object_name from dba_objects where object_id=73179;OWNER OBJECT_NAME------------------------------ --------------------------------------------------------------------------------SCOTT DEPT明顯可以看到,當(dāng)我們沒(méi)有使用of子句的時(shí)候,默認(rèn)就是對(duì)所有select的數(shù)據(jù)表進(jìn)行l(wèi)ock操作。加鎖行為子句加鎖行為子句相對(duì)比較容易理解。這里分別介紹。Nowait子句當(dāng)我們進(jìn)行for update的操作時(shí),與普通select存在很大不同。一般select是不需要考慮數(shù)據(jù)是否被鎖定,最多根據(jù)多版本一致讀的特性讀取之前的版本。加入for update之后,Oracle就要求啟動(dòng)一個(gè)新事務(wù),嘗試對(duì)數(shù)據(jù)進(jìn)行加鎖。如果當(dāng)前已經(jīng)被加鎖,默認(rèn)的行為必然是block等待。使用nowait子句的作用就是避免進(jìn)行等待,當(dāng)發(fā)現(xiàn)請(qǐng)求加鎖資源被鎖定未釋放的時(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 207499 ALLEN SALESMAN 76981981-2-20 1600.00 300.00 307521 WARD SALESMAN 76981981-2-22 1250.00 500.00 307566 JONES MANAGER 78391981-4-2 2975.00 20//變換session,進(jìn)行執(zhí)行。SQL> select * from emp for update nowait;select * from emp for update nowaitORA-00054:資源正忙,但指定以NOWAIT方式獲取資源,或者超時(shí)失效對(duì)應(yīng)的還有就是wait子句,也就是默認(rèn)的for update行為。一旦發(fā)現(xiàn)對(duì)應(yīng)資源被鎖定,就等待blocking,直到資源被釋放或者用戶強(qiáng)制終止命令。對(duì)wait子句還存在一個(gè)數(shù)據(jù)參數(shù)位,表示當(dāng)出現(xiàn)blocking等待的時(shí)候最多等待多長(zhǎng)時(shí)間。單位是秒級(jí)別。//接上面的案例SQL> select * from emp for update wait 3;select * from emp for update wait 3ORA-30006:資源已被占用;執(zhí)行操作時(shí)出現(xiàn)WAIT超時(shí)Skip locked參數(shù)Skip locked參數(shù)是最新引入到for update語(yǔ)句中的一個(gè)參數(shù)。簡(jiǎn)單的說(shuō),就是在對(duì)數(shù)據(jù)行進(jìn)行加鎖操作時(shí),如果發(fā)現(xiàn)數(shù)據(jù)行被鎖定,就跳過(guò)處理。這樣for update就只針對(duì)未加鎖的數(shù)據(jù)行進(jìn)行處理加鎖。//session1中,對(duì)一部分?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 207499 ALLEN SALESMAN 76981981-2-20 1600.00 300.00 307521 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 1011 rows selected總數(shù)據(jù)一共14行。Session1中,先lock住了3行數(shù)據(jù)。之后的seesion2中,由于使用的skip locked子句參數(shù),將剩下的11條數(shù)據(jù)進(jìn)行讀取到并且加鎖。 --------------------------------------------------------------- Oracle 的for update行鎖鍵字: oracle 的for update行鎖 SELECT...FOR UPDATE 語(yǔ)句的語(yǔ)法如下: SELECT ... FOR UPDATE [OF column_list][WAIT n|NOWAIT][SKIP LOCKED]; 其中: OF 子句用于指定即將更新的列,即鎖定行上的特定列。 WAIT 子句指定等待其他用戶釋放鎖的秒數(shù),防止無(wú)限期的等待。 “使用FOR UPDATE WAIT”子句的優(yōu)點(diǎn)如下: 1防止無(wú)限期地等待被鎖定的行; 2允許應(yīng)用程序中對(duì)鎖的等待時(shí)間進(jìn)行更多的控制。 3對(duì)于交互式應(yīng)用程序非常有用,因?yàn)檫@些用戶不能等待不確定 4 若使用了skip locked,則可以越過(guò)鎖定的行,不會(huì)報(bào)告由wait n 引發(fā)的‘資源忙’異常報(bào)告示例: create table t(a varchar2(20),b varchar2(20)); insert into t values('1','1'); insert into t values('2','2'); insert into t values('3','3'); insert into t values('4','4'); 現(xiàn)在執(zhí)行如下操作: 在plsql develope中打開(kāi)兩個(gè)sql窗口, 在1窗口中運(yùn)行sql select * from t where a='1' for update; 在2窗口中運(yùn)行sql1 1. select * from t where a='1'; 這一點(diǎn)問(wèn)題也沒(méi)有,因?yàn)樾屑?jí)鎖不會(huì)影響純粹的select語(yǔ)句 再運(yùn)行sql2 2. select * from t where a='1' for update; 則這一句sql在執(zhí)行時(shí),永遠(yuǎn)處于等待狀態(tài),除非窗口1中sql被提交或回滾。 如何才能讓sql2不等待或等待指定的時(shí)間呢? 我們?cè)龠\(yùn)行sql3 3. select * from t where a='1' for update nowait; 則在執(zhí)行此sql時(shí),直接報(bào)資源忙的異常。 若執(zhí)行 select * from t where a='1' for update wait 6; 則在等待6秒后,報(bào) 資源忙的異常。 如果我們執(zhí)行sql4 4. select * from t where a='1' for update nowait skip Locked; 則執(zhí)行sql時(shí),即不等待,也不報(bào)資源忙異常。 現(xiàn)在我們看看執(zhí)行如下操作將會(huì)發(fā)生什么呢? 在窗口1中執(zhí)行: select * from t where rownum<=3 nowait skip Locked; 在窗口2中執(zhí)行: select * from t where rownum<=6 nowait skip Locked; select for update 也就如此了吧,insert、update、delete操作默認(rèn)加行級(jí)鎖,其原理和操作與select for update并無(wú)兩樣。 select for update of,這個(gè)of子句在牽連到多個(gè)表時(shí),具有較大作用,如不使用of指定鎖定的表的列,則所有表的相關(guān)行均被鎖定,若在of中指定了需修改的列,則只有與這些列相關(guān)的表的行才會(huì)被鎖定。--------------------------------- MySQL -----------------------------------------------------MySQL中select * for update鎖表的問(wèn)題頁(yè)級(jí):引擎 BDB。 表級(jí):引擎 MyISAM , 理解為鎖住整個(gè)表,可以同時(shí)讀,寫不行 行級(jí):引擎 INNODB , 單獨(dú)的一行記錄加鎖 表級(jí),直接鎖定整張表,在你鎖定期間,其它進(jìn)程無(wú)法對(duì)該表進(jìn)行寫操作。如果你是寫鎖,則其它進(jìn)程則讀也不允許 行級(jí),,僅對(duì)指定的記錄進(jìn)行加鎖,這樣其它進(jìn)程還是可以對(duì)同一個(gè)表中的其它記錄進(jìn)行操作。 頁(yè)級(jí),表級(jí)鎖速度快,但沖突多,行級(jí)沖突少,但速度慢。所以取了折衷的頁(yè)級(jí),一次鎖定相鄰的一組記錄。 MySQL 5.1支持對(duì)MyISAM和MEMORY表進(jìn)行表級(jí)鎖定,對(duì)BDB表進(jìn)行頁(yè)級(jí)鎖定,對(duì)InnoDB表進(jìn)行行級(jí)鎖定。 對(duì)WRITE,MySQL使用的表鎖定方法原理如下: 如果在表上沒(méi)有鎖,在它上面放一個(gè)寫鎖。 否則,把鎖定請(qǐng)求放在寫鎖定隊(duì)列中。 對(duì)READ,MySQL使用的鎖定方法原理如下: 如果在表上沒(méi)有寫鎖定,把一個(gè)讀鎖定放在它上面 否則,把鎖請(qǐng)求放在讀鎖定隊(duì)列中。 InnoDB使用行鎖定,BDB使用頁(yè)鎖定。對(duì)于這兩種存儲(chǔ)引擎,都可能存在死鎖。這是因?yàn)?#xff0c;在SQL語(yǔ)句處理期間,InnoDB自動(dòng)獲得行鎖定和BDB獲得頁(yè)鎖定,而不是在事務(wù)啟動(dòng)時(shí)獲得。 MySQL中select * for update鎖表的問(wèn)題 由于InnoDB預(yù)設(shè)是Row-Level Lock,所以只有「明確」的指定主鍵,MySQL才會(huì)執(zhí)行Row lock (只鎖住被選取的資料例) ,否則MySQL將會(huì)執(zhí)行Table Lock (將整個(gè)資料表單給鎖住)。 舉個(gè)例子: 假設(shè)有個(gè)表單products ,里面有id跟name二個(gè)欄位,id是主鍵。 例1: (明確指定主鍵,并且有此筆資料,row lock) SELECT * FROM products WHERE id='3' FOR UPDATE; SELECT * FROM products WHERE id='3' and type=1 FOR UPDATE;例2: (明確指定主鍵,若查無(wú)此筆資料,無(wú)lock) SELECT * FROM products WHERE id='-1' FOR UPDATE;例2: (無(wú)主鍵,table lock) SELECT * FROM products WHERE name='Mouse' FOR UPDATE;例3: (主鍵不明確,table lock) SELECT * FROM products WHERE id<>'3' FOR UPDATE;例4: (主鍵不明確,table lock) SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;注1: FOR UPDATE僅適用于InnoDB,且必須在交易區(qū)塊(BEGIN/COMMIT)中才能生效。 注2: 要測(cè)試鎖定的狀況,可以利用MySQL的Command Mode ,開(kāi)二個(gè)視窗來(lái)做測(cè)試。在MySql 5.0中測(cè)試確實(shí)是這樣的 另外:MyAsim 只支持表級(jí)鎖,InnerDB支持行級(jí)鎖 添加了(行級(jí)鎖/表級(jí)鎖)鎖的數(shù)據(jù)不能被其它事務(wù)再鎖定,也不被其它事務(wù)修改(修改、刪除) 是表級(jí)鎖時(shí),不管是否查詢到記錄,都會(huì)鎖定表 ---------------------------------------------------------?
總結(jié)
以上是生活随笔為你收集整理的Oracle 共享锁和排它锁、 DML和DDL锁、 for update 锁表的问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 事务的四大特性、事务处理开始与结束、v$
- 下一篇: oracle解除死锁