:您好!鎖是數(shù)據(jù)庫中的一個非常重要的概念,它主要用于多用戶環(huán)境下保證數(shù)據(jù)庫完整性和一致性。 我們知道,多個用戶能夠同時操縱同一個數(shù)據(jù)庫中的數(shù)據(jù),會發(fā)生數(shù)據(jù)不一致現(xiàn)象。即如果沒有鎖定且多個用戶同時訪問一個數(shù)據(jù)庫
成都創(chuàng)新互聯(lián)公司是一家朝氣蓬勃的網(wǎng)站建設(shè)公司。公司專注于為企業(yè)提供信息化建設(shè)解決方案。從事網(wǎng)站開發(fā),網(wǎng)站制作,網(wǎng)站設(shè)計(jì),網(wǎng)站模板,微信公眾號開發(fā),軟件開發(fā),小程序開發(fā),10年建站對活動板房等多個方面,擁有豐富建站經(jīng)驗(yàn)。
SQL Server數(shù)據(jù)庫發(fā)生死鎖時不會象ORACLE那樣自動生成一個跟蹤文件.
有時可以在[管理]-[當(dāng)前活動] 里看到阻塞信息(有時SQL Server企業(yè)管理器會因?yàn)殒i太多而沒有響應(yīng)).
設(shè)定跟蹤1204:
USE MASTER
DBCC TRACEON (1204,-1)
顯示當(dāng)前啟用的所有跟蹤標(biāo)記的狀態(tài):
DBCC TRACESTATUS(-1)
取消跟蹤1204:
DBCC TRACEOFF (1204,-1)
在設(shè)定跟蹤1204后,會在數(shù)據(jù)庫的日志文件里顯示SQL Server數(shù)據(jù)庫死鎖時一些信息,
但那些信息很難看懂,需要對照SQL Server聯(lián)機(jī)叢書仔細(xì)來看.
根據(jù)PAG鎖要找到相關(guān)數(shù)據(jù)庫表的方法:
DBCC TRACEON (3604)
DBCC PAGE (db_id,file_id,page_no)
DBCC TRACEOFF (3604)
請參考sqlservercentral.com上更詳細(xì)的講解.
從CSDN學(xué)到了一個找到死鎖原因的方法.
我稍加修改, 去掉了游標(biāo)操作并增加了一些提示信息,寫了一個系統(tǒng)存儲過程sp_who_lock.sql.
需要的時候直接調(diào)用:
sp_who_lock
就可以查出引起死鎖的進(jìn)程和SQL語句.
SQL Server自帶的系統(tǒng)存儲過程sp_who和sp_lock也可以用來查找阻塞和死鎖, 但沒有這里介紹的方法好用.
如果想知道其它tracenum參數(shù)的含義,請看文章
我們還可以設(shè)置鎖的超時時間(單位是毫秒), 來縮短死鎖可能影響的時間范圍:
例如:
use master
seelct @@lock_timeout
set lock_timeout 900000
-- 15分鐘
seelct @@lock_timeout
這涉及到數(shù)據(jù)庫中,鎖的概念
首先,SQL Server更強(qiáng)調(diào)由系統(tǒng)來管理鎖。在用戶有SQL請求時,系統(tǒng)分析請求,自動在滿足鎖定條件和系統(tǒng)性能之間為數(shù)據(jù)庫加上適當(dāng)?shù)逆i,同時系統(tǒng)在運(yùn)行期間常常自動進(jìn)行優(yōu)化處理,實(shí)行動態(tài)加鎖。也就是說,你的擔(dān)心是不必要的,SQLServer可以保證這種情況基本不會出現(xiàn).如果特殊情況下,需要你手動出來,請參考下面文檔。
一. 為什么要引入鎖
多個用戶同時對數(shù)據(jù)庫的并發(fā)操作時會帶來以下數(shù)據(jù)不一致的問題:
丟失更新
A,B兩個用戶讀同一數(shù)據(jù)并進(jìn)行修改,其中一個用戶的修改結(jié)果破壞了另一個修改的結(jié)果,比如訂票系統(tǒng)
臟讀
A用戶修改了數(shù)據(jù),隨后B用戶又讀出該數(shù)據(jù),但A用戶因?yàn)槟承┰蛉∠藢?shù)據(jù)的修改,數(shù)據(jù)恢復(fù)原值,此時B得到的數(shù)據(jù)就與數(shù)據(jù)庫內(nèi)的數(shù)據(jù)產(chǎn)生了不一致
不可重復(fù)讀
A用戶讀取數(shù)據(jù),隨后B用戶讀出該數(shù)據(jù)并修改,此時A用戶再讀取數(shù)據(jù)時發(fā)現(xiàn)前后兩次的值不一致
并發(fā)控制的主要方法是封鎖,鎖就是在一段時間內(nèi)禁止用戶做某些操作以避免產(chǎn)生數(shù)據(jù)不一致
二 鎖的分類
鎖的類別有兩種分法:
1. 從數(shù)據(jù)庫系統(tǒng)的角度來看:分為獨(dú)占鎖(即排它鎖),共享鎖和更新鎖
MS-SQL Server 使用以下資源鎖模式。
鎖模式 描述
共享 (S) 用于不更改或不更新數(shù)據(jù)的操作(只讀操作),如 SELECT 語句。
更新 (U) 用于可更新的資源中。防止當(dāng)多個會話在讀取、鎖定以及隨后可能進(jìn)行的資源更新時發(fā)生常見形式的死鎖。
排它 (X) 用于數(shù)據(jù)修改操作,例如 INSERT、UPDATE 或 DELETE。確保不會同時同一資源進(jìn)行多重更新。
意向鎖 用于建立鎖的層次結(jié)構(gòu)。意向鎖的類型為:意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
架構(gòu)鎖 在執(zhí)行依賴于表架構(gòu)的操作時使用。架構(gòu)鎖的類型為:架構(gòu)修改 (Sch-M) 和架構(gòu)穩(wěn)定性 (Sch-S)。
大容量更新 (BU) 向表中大容量復(fù)制數(shù)據(jù)并指定了 TABLOCK 提示時使用。
共享鎖
共享 (S) 鎖允許并發(fā)事務(wù)讀取 (SELECT) 一個資源。資源上存在共享 (S) 鎖時,任何其它事務(wù)都不能修改數(shù)據(jù)。一旦已經(jīng)讀取數(shù)據(jù),便立即釋放資源上的共享 (S) 鎖,除非將事務(wù)隔離級別設(shè)置為可重復(fù)讀或更高級別,或者在事務(wù)生存周期內(nèi)用鎖定提示保留共享 (S) 鎖。
更新鎖
更新 (U) 鎖可以防止通常形式的死鎖。一般更新模式由一個事務(wù)組成,此事務(wù)讀取記錄,獲取資源(頁或行)的共享 (S) 鎖,然后修改行,此操作要求鎖轉(zhuǎn)換為排它 (X) 鎖。如果兩個事務(wù)獲得了資源上的共享模式鎖,然后試圖同時更新數(shù)據(jù),則一個事務(wù)嘗試將鎖轉(zhuǎn)換為排它 (X) 鎖。共享模式到排它鎖的轉(zhuǎn)換必須等待一段時間,因?yàn)橐粋€事務(wù)的排它鎖與其它事務(wù)的共享模式鎖不兼容;發(fā)生鎖等待。第二個事務(wù)試圖獲取排它 (X) 鎖以進(jìn)行更新。由于兩個事務(wù)都要轉(zhuǎn)換為排它 (X) 鎖,并且每個事務(wù)都等待另一個事務(wù)釋放共享模式鎖,因此發(fā)生死鎖。
若要避免這種潛在的死鎖問題,請使用更新 (U) 鎖。一次只有一個事務(wù)可以獲得資源的更新 (U) 鎖。如果事務(wù)修改資源,則更新 (U) 鎖轉(zhuǎn)換為排它 (X) 鎖。否則,鎖轉(zhuǎn)換為共享鎖。
排它鎖
排它 (X) 鎖可以防止并發(fā)事務(wù)對資源進(jìn)行訪問。其它事務(wù)不能讀取或修改排它 (X) 鎖鎖定的數(shù)據(jù)。
意向鎖
意向鎖表示 SQL Server 需要在層次結(jié)構(gòu)中的某些底層資源上獲取共享 (S) 鎖或排它 (X) 鎖。例如,放置在表級的共享意向鎖表示事務(wù)打算在表中的頁或行上放置共享 (S) 鎖。在表級設(shè)置意向鎖可防止另一個事務(wù)隨后在包含那一頁的表上獲取排它 (X) 鎖。意向鎖可以提高性能,因?yàn)?SQL Server 僅在表級檢查意向鎖來確定事務(wù)是否可以安全地獲取該表上的鎖。而無須檢查表中的每行或每頁上的鎖以確定事務(wù)是否可以鎖定整個表。
意向鎖包括意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
鎖模式 描述
意向共享 (IS) 通過在各資源上放置 S 鎖,表明事務(wù)的意向是讀取層次結(jié)構(gòu)中的部分(而不是全部)底層資源。
意向排它 (IX) 通過在各資源上放置 X 鎖,表明事務(wù)的意向是修改層次結(jié)構(gòu)中的部分(而不是全部)底層資源。IX 是 IS 的超集。
與意向排它共享 (SIX) 通過在各資源上放置 IX 鎖,表明事務(wù)的意向是讀取層次結(jié)構(gòu)中的全部底層資源并修改部分(而不是全部)底層資源。允許頂層資源上的并發(fā) IS 鎖。例如,表的 SIX 鎖在表上放置一個 SIX 鎖(允許并發(fā) IS 鎖),在當(dāng)前所修改頁上放置 IX 鎖(在已修改行上放置 X 鎖)。雖然每個資源在一段時間內(nèi)只能有一個 SIX 鎖,以防止其它事務(wù)對資源進(jìn)行更新,但是其它事務(wù)可以通過獲取表級的 IS 鎖來讀取層次結(jié)構(gòu)中的底層資源。
獨(dú)占鎖:只允許進(jìn)行鎖定操作的程序使用,其他任何對他的操作均不會被接受。執(zhí)行數(shù)據(jù)更新命令時,SQL Server會自動使用獨(dú)占鎖。當(dāng)對象上有其他鎖存在時,無法對其加獨(dú)占鎖。
共享鎖:共享鎖鎖定的資源可以被其他用戶讀取,但其他用戶無法修改它,在執(zhí)行Select時,SQL Server會對對象加共享鎖。
更新鎖:當(dāng)SQL Server準(zhǔn)備更新數(shù)據(jù)時,它首先對數(shù)據(jù)對象作更新鎖鎖定,這樣數(shù)據(jù)將不能被修改,但可以讀取。等到SQL Server確定要進(jìn)行更新數(shù)據(jù)操作時,他會自動將更新鎖換為獨(dú)占鎖,當(dāng)對象上有其他鎖存在時,無法對其加更新鎖。
2. 從程序員的角度看:分為樂觀鎖和悲觀鎖。
樂觀鎖:完全依靠數(shù)據(jù)庫來管理鎖的工作。
悲觀鎖:程序員自己管理數(shù)據(jù)或?qū)ο笊系逆i處理。
MS-SQLSERVER 使用鎖在多個同時在數(shù)據(jù)庫內(nèi)執(zhí)行修改的用戶間實(shí)現(xiàn)悲觀并發(fā)控制
三 鎖的粒度
鎖粒度是被封鎖目標(biāo)的大小,封鎖粒度小則并發(fā)性高,但開銷大,封鎖粒度大則并發(fā)性低但開銷小
SQL Server支持的鎖粒度可以分為為行、頁、鍵、鍵范圍、索引、表或數(shù)據(jù)庫獲取鎖
資源 描述
RID 行標(biāo)識符。用于單獨(dú)鎖定表中的一行。
鍵 索引中的行鎖。用于保護(hù)可串行事務(wù)中的鍵范圍。
頁 8 千字節(jié) (KB) 的數(shù)據(jù)頁或索引頁。
擴(kuò)展盤區(qū) 相鄰的八個數(shù)據(jù)頁或索引頁構(gòu)成的一組。
表 包括所有數(shù)據(jù)和索引在內(nèi)的整個表。
DB 數(shù)據(jù)庫。
四 鎖定時間的長短
鎖保持的時間長度為保護(hù)所請求級別上的資源所需的時間長度。
用于保護(hù)讀取操作的共享鎖的保持時間取決于事務(wù)隔離級別。采用 READ COMMITTED 的默認(rèn)事務(wù)隔離級別時,只在讀取頁的期間內(nèi)控制共享鎖。在掃描中,直到在掃描內(nèi)的下一頁上獲取鎖時才釋放鎖。如果指定 HOLDLOCK 提示或者將事務(wù)隔離級別設(shè)置為 REPEATABLE READ 或 SERIALIZABLE,則直到事務(wù)結(jié)束才釋放鎖。
根據(jù)為游標(biāo)設(shè)置的并發(fā)選項(xiàng),游標(biāo)可以獲取共享模式的滾動鎖以保護(hù)提取。當(dāng)需要滾動鎖時,直到下一次提取或關(guān)閉游標(biāo)(以先發(fā)生者為準(zhǔn))時才釋放滾動鎖。但是,如果指定 HOLDLOCK,則直到事務(wù)結(jié)束才釋放滾動鎖。
用于保護(hù)更新的排它鎖將直到事務(wù)結(jié)束才釋放。
如果一個連接試圖獲取一個鎖,而該鎖與另一個連接所控制的鎖沖突,則試圖獲取鎖的連接將一直阻塞到:
將沖突鎖釋放而且連接獲取了所請求的鎖。
連接的超時間隔已到期。默認(rèn)情況下沒有超時間隔,但是一些應(yīng)用程序設(shè)置超時間隔以防止無限期等待
五 SQL Server 中鎖的自定義
1 處理死鎖和設(shè)置死鎖優(yōu)先級
死鎖就是多個用戶申請不同封鎖,由于申請者均擁有一部分封鎖權(quán)而又等待其他用戶擁有的部分封鎖而引起的無休止的等待
可以使用SET DEADLOCK_PRIORITY控制在發(fā)生死鎖情況時會話的反應(yīng)方式。如果兩個進(jìn)程都鎖定數(shù)據(jù),并且直到其它進(jìn)程釋放自己的鎖時,每個進(jìn)程才能釋放自己的鎖,即發(fā)生死鎖情況。
2 處理超時和設(shè)置鎖超時持續(xù)時間。
@@LOCK_TIMEOUT 返回當(dāng)前會話的當(dāng)前鎖超時設(shè)置,單位為毫秒
SET LOCK_TIMEOUT 設(shè)置允許應(yīng)用程序設(shè)置語句等待阻塞資源的最長時間。當(dāng)語句等待的時間大于 LOCK_TIMEOUT 設(shè)置時,系統(tǒng)將自動取消阻塞的語句,并給應(yīng)用程序返回"已超過了鎖請求超時時段"的 1222 號錯誤信息
示例
下例將鎖超時期限設(shè)置為 1,800 毫秒。
SET LOCK_TIMEOUT 1800
3) 設(shè)置事務(wù)隔離級別。
4 ) 對 SELECT、INSERT、UPDATE 和 DELETE 語句使用表級鎖定提示。
5) 配置索引的鎖定粒度
可以使用 sp_indexoption 系統(tǒng)存儲過程來設(shè)置用于索引的鎖定粒度
六 查看鎖的信息
1 執(zhí)行 EXEC SP_LOCK 報(bào)告有關(guān)鎖的信息
2 查詢分析器中按Ctrl+2可以看到鎖的信息
七 使用注意事項(xiàng)
如何避免死鎖
1 使用事務(wù)時,盡量縮短事務(wù)的邏輯處理過程,及早提交或回滾事務(wù);
2 設(shè)置死鎖超時參數(shù)為合理范圍,如:3分鐘-10分種;超過時間,自動放棄本次操作,避免進(jìn)程懸掛;
3 優(yōu)化程序,檢查并避免死鎖現(xiàn)象出現(xiàn);
4 .對所有的腳本和SP都要仔細(xì)測試,在正是版本之前。
5 所有的SP都要有錯誤處理(通過@error)
6 一般不要修改SQL SERVER事務(wù)的默認(rèn)級別。不推薦強(qiáng)行加鎖
解決問題 如何對行 表 數(shù)據(jù)庫加鎖
八 幾個有關(guān)鎖的問題
1 如何鎖一個表的某一行
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM table ROWLOCK WHERE id = 1
2 鎖定數(shù)據(jù)庫的一個表
SELECT * FROM table WITH (HOLDLOCK)
加鎖語句:
sybase:
update 表 set col1=col1 where 1=0 ;
MSSQL:
select col1 from 表 (tablockx) where 1=0 ;
oracle:
LOCK TABLE 表 IN EXCLUSIVE MODE ;
加鎖后其它人不可操作,直到加鎖用戶解鎖,用commit或rollback解鎖
幾個例子幫助大家加深印象
設(shè)table1(A,B,C)
A B C
a1 b1 c1
a2 b2 c2
a3 b3 c3
1)排它鎖
新建兩個連接
在第一個連接中執(zhí)行以下語句
begin tran
update table1
set A='aa'
where B='b2'
waitfor delay '00:00:30' --等待30秒
commit tran
在第二個連接中執(zhí)行以下語句
begin tran
select * from table1
where B='b2'
commit tran
若同時執(zhí)行上述兩個語句,則select查詢必須等待update執(zhí)行完畢才能執(zhí)行即要等待30秒
2)共享鎖
在第一個連接中執(zhí)行以下語句
begin tran
select * from table1 holdlock -holdlock人為加鎖
where B='b2'
waitfor delay '00:00:30' --等待30秒
commit tran
在第二個連接中執(zhí)行以下語句
begin tran
select A,C from table1
where B='b2'
update table1
set A='aa'
where B='b2'
commit tran
若同時執(zhí)行上述兩個語句,則第二個連接中的select查詢可以執(zhí)行
而update必須等待第一個事務(wù)釋放共享鎖轉(zhuǎn)為排它鎖后才能執(zhí)行 即要等待30秒
3)死鎖
增設(shè)table2(D,E)
D E
d1 e1
d2 e2
在第一個連接中執(zhí)行以下語句
begin tran
update table1
set A='aa'
where B='b2'
waitfor delay '00:00:30'
update table2
set D='d5'
where E='e1'
commit tran
在第二個連接中執(zhí)行以下語句
begin tran
update table2
set D='d5'
where E='e1'
waitfor delay '00:00:10'
update table1
set A='aa'
where B='b2'
commit tran
同時執(zhí)行,系統(tǒng)會檢測出死鎖,并中止進(jìn)程
補(bǔ)充一點(diǎn):
Sql Server2000支持的表級鎖定提示
HOLDLOCK 持有共享鎖,直到整個事務(wù)完成,應(yīng)該在被鎖對象不需要時立即釋放,等于SERIALIZABLE事務(wù)隔離級別
NOLOCK 語句執(zhí)行時不發(fā)出共享鎖,允許臟讀 ,等于 READ UNCOMMITTED事務(wù)隔離級別
PAGLOCK 在使用一個表鎖的地方用多個頁鎖
READPAST 讓sql server跳過任何鎖定行,執(zhí)行事務(wù),適用于READ UNCOMMITTED事務(wù)隔離級別只跳過RID鎖,不跳過頁,區(qū)域和表鎖
ROWLOCK 強(qiáng)制使用行鎖
TABLOCKX 強(qiáng)制使用獨(dú)占表級鎖,這個鎖在事務(wù)期間阻止任何其他事務(wù)使用這個表
UPLOCK 強(qiáng)制在讀表時使用更新而不用共享鎖
應(yīng)用程序鎖:
應(yīng)用程序鎖就是客戶端代碼生成的鎖,而不是sql server本身生成的鎖
處理應(yīng)用程序鎖的兩個過程
sp_getapplock 鎖定應(yīng)用程序資源
sp_releaseapplock 為應(yīng)用程序資源解鎖
注意: 鎖定數(shù)據(jù)庫的一個表的區(qū)別
SELECT * FROM table WITH (HOLDLOCK) 其他事務(wù)可以讀取表,但不能更新刪除
SELECT * FROM table WITH (TABLOCKX) 其他事務(wù)不能讀取表,更新和刪除
一. 為什么要引入鎖
多個用戶同時對數(shù)據(jù)庫的并發(fā)操作時會帶來以下數(shù)據(jù)不一致的問題:
丟失更新
A,B兩個用戶讀同一數(shù)據(jù)并進(jìn)行修改,其中一個用戶的修改結(jié)果破壞了另一個修改的結(jié)果,比如訂票系統(tǒng)
臟讀
A用戶修改了數(shù)據(jù),隨后B用戶又讀出該數(shù)據(jù),但A用戶因?yàn)槟承┰蛉∠藢?shù)據(jù)的修改,數(shù)據(jù)恢復(fù)原值,此時B得到的數(shù)據(jù)就與數(shù)據(jù)庫內(nèi)的數(shù)據(jù)產(chǎn)生了不一致
不可重復(fù)讀
A用戶讀取數(shù)據(jù),隨后B用戶讀出該數(shù)據(jù)并修改,此時A用戶再讀取數(shù)據(jù)時發(fā)現(xiàn)前后兩次的值不一致
并發(fā)控制的主要方法是封鎖,鎖就是在一段時間內(nèi)禁止用戶做某些操作以避免產(chǎn)生數(shù)據(jù)不一致
二 鎖的分類
鎖的類別有兩種分法:
1. 從數(shù)據(jù)庫系統(tǒng)的角度來看:分為獨(dú)占鎖(即排它鎖),共享鎖和更新鎖
MS-SQL Server 使用以下資源鎖模式。
鎖模式 描述
共享 (S) 用于不更改或不更新數(shù)據(jù)的操作(只讀操作),如 SELECT 語句。
更新 (U) 用于可更新的資源中。防止當(dāng)多個會話在讀取、鎖定以及隨后可能進(jìn)行的資源更新時發(fā)生常見形式的死鎖。
排它 (X) 用于數(shù)據(jù)修改操作,例如 INSERT、UPDATE 或 DELETE。確保不會同時同一資源進(jìn)行多重更新。
意向鎖 用于建立鎖的層次結(jié)構(gòu)。意向鎖的類型為:意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
架構(gòu)鎖 在執(zhí)行依賴于表架構(gòu)的操作時使用。架構(gòu)鎖的類型為:架構(gòu)修改 (Sch-M) 和架構(gòu)穩(wěn)定性 (Sch-S)。
大容量更新 (BU) 向表中大容量復(fù)制數(shù)據(jù)并指定了 TABLOCK 提示時使用。
共享鎖
共享 (S) 鎖允許并發(fā)事務(wù)讀取 (SELECT) 一個資源。資源上存在共享 (S) 鎖時,任何其它事務(wù)都不能修改數(shù)據(jù)。一旦已經(jīng)讀取數(shù)據(jù),便立即釋放資源上的共享 (S) 鎖,除非將事務(wù)隔離級別設(shè)置為可重復(fù)讀或更高級別,或者在事務(wù)生存周期內(nèi)用鎖定提示保留共享 (S) 鎖。
更新鎖
更新 (U) 鎖可以防止通常形式的死鎖。一般更新模式由一個事務(wù)組成,此事務(wù)讀取記錄,獲取資源(頁或行)的共享 (S) 鎖,然后修改行,此操作要求鎖轉(zhuǎn)換為排它 (X) 鎖。如果兩個事務(wù)獲得了資源上的共享模式鎖,然后試圖同時更新數(shù)據(jù),則一個事務(wù)嘗試將鎖轉(zhuǎn)換為排它 (X) 鎖。共享模式到排它鎖的轉(zhuǎn)換必須等待一段時間,因?yàn)橐粋€事務(wù)的排它鎖與其它事務(wù)的共享模式鎖不兼容;發(fā)生鎖等待。第二個事務(wù)試圖獲取排它 (X) 鎖以進(jìn)行更新。由于兩個事務(wù)都要轉(zhuǎn)換為排它 (X) 鎖,并且每個事務(wù)都等待另一個事務(wù)釋放共享模式鎖,因此發(fā)生死鎖。
若要避免這種潛在的死鎖問題,請使用更新 (U) 鎖。一次只有一個事務(wù)可以獲得資源的更新 (U) 鎖。如果事務(wù)修改資源,則更新 (U) 鎖轉(zhuǎn)換為排它 (X) 鎖。否則,鎖轉(zhuǎn)換為共享鎖。
排它鎖
排它 (X) 鎖可以防止并發(fā)事務(wù)對資源進(jìn)行訪問。其它事務(wù)不能讀取或修改排它 (X) 鎖鎖定的數(shù)據(jù)。
意向鎖
意向鎖表示 SQL Server 需要在層次結(jié)構(gòu)中的某些底層資源上獲取共享 (S) 鎖或排它 (X) 鎖。例如,放置在表級的共享意向鎖表示事務(wù)打算在表中的頁或行上放置共享 (S) 鎖。在表級設(shè)置意向鎖可防止另一個事務(wù)隨后在包含那一頁的表上獲取排它 (X) 鎖。意向鎖可以提高性能,因?yàn)?SQL Server 僅在表級檢查意向鎖來確定事務(wù)是否可以安全地獲取該表上的鎖。而無須檢查表中的每行或每頁上的鎖以確定事務(wù)是否可以鎖定整個表。
意向鎖包括意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
鎖模式 描述
意向共享 (IS) 通過在各資源上放置 S 鎖,表明事務(wù)的意向是讀取層次結(jié)構(gòu)中的部分(而不是全部)底層資源。
意向排它 (IX) 通過在各資源上放置 X 鎖,表明事務(wù)的意向是修改層次結(jié)構(gòu)中的部分(而不是全部)底層資源。IX 是 IS 的超集。
與意向排它共享 (SIX) 通過在各資源上放置 IX 鎖,表明事務(wù)的意向是讀取層次結(jié)構(gòu)中的全部底層資源并修改部分(而不是全部)底層資源。允許頂層資源上的并發(fā) IS 鎖。例如,表的 SIX 鎖在表上放置一個 SIX 鎖(允許并發(fā) IS 鎖),在當(dāng)前所修改頁上放置 IX 鎖(在已修改行上放置 X 鎖)。雖然每個資源在一段時間內(nèi)只能有一個 SIX 鎖,以防止其它事務(wù)對資源進(jìn)行更新,但是其它事務(wù)可以通過獲取表級的 IS 鎖來讀取層次結(jié)構(gòu)中的底層資源。
獨(dú)占鎖:只允許進(jìn)行鎖定操作的程序使用,其他任何對他的操作均不會被接受。執(zhí)行數(shù)據(jù)更新命令時,SQL Server會自動使用獨(dú)占鎖。當(dāng)對象上有其他鎖存在時,無法對其加獨(dú)占鎖。
共享鎖:共享鎖鎖定的資源可以被其他用戶讀取,但其他用戶無法修改它,在執(zhí)行Select時,SQL Server會對對象加共享鎖。
更新鎖:當(dāng)SQL Server準(zhǔn)備更新數(shù)據(jù)時,它首先對數(shù)據(jù)對象作更新鎖鎖定,這樣數(shù)據(jù)將不能被修改,但可以讀取。等到SQL Server確定要進(jìn)行更新數(shù)據(jù)操作時,他會自動將更新鎖換為獨(dú)占鎖,當(dāng)對象上有其他鎖存在時,無法對其加更新鎖。
2. 從程序員的角度看:分為樂觀鎖和悲觀鎖。
樂觀鎖:完全依靠數(shù)據(jù)庫來管理鎖的工作。
悲觀鎖:程序員自己管理數(shù)據(jù)或?qū)ο笊系逆i處理。
MS-SQLSERVER 使用鎖在多個同時在數(shù)據(jù)庫內(nèi)執(zhí)行修改的用戶間實(shí)現(xiàn)悲觀并發(fā)控制
三 鎖的粒度
鎖粒度是被封鎖目標(biāo)的大小,封鎖粒度小則并發(fā)性高,但開銷大,封鎖粒度大則并發(fā)性低但開銷小
SQL Server支持的鎖粒度可以分為為行、頁、鍵、鍵范圍、索引、表或數(shù)據(jù)庫獲取鎖
資源 描述
RID 行標(biāo)識符。用于單獨(dú)鎖定表中的一行。
鍵 索引中的行鎖。用于保護(hù)可串行事務(wù)中的鍵范圍。
頁 8 千字節(jié) (KB) 的數(shù)據(jù)頁或索引頁。
擴(kuò)展盤區(qū) 相鄰的八個數(shù)據(jù)頁或索引頁構(gòu)成的一組。
表 包括所有數(shù)據(jù)和索引在內(nèi)的整個表。
DB 數(shù)據(jù)庫。
四 鎖定時間的長短
鎖保持的時間長度為保護(hù)所請求級別上的資源所需的時間長度。
用于保護(hù)讀取操作的共享鎖的保持時間取決于事務(wù)隔離級別。采用 READ COMMITTED 的默認(rèn)事務(wù)隔離級別時,只在讀取頁的期間內(nèi)控制共享鎖。在掃描中,直到在掃描內(nèi)的下一頁上獲取鎖時才釋放鎖。如果指定 HOLDLOCK 提示或者將事務(wù)隔離級別設(shè)置為 REPEATABLE READ 或 SERIALIZABLE,則直到事務(wù)結(jié)束才釋放鎖。
根據(jù)為游標(biāo)設(shè)置的并發(fā)選項(xiàng),游標(biāo)可以獲取共享模式的滾動鎖以保護(hù)提取。當(dāng)需要滾動鎖時,直到下一次提取或關(guān)閉游標(biāo)(以先發(fā)生者為準(zhǔn))時才釋放滾動鎖。但是,如果指定 HOLDLOCK,則直到事務(wù)結(jié)束才釋放滾動鎖。
用于保護(hù)更新的排它鎖將直到事務(wù)結(jié)束才釋放。
如果一個連接試圖獲取一個鎖,而該鎖與另一個連接所控制的鎖沖突,則試圖獲取鎖的連接將一直阻塞到:
將沖突鎖釋放而且連接獲取了所請求的鎖。
連接的超時間隔已到期。默認(rèn)情況下沒有超時間隔,但是一些應(yīng)用程序設(shè)置超時間隔以防止無限期等待
五 SQL Server 中鎖的自定義
1 處理死鎖和設(shè)置死鎖優(yōu)先級
死鎖就是多個用戶申請不同封鎖,由于申請者均擁有一部分封鎖權(quán)而又等待其他用戶擁有的部分封鎖而引起的無休止的等待
可以使用SET DEADLOCK_PRIORITY控制在發(fā)生死鎖情況時會話的反應(yīng)方式。如果兩個進(jìn)程都鎖定數(shù)據(jù),并且直到其它進(jìn)程釋放自己的鎖時,每個進(jìn)程才能釋放自己的鎖,即發(fā)生死鎖情況。
2 處理超時和設(shè)置鎖超時持續(xù)時間。
@@LOCK_TIMEOUT 返回當(dāng)前會話的當(dāng)前鎖超時設(shè)置,單位為毫秒
SET LOCK_TIMEOUT 設(shè)置允許應(yīng)用程序設(shè)置語句等待阻塞資源的最長時間。當(dāng)語句等待的時間大于 LOCK_TIMEOUT 設(shè)置時,系統(tǒng)將自動取消阻塞的語句,并給應(yīng)用程序返回"已超過了鎖請求超時時段"的 1222 號錯誤信息
示例
下例將鎖超時期限設(shè)置為 1,800 毫秒。
SET LOCK_TIMEOUT 1800
3) 設(shè)置事務(wù)隔離級別。
4 ) 對 SELECT、INSERT、UPDATE 和 DELETE 語句使用表級鎖定提示。
5) 配置索引的鎖定粒度
可以使用 sp_indexoption 系統(tǒng)存儲過程來設(shè)置用于索引的鎖定粒度
六 查看鎖的信息
1 執(zhí)行 EXEC SP_LOCK 報(bào)告有關(guān)鎖的信息
2 查詢分析器中按Ctrl+2可以看到鎖的信息
七 使用注意事項(xiàng)
如何避免死鎖
1 使用事務(wù)時,盡量縮短事務(wù)的邏輯處理過程,及早提交或回滾事務(wù);
2 設(shè)置死鎖超時參數(shù)為合理范圍,如:3分鐘-10分種;超過時間,自動放棄本次操作,避免進(jìn)程懸掛;
3 優(yōu)化程序,檢查并避免死鎖現(xiàn)象出現(xiàn);
4 .對所有的腳本和SP都要仔細(xì)測試,在正是版本之前。
5 所有的SP都要有錯誤處理(通過@error)
6 一般不要修改SQL SERVER事務(wù)的默認(rèn)級別。不推薦強(qiáng)行加鎖
解決問題 如何對行 表 數(shù)據(jù)庫加鎖
八 幾個有關(guān)鎖的問題
1 如何鎖一個表的某一行
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM table ROWLOCK WHERE id = 1
2 鎖定數(shù)據(jù)庫的一個表
SELECT * FROM table WITH (HOLDLOCK)
加鎖語句:
sybase:
update 表 set col1=col1 where 1=0 ;
MSSQL:
select col1 from 表 (tablockx) where 1=0 ;
oracle:
LOCK TABLE 表 IN EXCLUSIVE MODE ;
加鎖后其它人不可操作,直到加鎖用戶解鎖,用commit或rollback解鎖
幾個例子幫助大家加深印象
設(shè)table1(A,B,C)
A B C
a1 b1 c1
a2 b2 c2
a3 b3 c3
1)排它鎖
新建兩個連接
在第一個連接中執(zhí)行以下語句
begin tran
update table1
set A='aa'
where B='b2'
waitfor delay '00:00:30' --等待30秒
commit tran
在第二個連接中執(zhí)行以下語句
begin tran
select * from table1
where B='b2'
commit tran
若同時執(zhí)行上述兩個語句,則select查詢必須等待update執(zhí)行完畢才能執(zhí)行即要等待30秒
2)共享鎖
在第一個連接中執(zhí)行以下語句
begin tran
select * from table1 holdlock -holdlock人為加鎖
where B='b2'
waitfor delay '00:00:30' --等待30秒
commit tran
在第二個連接中執(zhí)行以下語句
begin tran
select A,C from table1
where B='b2'
update table1
set A='aa'
where B='b2'
commit tran
若同時執(zhí)行上述兩個語句,則第二個連接中的select查詢可以執(zhí)行
而update必須等待第一個事務(wù)釋放共享鎖轉(zhuǎn)為排它鎖后才能執(zhí)行 即要等待30秒
3)死鎖
增設(shè)table2(D,E)
D E
d1 e1
d2 e2
在第一個連接中執(zhí)行以下語句
begin tran
update table1
set A='aa'
where B='b2'
waitfor delay '00:00:30'
update table2
set D='d5'
where E='e1'
commit tran
在第二個連接中執(zhí)行以下語句
begin tran
update table2
set D='d5'
where E='e1'
waitfor delay '00:00:10'
update table1
set A='aa'
where B='b2'
commit tran
同時執(zhí)行,系統(tǒng)會檢測出死鎖,并中止進(jìn)程
補(bǔ)充一點(diǎn):
Sql Server2000支持的表級鎖定提示
HOLDLOCK 持有共享鎖,直到整個事務(wù)完成,應(yīng)該在被鎖對象不需要時立即釋放,等于SERIALIZABLE事務(wù)隔離級別
NOLOCK 語句執(zhí)行時不發(fā)出共享鎖,允許臟讀 ,等于 READ UNCOMMITTED事務(wù)隔離級別
PAGLOCK 在使用一個表鎖的地方用多個頁鎖
READPAST 讓sql server跳過任何鎖定行,執(zhí)行事務(wù),適用于READ UNCOMMITTED事務(wù)隔離級別只跳過RID鎖,不跳過頁,區(qū)域和表鎖
ROWLOCK 強(qiáng)制使用行鎖
TABLOCKX 強(qiáng)制使用獨(dú)占表級鎖,這個鎖在事務(wù)期間阻止任何其他事務(wù)使用這個表
UPLOCK 強(qiáng)制在讀表時使用更新而不用共享鎖
應(yīng)用程序鎖:
應(yīng)用程序鎖就是客戶端代碼生成的鎖,而不是sql server本身生成的鎖
處理應(yīng)用程序鎖的兩個過程
sp_getapplock 鎖定應(yīng)用程序資源
sp_releaseapplock 為應(yīng)用程序資源解鎖
注意: 鎖定數(shù)據(jù)庫的一個表的區(qū)別
SELECT * FROM table WITH (HOLDLOCK) 其他事務(wù)可以讀取表,但不能更新刪除
SELECT * FROM table WITH (TABLOCKX) 其他事務(wù)不能讀取表,更新和刪除
給你個最詳細(xì)的吧可能有你要的內(nèi)容鎖的概述一.為什么要引入鎖多個用戶同時對數(shù)據(jù)庫的并發(fā)操作時會帶來以下數(shù)據(jù)不一致的問題:丟失更新A,B兩個用戶讀同一數(shù)據(jù)并進(jìn)行修改,其中一個用戶的修改結(jié)果破壞了另一個修改的結(jié)果,比如訂票系統(tǒng)臟讀A用戶修改了數(shù)據(jù),隨后B用戶又讀出該數(shù)據(jù),但A用戶因?yàn)槟承┰蛉∠藢?shù)據(jù)的修改,數(shù)據(jù)恢復(fù)原值,此時B得到的數(shù)據(jù)就與數(shù)據(jù)庫內(nèi)的數(shù)據(jù)產(chǎn)生了不一致不可重復(fù)讀A用戶讀取數(shù)據(jù),隨后B用戶讀出該數(shù)據(jù)并修改,此時A用戶再讀取數(shù)據(jù)時發(fā)現(xiàn)前后兩次的值不一致并發(fā)控制的主要方法是封鎖,鎖就是在一段時間內(nèi)禁止用戶做某些操作以避免產(chǎn)生數(shù)據(jù)不一致二鎖的分類鎖的類別有兩種分法:1.從數(shù)據(jù)庫系統(tǒng)的角度來看:分為獨(dú)占鎖(即排它鎖),共享鎖和更新鎖MS-SQLServer使用以下資源鎖模式。鎖模式描述共享(S)用于不更改或不更新數(shù)據(jù)的操作(只讀操作),如SELECT語句。更新(U)用于可更新的資源中。防止當(dāng)多個會話在讀取、鎖定以及隨后可能進(jìn)行的資源更新時發(fā)生常見形式的死鎖。排它(X)用于數(shù)據(jù)修改操作,例如INSERT、UPDATE或DELETE。確保不會同時同一資源進(jìn)行多重更新。意向鎖用于建立鎖的層次結(jié)構(gòu)。意向鎖的類型為:意向共享(IS)、意向排它(IX)以及與意向排它共享(SIX)。架構(gòu)鎖在執(zhí)行依賴于表架構(gòu)的操作時使用。架構(gòu)鎖的類型為:架構(gòu)修改(Sch-M)和架構(gòu)穩(wěn)定性(Sch-S)。大容量更新(BU)向表中大容量復(fù)制數(shù)據(jù)并指定了TABLOCK提示時使用。共享鎖共享(S)鎖允許并發(fā)事務(wù)讀取(SELECT)一個資源。資源上存在共享(S)鎖時,任何其它事務(wù)都不能修改數(shù)據(jù)。一旦已經(jīng)讀取數(shù)據(jù),便立即釋放資源上的共享(S)鎖,除非將事務(wù)隔離級別設(shè)置為可重復(fù)讀或更高級別,或者在事務(wù)生存周期內(nèi)用鎖定提示保留共享(S)鎖。更新鎖更新(U)鎖可以防止通常形式的死鎖。一般更新模式由一個事務(wù)組成,此事務(wù)讀取記錄,獲取資源(頁或行)的共享(S)鎖,然后修改行,此操作要求鎖轉(zhuǎn)換為排它(X)鎖。如果兩個事務(wù)獲得了資源上的共享模式鎖,然后試圖同時更新數(shù)據(jù),則一個事務(wù)嘗試將鎖轉(zhuǎn)換為排它(X)鎖。共享模式到排它鎖的轉(zhuǎn)換必須等待一段時間,因?yàn)橐粋€事務(wù)的排它鎖與其它事務(wù)的共享模式鎖不兼容;發(fā)生鎖等待。第二個事務(wù)試圖獲取排它(X)鎖以進(jìn)行更新。由于兩個事務(wù)都要轉(zhuǎn)換為排它(X)鎖,并且每個事務(wù)都等待另一個事務(wù)釋放共享模式鎖,因此發(fā)生死鎖。若要避免這種潛在的死鎖問題,請使用更新(U)鎖。一次只有一個事務(wù)可以獲得資源的更新(U)鎖。如果事務(wù)修改資源,則更新(U)鎖轉(zhuǎn)換為排它(X)鎖。否則,鎖轉(zhuǎn)換為共享鎖。排它鎖排它(X)鎖可以防止并發(fā)事務(wù)對資源進(jìn)行訪問。其它事務(wù)不能讀取或修改排它(X)鎖鎖定的數(shù)據(jù)。意向鎖意向鎖表示SQLServer需要在層次結(jié)構(gòu)中的某些底層資源上獲取共享(S)鎖或排它(X)鎖。例如,放置在表級的共享意向鎖表示事務(wù)打算在表中的頁或行上放置共享(S)鎖。在表級設(shè)置意向鎖可防止另一個事務(wù)隨后在包含那一頁的表上獲取排它(X)鎖。意向鎖可以提高性能,因?yàn)镾QLServer僅在表級檢查意向鎖來確定事務(wù)是否可以安全地獲取該表上的鎖。而無須檢查表中的每行或每頁上的鎖以確定事務(wù)是否可以鎖定整個表。意向鎖包括意向共享(IS)、意向排它(IX)以及與意向排它共享(SIX)。鎖模式描述意向共享(IS)通過在各資源上放置S鎖,表明事務(wù)的意向是讀取層次結(jié)構(gòu)中的部分(而不是全部)底層資源。意向排它(IX)通過在各資源上放置X鎖,表明事務(wù)的意向是修改層次結(jié)構(gòu)中的部分(而不是全部)底層資源。IX是IS的超集。與意向排它共享(SIX)通過在各資源上放置IX鎖,表明事務(wù)的意向是讀取層次結(jié)構(gòu)中的全部底層資源并修改部分(而不是全部)底層資源。允許頂層資源上的并發(fā)IS鎖。例如,表的SIX鎖在表上放置一個SIX鎖(允許并發(fā)IS鎖),在當(dāng)前所修改頁上放置IX鎖(在已修改行上放置X鎖)。雖然每個資源在一段時間內(nèi)只能有一個SIX鎖,以防止其它事務(wù)對資源進(jìn)行更新,但是其它事務(wù)可以通過獲取表級的IS鎖來讀取層次結(jié)構(gòu)中的底層資源。獨(dú)占鎖:只允許進(jìn)行鎖定操作的程序使用,其他任何對他的操作均不會被接受。執(zhí)行數(shù)據(jù)更新命令時,SQLServer會自動使用獨(dú)占鎖。當(dāng)對象上有其他鎖存在時,無法對其加獨(dú)占鎖。共享鎖:共享鎖鎖定的資源可以被其他用戶讀取,但其他用戶無法修改它,在執(zhí)行Select時,SQLServer會對對象加共享鎖。更新鎖:當(dāng)SQLServer準(zhǔn)備更新數(shù)據(jù)時,它首先對數(shù)據(jù)對象作更新鎖鎖定,這樣數(shù)據(jù)將不能被修改,但可以讀取。等到SQLServer確定要進(jìn)行更新數(shù)據(jù)操作時,他會自動將更新鎖換為獨(dú)占鎖,當(dāng)對象上有其他鎖存在時,無法對其加更新鎖。2.從程序員的角度看:分為樂觀鎖和悲觀鎖。樂觀鎖:完全依靠數(shù)據(jù)庫來管理鎖的工作。悲觀鎖:程序員自己管理數(shù)據(jù)或?qū)ο笊系逆i處理。MS-SQLSERVER使用鎖在多個同時在數(shù)據(jù)庫內(nèi)執(zhí)行修改的用戶間實(shí)現(xiàn)悲觀并發(fā)控制三鎖的粒度鎖粒度是被封鎖目標(biāo)的大小,封鎖粒度小則并發(fā)性高,但開銷大,封鎖粒度大則并發(fā)性低但開銷小SQLServer支持的鎖粒度可以分為為行、頁、鍵、鍵范圍、索引、表或數(shù)據(jù)庫獲取鎖資源描述RID行標(biāo)識符。用于單獨(dú)鎖定表中的一行。鍵索引中的行鎖。用于保護(hù)可串行事務(wù)中的鍵范圍。頁8千字節(jié)(KB)的數(shù)據(jù)頁或索引頁。擴(kuò)展盤區(qū)相鄰的八個數(shù)據(jù)頁或索引頁構(gòu)成的一組。表包括所有數(shù)據(jù)和索引在內(nèi)的整個表。DB數(shù)據(jù)庫。四鎖定時間的長短鎖保持的時間長度為保護(hù)所請求級別上的資源所需的時間長度。用于保護(hù)讀取操作的共享鎖的保持時間取決于事務(wù)隔離級別。采用READCOMMITTED的默認(rèn)事務(wù)隔離級別時,只在讀取頁的期間內(nèi)控制共享鎖。在掃描中,直到在掃描內(nèi)的下一頁上獲取鎖時才釋放鎖。如果指定HOLDLOCK提示或者將事務(wù)隔離級別設(shè)置為REPEATABLEREAD或SERIALIZABLE,則直到事務(wù)結(jié)束才釋放鎖。根據(jù)為游標(biāo)設(shè)置的并發(fā)選項(xiàng),游標(biāo)可以獲取共享模式的滾動鎖以保護(hù)提取。當(dāng)需要滾動鎖時,直到下一次提取或關(guān)閉游標(biāo)(以先發(fā)生者為準(zhǔn))時才釋放滾動鎖。但是,如果指定HOLDLOCK,則直到事務(wù)結(jié)束才釋放滾動鎖。用于保護(hù)更新的排它鎖將直到事務(wù)結(jié)束才釋放。如果一個連接試圖獲取一個鎖,而該鎖與另一個連接所控制的鎖沖突,則試圖獲取鎖的連接將一直阻塞到:將沖突鎖釋放而且連接獲取了所請求的鎖。連接的超時間隔已到期。默認(rèn)情況下沒有超時間隔,但是一些應(yīng)用程序設(shè)置超時間隔以防止無限期等待五SQLServer中鎖的自定義1處理死鎖和設(shè)置死鎖優(yōu)先級死鎖就是多個用戶申請不同封鎖,由于申請者均擁有一部分封鎖權(quán)而又等待其他用戶擁有的部分封鎖而引起的無休止的等待可以使用SETDEADLOCK_PRIORITY控制在發(fā)生死鎖情況時會話的反應(yīng)方式。如果兩個進(jìn)程都鎖定數(shù)據(jù),并且直到其它進(jìn)程釋放自己的鎖時,每個進(jìn)程才能釋放自己的鎖,即發(fā)生死鎖情況。2處理超時和設(shè)置鎖超時持續(xù)時間。@@LOCK_TIMEOUT返回當(dāng)前會話的當(dāng)前鎖超時設(shè)置,單位為毫秒SETLOCK_TIMEOUT設(shè)置允許應(yīng)用程序設(shè)置語句等待阻塞資源的最長時間。當(dāng)語句等待的時間大于LOCK_TIMEOUT設(shè)置時,系統(tǒng)將自動取消阻塞的語句,并給應(yīng)用程序返回"已超過了鎖請求超時時段"的1222號錯誤信息示例下例將鎖超時期限設(shè)置為1,800毫秒。SETLOCK_TIMEOUT18003)設(shè)置事務(wù)隔離級別。4)對SELECT、INSERT、UPDATE和DELETE語句使用表級鎖定提示。5)配置索引的鎖定粒度可以使用sp_indexoption系統(tǒng)存儲過程來設(shè)置用于索引的鎖定粒度六查看鎖的信息1執(zhí)行EXECSP_LOCK報(bào)告有關(guān)鎖的信息2查詢分析器中按Ctrl+2可以看到鎖的信息七使用注意事項(xiàng)如何避免死鎖1使用事務(wù)時,盡量縮短事務(wù)的邏輯處理過程,及早提交或回滾事務(wù);2設(shè)置死鎖超時參數(shù)為合理范圍,如:3分鐘-10分種;超過時間,自動放棄本次操作,避免進(jìn)程懸掛;3優(yōu)化程序,檢查并避免死鎖現(xiàn)象出現(xiàn);4.對所有的腳本和SP都要仔細(xì)測試,在正是版本之前。5所有的SP都要有錯誤處理(通過@error)6一般不要修改SQLSERVER事務(wù)的默認(rèn)級別。不推薦強(qiáng)行加鎖解決問題如何對行表數(shù)據(jù)庫加鎖八幾個有關(guān)鎖的問題1如何鎖一個表的某一行SETTRANSACTIONISOLATIONLEVELREADUNCOMMITTEDSELECT*FROMtableROWLOCKWHEREid=12鎖定數(shù)據(jù)庫的一個表SELECT*FROMtableWITH(HOLDLOCK)加鎖語句:sybase:update表setcol1=col1where1=0;MSSQL:selectcol1from表(tablockx)where1=0;oracle:LOCKTABLE表INEXCLUSIVEMODE;加鎖后其它人不可操作,直到加鎖用戶解鎖,用commit或rollback解鎖幾個例子幫助大家加深印象設(shè)table1(A,B,C)ABCa1b1c1a2b2c2a3b3c31)排它鎖新建兩個連接在第一個連接中執(zhí)行以下語句begintranupdatetable1setA='aa'whereB='b2'waitfordelay'00:00:30'--等待30秒committran在第二個連接中執(zhí)行以下語句begintranselect*fromtable1whereB='b2'committran若同時執(zhí)行上述兩個語句,則select查詢必須等待update執(zhí)行完畢才能執(zhí)行即要等待30秒2)共享鎖在第一個連接中執(zhí)行以下語句begintranselect*fromtable1holdlock-holdlock人為加鎖whereB='b2'waitfordelay'00:00:30'--等待30秒committran在第二個連接中執(zhí)行以下語句begintranselectA,Cfromtable1whereB='b2'updatetable1setA='aa'whereB='b2'committran若同時執(zhí)行上述兩個語句,則第二個連接中的select查詢可以執(zhí)行而update必須等待第一個事務(wù)釋放共享鎖轉(zhuǎn)為排它鎖后才能執(zhí)行即要等待30秒3)死鎖增設(shè)table2(D,E)DEd1e1d2e2在第一個連接中執(zhí)行以下語句begintranupdatetable1setA='aa'whereB='b2'waitfordelay'00:00:30'updatetable2setD='d5'whereE='e1'committran在第二個連接中執(zhí)行以下語句begintranupdatetable2setD='d5'whereE='e1'waitfordelay'00:00:10'updatetable1setA='aa'whereB='b2'committran同時執(zhí)行,系統(tǒng)會檢測出死鎖,并中止進(jìn)程補(bǔ)充一點(diǎn):SqlServer2000支持的表級鎖定提示HOLDLOCK持有共享鎖,直到整個事務(wù)完成,應(yīng)該在被鎖對象不需要時立即釋放,等于SERIALIZABLE事務(wù)隔離級別NOLOCK語句執(zhí)行時不發(fā)出共享鎖,允許臟讀,等于READUNCOMMITTED事務(wù)隔離級別PAGLOCK在使用一個表鎖的地方用多個頁鎖READPAST讓sqlserver跳過任何鎖定行,執(zhí)行事務(wù),適用于READUNCOMMITTED事務(wù)隔離級別只跳過RID鎖,不跳過頁,區(qū)域和表鎖ROWLOCK強(qiáng)制使用行鎖TABLOCKX強(qiáng)制使用獨(dú)占表級鎖,這個鎖在事務(wù)期間阻止任何其他事務(wù)使用這個表UPLOCK強(qiáng)制在讀表時使用更新而不用共享鎖應(yīng)用程序鎖:應(yīng)用程序鎖就是客戶端代碼生成的鎖,而不是sqlserver本身生成的鎖處理應(yīng)用程序鎖的兩個過程sp_getapplock鎖定應(yīng)用程序資源sp_releaseapplock為應(yīng)用程序資源解鎖注意:鎖定數(shù)據(jù)庫的一個表的區(qū)別SELECT*FROMtableWITH(HOLDLOCK)其他事務(wù)可以讀取表,但不能更新刪除SELECT*FROMtableWITH(TABLOCKX)其他事務(wù)不能讀取表,更新和刪除參考資料:
數(shù)據(jù)庫必須有鎖的機(jī)制來確保數(shù)據(jù)的完整和一致性
鎖的類型:
(1) 共享鎖:
共享鎖用于所有的只讀數(shù)據(jù)操作.
(2) 修改鎖:
修改鎖在修改操作的初始化階段用來鎖定可能要被修改的資源,這樣可以避免使用共享鎖造成的死鎖現(xiàn)象
(3) 獨(dú)占鎖:
獨(dú)占鎖是為修改數(shù)據(jù)而保留的。它所鎖定的資源,其他事務(wù)不能讀取也不能修改。獨(dú)占鎖不能和其他鎖兼容。
(4) 架構(gòu)鎖
結(jié)構(gòu)鎖分為結(jié)構(gòu)修改鎖(Sch-M)和結(jié)構(gòu)穩(wěn)定鎖(Sch-S)。執(zhí)行表定義語言操作時,SQL Server采用Sch-M鎖,編譯查詢時,SQL Server采用Sch-S鎖。
(5) 意向鎖
意向鎖說明SQL Server有在資源的低層獲得共享鎖或獨(dú)占鎖的意向。
(6) 批量修改鎖
批量復(fù)制數(shù)據(jù)時使用批量修改鎖