SQL Server中的鎖 詳解 nolock,rowlock,tablock,xlock,paglock


摘自: http://www.myexception.cn/sql-server/385562.html

 

 

復制代碼
高手進 鎖 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) 在下表中,T1、T2、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用來同步多個用戶同時對同一個數據塊的訪問的一種機制。 鎖要結合事務才能顯示出鎖的用處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM