摘自: http://www.myexception.cn/sql-server/385562.htmlhtml
高手進 鎖 nolock,rowlock,tablock,xlock,paglock
鎖 nolock,rowlock,tablock,xlock,paglock
請問大哥,在什麼狀況下用什麼樣的鎖,小弟不太明白。
------解決方案-------------------- SQL code 鎖定提示 描述 HOLDLOCK 將共享鎖保留到事務完成,而不是在相應的表、行或數據頁再也不須要時就當即釋放鎖。HOLDLOCK 等同於 SERIALIZABLE。 NOLOCK 不要發出共享鎖,而且不要提供排它鎖。當此選項生效時,可能會讀取未提交的事務或一組在讀取中間回滾的頁面。有可能發生髒讀。僅應用於 SELECT 語句。 PAGLOCK 在一般使用單個表鎖的地方採用頁鎖。 READCOMMITTED 用與運行在提交讀隔離級別的事務相同的鎖語義執行掃描。默認狀況下,SQL Server 2000 在此隔離級別上操做。 READPAST 跳過鎖定行。此選項致使事務跳過由其它事務鎖定的行(這些行日常會顯示在結果集內),而不是阻塞該事務,使其等待其它事務釋放在這些行上的鎖。READPAST 鎖提示僅適用於運行在提交讀隔離級別的事務,而且只在行級鎖以後讀取。僅適用於 SELECT 語句。 READUNCOMMITTED 等同於 NOLOCK。 REPEATABLEREAD 用與運行在可重複讀隔離級別的事務相同的鎖語義執行掃描。 ROWLOCK 使用行級鎖,而不使用粒度更粗的頁級鎖和表級鎖。 SERIALIZABLE 用與運行在可串行讀隔離級別的事務相同的鎖語義執行掃描。等同於 HOLDLOCK。 TABLOCK 使用表鎖代替粒度更細的行級鎖或頁級鎖。在語句結束前,SQL Server 一直持有該鎖。可是,若是同時指定 HOLDLOCK,那麼在事務結束以前,鎖將被一直持有。 TABLOCKX 使用表的排它鎖。該鎖能夠防止其它事務讀取或更新表,並在語句或事務結束前一直持有。 UPDLOCK 讀取表時使用更新鎖,而不使用共享鎖,並將鎖一直保留到語句或事務的結束。UPDLOCK 的優勢是容許您讀取數據(不阻塞其它事務)並在之後更新數據,同時確保自從上次讀取數據後數據沒有被更改。 XLOCK 使用排它鎖並一直保持到由語句處理的全部數據上的事務結束時。可使用 PAGLOCK 或 TABLOCK 指定該鎖,這種狀況下排它鎖適用於適當級別的粒度 ------解決方案-------------------- SQL code 就啓明星提出的在SQL Server中使用加鎖的問題,我就之前的經驗和收集的一些資料簡單的提出我本身的一些見解,不知道對啓明星是否有所幫助: 通常而言,下面是個典型的打開數據庫的過程。 <% ’遊標類型 Const adOpenForwardOnly = 0 Const adOpenKeyset = 1 Const adOpenDynamic = 2 Const adOpenStatic = 3 ’加鎖類型 Const adLockReadOnly = 1 Const adLockPessimistic = 2 Const adLockOptimistic = 3 Const adLockBatchOptimistic = 4 >% <% set conn = server.createobject(’adodb.connection’) >% <% set rsmov = server.createobject(’adodb.recordset’) >% <% conn.open ’soc’, ’’, ’’ >% <% rsmov.open sqlmov, conn, adopenkeyset, adlockreadonly >% 遊標使用時是比較靈活的,它有時用來描述一個記錄集,有時又是用來描述當前記錄集中某一條記錄的指針。遊標主要是用來創建一個關係數據庫中行/列關係的一種SQL可利用的訪問格。與遊標有關係的技術術語還有一個叫Bookmark的。若是你選擇的遊標方式支持Bookmarks。數據庫將提供有關記錄數目的強大功能。在上面寫出的那麼多遊標方式中,adOpenDynamic是沒有太的用處的,雖然它提供實時顯示數據庫中的記錄的全部更新操做的功能,可是由於並非全部的數據庫都支持該遊標方式,沒有移植性的遊標方式對當前錯綜複雜的數據庫來講真是用處不大。在實際的編程中,我相信你們使用得最頻繁的是adOpenStatic方式,固然這種方式的缺點是不可以就、實時反應出數據庫中內容改變時的情況。若是要想看到數據庫被其它用戶改變的情況,可以使用adOpenKeyse方式(可是它只可以反應出被編輯的改變狀況,也就是說不可以反映出新增和刪除記錄的改變狀況。) 其實上面的內容你們通常均可以在微軟的技術參考資料中找到,下面來講說在使用這些遊標 方式和加鎖方式時要注意到的問題。 1。首先要注意到的是這兩種方式在混合使用時的問題,就是說你同時設置遊標方式和加鎖方式。 除非你是在使用Access數據庫,通常而言當你混合使用時是並不可以獲得你預期想要的遊標方式和加鎖方式的。例如,若是你同時將遊標設置爲adOpenStatic方式,而將加鎖設置爲adLockOptimistic,你將得不到adOpenStatic方式的遊標,你這時使用的遊標方式將是 adOpenKeyset,也就是說你使用ADO的話,它將返回adOpenKeyset的遊標。 2。其次,遊標和加鎖的混合使用還會致使ADO返回的不是你想要的加鎖方式,ADO會改變你的加鎖 方式。例如,在默認狀態下游標方式是adOpenForwardOnly,在使用這種遊標方式的同時若是 你使用的加鎖方式爲-1(就是讓數據源來判斷加鎖方式)或則adLockReadOnly,那麼這種混合方式基本上不支持RecordSet的任何方法,也就是說RecordSet的任何方法將返回False (你的recordcount,absoultpage,addnew,delete,update等都會返回-1,-1就是表示不支持該屬性),可是這時若是你使用的是adOpenForwardOnly遊標方式和其它的加鎖方式混合,它反而 會支持填加,刪除和更新。 -------------------------------------------------------------------------- SELECT 語句中「加鎖選項」的功能說明 SQL Server提供了強大而完備的鎖機制來幫助實現數據庫系統的併發性和高性能。用戶既能使用SQL Server的缺省設置也能夠在select 語句中使用「加鎖選項」來實現預期的效果。 本文介紹了SELECT語句中的各項「加鎖選項」以及相應的功能說明。 功能說明: NOLOCK(不加鎖) 此選項被選中時,SQL Server 在讀取或修改數據時不加任何鎖。 在這種狀況下,用戶有可能讀取到未完成事務(Uncommited Transaction)或回滾(Roll Back)中的數據, 即所謂的「髒數據」。 HOLDLOCK(保持鎖) 此選項被選中時,SQL Server 會將此共享鎖保持至整個事務結束,而不會在途中釋放。 UPDLOCK(修改鎖) 此選項被選中時,SQL Server 在讀取數據時使用修改鎖來代替共享鎖,並將此鎖保持至整個事務或命令結束。使用此選項可以保證多個進程能同時讀取數據但只有該進程能修改數據。
TABLOCK(表鎖)
此選項被選中時,SQL Server 將在整個表上置共享鎖直至該命令結束。 這個選項保證其餘進程只能讀取而不能修改數據。
PAGLOCK(頁鎖)
此選項爲默認選項, 當被選中時,SQL Server 使用共享頁鎖。
TABLOCKX(排它表鎖)
此選項被選中時,SQL Server 將在整個表上置排它鎖直至該命令或事務結束。這將防止其餘進程讀取或修改表中的數據。
使用這些選項將使系統忽略原先在SET語句設定的事務隔離級別(Transaction Isolation Level)。 請查閱SQL Server 聯機手冊獲取更多信息。
-------------------------------------------------------------------------
1 如何鎖一個表的某一行 A 鏈接中執行 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ begin tran select * from tablename with (rowlock) where id=3 waitfor delay ’00:00:05’ commit tran B鏈接中若是執行 update tablename set colname=’10’ where id=3 --則要等待5秒 update tablename set colname=’10’ where id <>3 --可當即執行 2 鎖定數據庫的一個表 SELECT * FROM table WITH (HOLDLOCK) 注意: 鎖定數據庫的一個表的區別 SELECT * FROM table WITH (HOLDLOCK) 其餘事務能夠讀取表,但不能更新刪除 SELECT * FROM table WITH (TABLOCKX) 其餘事務不能讀取表,更新和刪除 select * from table with (..) SELECT 語句中「加鎖選項」的功能說明 SQL Server提供了強大而完備的鎖機制來幫助實現數據庫系統的併發性和高性能。用戶既能使用SQL Server的缺省設置也能夠在select 語句中使用「加鎖選項」來實現預期的效果。 本文介紹了SELECT語句中的各項「加鎖選項」以及相應的功能說明。 功能說明: NOLOCK(不加鎖) 此選項被選中時,SQL Server 在讀取或修改數據時不加任何鎖。 在這種狀況下,用戶有可能讀取到未完成事務(Uncommited Transaction)或回滾(Roll Back)中的數據, 即所謂的「髒數據」。 HOLDLOCK(保持鎖) 此選項被選中時,SQL Server 會將此共享鎖保持至整個事務結束,而不會在途中釋放。 UPDLOCK(修改鎖) 此選項被選中時,SQL Server 在讀取數據時使用修改鎖來代替共享鎖,並將此鎖保持至整個事務或命令結束。使用此選項可以保證多個進程能同時讀取數據但只有該進程能修改數據。 TABLOCK(表鎖) 此選項被選中時,SQL Server 將在整個表上置共享鎖直至該命令結束。 這個選項保證其餘進程只能讀取而不能修改數據。 PAGLOCK(頁鎖) 此選項爲默認選項, 當被選中時,SQL Server 使用共享頁鎖。 TABLOCKX(排它表鎖) 此選項被選中時,SQL Server 將在整個表上置排它鎖直至該命令或事務結束。這將防止其餘進程讀取或修改表中的數據。 使用這些選項將使系統忽略原先在SET語句設定的事務隔離級別(Transaction Isolation Level)。 請查閱SQL Server 聯機手冊獲取更多信息。 ------------------------------------------------ 什幺是事務 事務(Transaction)是併發控制的基本單位。所謂事務,它是一個操做序列,這些操做要幺都執行,要幺都不執行,它是一個不可分割的工做單位。例如,銀行轉賬工做:從一個賬號扣款並使另外一個賬號增款,這兩個操做要幺都執行,要幺都不執行。因此,應該把他們當作一個事務。事務是數據庫維護數據一致性的單位,在每一個事務結束時,都能保持數據一致性。 數據一致性問題 多用戶併發存取同一數據將會致使如下的數據不一致性問題。 • 丟失修改( Lost Update) 在下表中,T一、T二、T3和T4表示順序的時間。 用戶T 1T 2T 3T 4 Ax = 40X = x-30 BX = 40X = x-20 假設用戶A和B都讀取x ( x = 40 ) ,而後分別把x減小30和20。用戶A在t3把改後的x ( x = 10 )寫入數據庫。隨後,用戶B在t4把改後的x ( x = 20 )寫入數據庫。因而,對用戶A而言,他的修改在t4 處丟失了。 • 髒讀數據( Dirty Read) 請看下錶, 用戶T1T2T3T4 Ax = 40X = x + 30X = x - 30rollback BX = 70X = x-20 用戶A在t2把x增長30(尚沒寫入數據庫),用戶B在t3由數據緩存讀出x = 70。但用戶A在t4時撤消(Undo)了對x的修改,數據庫中仍維持x = 40。但用戶B已把改變的數據( x = 70)取走。 • 不能重複讀(Non-Repeatable Read) 用戶T1T2T3T4T5T6 AX=40Y=30 X+Y=70Z=30 X+Y+Z=100 Bx=40X=X+20CommitX=x-20 用戶A、用戶B分別讀取x = 40後,在t 3用戶A取出y = 30並計算x + y = 70。在t4時用戶B把x增長20,並於t 5把x ( x = 60 )寫入數據庫。在t6時,用戶A取出z ( z = 30 )並繼續計算x + y + z = 100。但若是用戶A爲進行覈算而把x、y、x重讀一次再進行計算,卻出現x + y + z = 120!(x已增長20)。 如何標識一個事務 在SQL Server中,一般事務是指以BEGIN TRAN開始,到ROLLBACK或一個相匹配的COMMIT之間的全部語句序列。ROLLBACK表示要撤消( U n d o)該事務已作的一切操做,回退到事務開始的狀態。COMMIT表示提交事務中的一切操做,使得對數據庫的改變生效。 在SQL Server中,對事務的管理包含三個方面: • 事務控制語句:它使程序員能指明把一系列操做( Transact - SQL命令)做爲一個工做單 位來處理。 • 鎖機制( Locking):封鎖正被一個事務修改的數據,防止其它用戶訪問到「不一致」的數據。 • 事務日誌( Transaction Log):使事務具備可恢復性。 SQL Server的鎖機制 所謂封鎖,就是一個事務可向系統提出請求,對被操做的數據加鎖( Lock )。其它事務必須等到此事務解鎖( Unlock)以後才能訪問該數據。從而,在多個用戶併發訪問數據庫時,確保不互相干擾。可鎖定的單位是:行、頁、表、盤區和數據庫。 1. 鎖的類型 SQL Server支持三種基本的封鎖類型:共享( S)鎖,排它(X)鎖和更新(U)鎖。封鎖的基本粒度爲行。 1) 共享(S)鎖:用於讀操做。 • 多個事務可封鎖一個共享單位的數據。 • 任何事務都不能修改加S鎖的數據。
一般是加S鎖的數據被讀取完畢,S鎖當即被釋放。
2) 獨佔(X)鎖:用於寫操做。 • 僅容許一個事務封鎖此共享數據。 • 其它任何事務必須等到X鎖被釋放才能對該數據進行訪問。 • X鎖一直到事務結束才能被釋放。 3) 更新(U)鎖。 • 用來預約要對此頁施加X鎖,它容許其它事務讀,但不容許再施加U 鎖或X鎖。 • 當被讀取數據頁將要被更新時,則升級爲X鎖。 • U鎖一直到事務結束時才能被釋放。 2. 三種鎖的兼容性 以下表簡單描述了三種鎖的兼容性: 一般,讀操做(SELECT)得到共享鎖,寫操做( INSERT、DELETE)得到獨佔鎖;而更新操做可分解爲一個有更新意圖的讀和一個寫操做,故先得到更新鎖,而後再升級爲獨佔鎖。 執行的命令得到鎖其它進程能夠查詢?其它進程能夠修改? Select title_id from titlesSYesNo delete titles where price>25XNoNo insert titles values( ...)XNoNo update titles set type=「general」UYesNo where type=「business」而後XNONo 使用索引下降鎖併發性 咱們爲什幺要討論鎖機制?若是用戶操做數據時儘量鎖定最少的數據,這樣處理過程,就不會等待被鎖住的數據解鎖,從而能夠潛在地提升SQL Server的性能。若是有200個用戶打算修改不一樣顧客的數據,僅對存儲單個顧客信息的單一行進行加鎖要比鎖住整個表好得多。那幺,用戶如何只鎖定行而不是表呢?固然是使用索引了。正如前面所提到的,對存有要修改數據的字段使用索引能夠提升性能,由於索引能直接找到數據所在的頁面,而不是搜索全部的數據頁面去找到所需的行。若是用戶直接找到表中對應的行並進行更新操做,只需鎖定該行便可,而不是鎖定多個頁面或者整個表。性能的提升不只僅是由於在修改時讀取的頁面較少,並且鎖定較少的頁面潛在地避免了一個用戶在修改數據完成以前其它用戶一直等待解鎖的狀況。 事務的隔離級別 ANSI標準爲SQL事務定義了4個隔離級別(isolation level),隔離級別越高,出現數據不一致性的可能性就越小(併發度也就越低)。較高的級別中包含了較低級別中所規定了的限制。 • 隔離級別0:防止「丟失修改」,容許髒讀。 • 隔離級別1:防止髒讀。容許讀已提交的數據。 • 隔離級別2:防止「不可重複讀」。 • 隔離級別3:「可串行化」(serializable)。其含義爲,某組並行事務的一種交叉調度產生的結果和這些事務的某一串行調度的結果相同(可避免破壞數據一致性)。SQL Server支持四種隔離級別,級別1爲缺省隔離級別,表中沒有隔離級別2, 請參考表: SQL Server支持的隔離級別封鎖方式數據一致性保證 X鎖施加於被修改的頁S鎖施加於被讀取的頁防止丟失修改防止讀髒數據能夠重複讀取 級別0封鎖到事務結束是 級別1(缺省)封鎖到事務結束讀後當即釋放是是 級別3封鎖到事務結束封鎖到事務結束是是是 在SQL Server也指定級別2,但級別3已包含級別2。ANSI-92 SQL中要求把級別3做爲全部事務的缺省隔離級別。 SQL Server用holdlock選項增強S鎖的限制,實現隔離級別3。SQL Server的缺省隔離級別爲級別1,共享讀鎖(S鎖)是在該頁被讀完後當即釋放。在select語句中加holdlock選項,則可以使S鎖一直保持到事務結束才釋放。她符合了ANSI隔離級別3的標準─「可串行化」。 下面這個例子中,在同一事務中對avg ( advance )要讀取兩次,且要求他們取值不變─「可重複讀」,爲此要使用選項holdlock。 BEGIN tran DECLARE @avg-adv money SELECT @avg-adv = avg(advance) FROM titles holdlock WHERE type = 「business「 if @avg-adv > 5000 SELECT title from titles WHERE type=「business「 and advance >@avg_adv COMMIT tran 在SQL Server中設定事務隔離級別的方法有三種: • 會話層設定 語法以下: SET TRANSACTION ISOLATION LEVEL { READ COMMITTED | READ UNCOMMITTED | REPEATABLE READ | SERIALIZABLE } 系統提供的系統存儲過程將在級別1下執行,它不受會話層設定的影響。 • 語法層設定 在SELECT、DECLARE cursor及read text語句中增長選項。好比: SELECT...at isolation{0|read uncommitted} 注意:語法層的設定將替代會話層的設定。 • 利用關鍵詞設定 ─在SELECT語句中,加選項holdlock則設定級別3 ─在SELECT語句中,加noholdlock則設定級別0 以下程序清單中所列的腳本實例在authors表上持有一個共享鎖,它將用戶檢查服務器當前活動的時間推遲兩分鐘。 程序清單測試事務隔離等級 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ GO BEGIN TRAN SELECT * FROM authors WHERE au_lname = ’Green’ WAITFOR DELAY ’00:02:00’ ROLLBACK TRAN GO Activity Legend(活動圖標)代表:當SQL Server檢索數據時會去掉頁面表意向鎖。Current Activity窗口(見圖3 - 3 )顯示共享鎖一直被保持直到事務完成爲止(也就是說,直到WAITFOR和ROLLBACK TRAN語句完成)。 使用鎖定優化程序提示 讓咱們再深刻考察程序清單的實例。經過改變優化程序提示,用戶能夠令SQL Server在authors表上設置一個獨佔表鎖(如程序所示)。 BEGIN TRAN SELECT * FROM authors (tablockx) WHERE au_lname = ’Green’ WAITFOR DELAY ’00:02:00’ ROLLBACK TRAN GO ------解決方案-------------------- 鎖是SQL SERVER用來同步多個用戶同時對同一個數據塊的訪問的一種機制。 鎖要結合事務才能顯示出鎖的用處