SQL SERVER 通過鎖管理器自動發(fā)現(xiàn)和解決死鎖。在 SQL SERVER 中 Lock Monitor 管理線程(spid=4)每 5 秒鐘檢查一次系統(tǒng)中是否存在死鎖,同時也會使用死鎖發(fā)現(xiàn)計數(shù)器(Deadlock Detection Counter)控制檢查死鎖的頻率。
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:國際域名空間、虛擬空間、營銷軟件、網(wǎng)站建設、定海網(wǎng)站維護、網(wǎng)站推廣。
死鎖發(fā)現(xiàn)計數(shù)器初始值為 3,當發(fā)現(xiàn)死鎖時被重新設置為 3,當沒有發(fā)現(xiàn)死鎖時此值減 1。如果死鎖發(fā)現(xiàn)計數(shù)器大于 0,則在每次有進程獲取鎖被阻止時,鎖管理器都要求 Lock Monitor 線程檢查死鎖;而如果計數(shù)器等于 0,則在每次有進程獲取鎖被阻止時,鎖管理器不會要求 Lock Monitor 線程檢查死鎖,只是每 5 秒鐘檢查一次。
Lock Monitor 線程通過檢查鎖的等待列表發(fā)現(xiàn)保持鎖的進程和等待鎖的進程間的關(guān)系,從而發(fā)現(xiàn)死鎖。
這個問題要具體分析:
第一,事務隔離級別基本兩種模式,一種是阻塞式(read committed,repeatable read,serializable)
,一種是非阻塞式(read uncommitted,snapshot)。
默認是read committed,這種情況一般在更新表的時候,如果不使用hint 提示,基本是先對表添加IX鎖,級別不算高,基本和其他鎖兼容,但是repeatable read,serializable 事務隔離級別就會先對表添加IX鎖,然后向X鎖轉(zhuǎn)化,而X鎖和大多數(shù)鎖都不兼容,容易發(fā)生表阻塞。
第二種隔離級別不會有以上問題,但是又引入了其它的問題。
以上是一種情況。
另外一種就是 鎖升級,一個鎖是96B內(nèi)存,如果太多,sqlserver就會升級為表鎖,一般是5000以上行級鎖就升級為一個表X鎖。
所以適當?shù)奈募纸M和表分區(qū) 是有必要的。
其次就是資源互相引用導致事務長時間不能釋放,導致真正的死鎖,不過SQL2005以后,這種情況發(fā)生的概率很低。
留個問題你自己去想。
兩個SQL,兩個連接,同時執(zhí)行。
update A set A.NAME=xxx where A.id=55
update A set A.NAME=xxx where A.id=56, 如果 56 不存在你說會發(fā)生什么情況呢?
SQL SERVER里的鎖機制:
NOLOCK(不加鎖)
此選項被選中時,SQL Server 在讀取或修改數(shù)據(jù)時不加任何鎖。 在這種情況下,用戶有可能讀取到未完成事務(Uncommited Transaction)或回滾(Roll Back)中的數(shù)據(jù), 即所謂的“臟數(shù)據(jù)”。
HOLDLOCK(保持鎖)
此選項被選中時,SQL Server 會將此共享鎖保持至整個事務結(jié)束,而不會在途中釋放。 例如,“ SELECT * FROM my_table HOLDLOCK”就要求在整個查詢過程中,保持對表的鎖定,直到查詢完成才釋放鎖定。
UPDLOCK(修改鎖)
此選項被選中時,SQL Server 在讀取數(shù)據(jù)時使用修改鎖來代替共享鎖,并將此鎖保持至整個事務或命令結(jié)束。使用此選項能夠保證多個進程能同時讀取數(shù)據(jù)但只有該進程能修改數(shù)據(jù)。
TABLOCK(表鎖)
此選項被選中時,SQL Server 將在整個表上置共享鎖直至該命令結(jié)束。 這個選項保證其他進程只能讀取而不能修改數(shù)據(jù)。
PAGLOCK(頁鎖)
此選項為默認選項, 當被選中時,SQL Server 使用共享頁鎖。
TABLOCKX(排它表鎖)
此選項被選中時,SQL Server 將在整個表上置排它鎖直至該命令或事務結(jié)束。這將防止其他進程讀取或修改表中的數(shù)據(jù)。
就你上面的事例而言,select的共享鎖性質(zhì)是得到結(jié)果即釋放,不會在事務中保留
而update所用到的U鎖及其進一步的X鎖則需要持續(xù)到事務的結(jié)束
如果是多線程的程序的話,在select與update處都可能會出現(xiàn)鎖等待,這要根據(jù)實際操作中數(shù)據(jù)是否沖突來看
不需要,就算確實用戶同時執(zhí)行,數(shù)據(jù)庫的操作機制是有隊列的,所以不存在并發(fā)情況。
鎖基本用不到,我反正開發(fā)了5年了沒用到過。
你要了解死鎖發(fā)生的情況,一般是用事務的時候可能會碰到死鎖,你申請了A資源,鎖住了A然后申請B資源,其他人申請了B資源,然后申請A,這樣就互不相讓,導致A,B資源都不可訪問了,不過其他數(shù)據(jù)我不知道,SQLSERVER發(fā)生這種死鎖不是一直鎖死的,過幾分鐘就會發(fā)現(xiàn)這個死鎖,把鎖釋放掉,2個事務都失敗。
各種大型數(shù)據(jù)庫所采用的鎖的基本理論是一致的,但在具體實現(xiàn)上各有差別。SQLServer更強調(diào)由系統(tǒng)來管理鎖。在用戶有SQL請求時,系統(tǒng)分析請求,自動在滿足鎖定條件和系統(tǒng)性能之間為數(shù)據(jù)庫加上適當?shù)逆i,同時系統(tǒng)在運行期間常常自動進行優(yōu)化處理,實行動態(tài)加鎖。對于一般的用戶而言,通過系統(tǒng)的自動鎖定管理機制基本可以滿足使用要求,但如果對數(shù)據(jù)安全、數(shù)據(jù)庫完整性和一致性有特殊要求,就需要了解SQLServer的鎖機制,掌握數(shù)據(jù)庫鎖定方法。 鎖是數(shù)據(jù)庫中的一個非常重要的概念,它主要用于多用戶環(huán)境下保證數(shù)據(jù)庫完整性和一致性。我們知道,多個用戶能夠同時操縱同一個數(shù)據(jù)庫中的數(shù)據(jù),會發(fā)生數(shù)據(jù)不一致現(xiàn)象。即如果沒有鎖定且多個用戶同時訪問一個數(shù)據(jù)庫,則當他們的事務同時使用相同的數(shù)據(jù)時可能會發(fā)生問題。這些問題包括:丟失更新、臟讀、不可重復讀和幻覺讀: 1.當兩個或多個事務選擇同一行,然后基于最初選定的值更新該行時,會發(fā)生丟失更新問題。每個事務都不知道其它事務的存在。最后的更新將重寫由其它事務所做的更新,這將導致數(shù)據(jù)丟失。例如,兩個編輯人員制作了同一文檔的電子復本。每個編輯人員獨立地更改其復本,然后保存更改后的復本,這樣就覆蓋了原始文檔。最后保存其更改復本的編輯人員覆蓋了第一個編輯人員所做的更改。如果在第一個編輯人員完成之后第二個編輯人員才能進行更改,則可以避免該問題。 2.臟讀就是指當一個事務正在訪問數(shù)據(jù),并且對數(shù)據(jù)進行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中,這時,另外一個事務也訪問這個數(shù)據(jù),然后使用了這個數(shù)據(jù)。因為這個數(shù)據(jù)是還沒有提交的數(shù)據(jù),那么另外一個事務讀到的這個數(shù)據(jù)是臟數(shù)據(jù),依據(jù)臟數(shù)據(jù)所做的操作可能是不正確的。例如,一個編輯人員正在更改電子文檔。在更改過程中,另一個編輯人員復制了該文檔(該復本包含到目前為止所做的全部更改)并將其分發(fā)給預期的用戶。此后,第一個編輯人員認為目前所做的更改是錯誤的,于是刪除了所做的編輯并保存了文檔。分發(fā)給用戶的文檔包含不再存在的編輯內(nèi)容,并且這些編輯內(nèi)容應認為從未存在過。如果在第一個編輯人員確定最終更改前任何人都不能讀取更改的文檔,則可以避免該問題。 3.不可重復讀是指在一個事務內(nèi),多次讀同一數(shù)據(jù)。在這個事務還沒有結(jié)束時,另外一個事務也訪問該同一數(shù)據(jù)。那么,在第一個事務中的兩次讀數(shù)據(jù)之間,由于第二個事務的修改,那么第一個事務兩次讀到的的數(shù)據(jù)可能是不一樣的。這樣就發(fā)生了在一個事務內(nèi)兩次讀到的數(shù)據(jù)是不一樣的,因此稱為是不可重復讀。例如,一個編輯人員兩次讀取同一文檔,但在兩次讀取之間,作者重寫了該文檔。當編輯人員第二次讀取文檔時,文檔已更改。原始讀取不可重復。如果只有在作者全部完成編寫后編輯人員才可以讀取文檔,則可以避免該問題。 4.幻覺讀是指當事務不是獨立執(zhí)行時發(fā)生的一種現(xiàn)象,例如第一個事務對一個表中的數(shù)據(jù)進行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時,第二個事務也修改這個表中的數(shù)據(jù),這種修改是向表中插入一行新數(shù)據(jù)。那么,以后就會發(fā)生操作第一個事務的用戶發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行,就好象發(fā)生了幻覺一樣。例如,一個編輯人員更改作者提交的文檔,但當生產(chǎn)部門將其更改內(nèi)容合并到該文檔的主復本時,發(fā)現(xiàn)作者已將未編輯的新材料添加到該文檔中。如果在編輯人員和生產(chǎn)部門完成對原始文檔的處理之前,任何人都不能將新材料添加到文檔中,則可以避免該問題。 所以,處理多用戶并發(fā)訪問的方法是加鎖。鎖是防止其他事務訪問指定的資源控制、實現(xiàn)并發(fā)控制的一種主要手段。當一個用戶鎖住數(shù)據(jù)庫中的某個對象時,其他用戶就不能再訪問該對象。加鎖對并發(fā)訪問的影響體現(xiàn)在鎖的粒度上。為了控制鎖定的資源,應該首先了解系統(tǒng)的空間管理。在SQLServer2000系統(tǒng)中,最小的空間管理單位是頁,一個頁有8K。所有的數(shù)據(jù)、日志、索引都存放在頁上。另外,使用頁有一個限制,這就是表中的一行數(shù)據(jù)必須在同一個頁上,不能跨頁。頁上面的空間管理單位是盤區(qū),一個盤區(qū)是8個連續(xù)的頁。表和索引的最小占用單位是盤區(qū)。數(shù)據(jù)庫是由一個或者多個表或者索引組成,即是由多個盤區(qū)組成。放在一個表上的鎖限制對整個表的并發(fā)訪問;放在盤區(qū)上的鎖限制了對整個盤區(qū)的訪問;放在數(shù)據(jù)頁上的鎖限制了對整個數(shù)據(jù)頁的訪問;放在行上的鎖只限制對該行的并發(fā)訪問。 SQLServer2000具有多粒度鎖定,允許一個事務鎖定不同類型的的資源。為了使鎖定的成本減至最少,SQLServer自動將資源鎖定在適合任務的級別。鎖定在較小的粒度(例如行)可以增加并發(fā)但需要較大的開銷,因為如果鎖定了許多行,則需要控制更多的鎖。鎖定在較大的粒度(例如表)就并發(fā)而言是相當昂貴的,因為鎖定整個表限制了其它事務對表中任意部分進行訪問,但要求的開銷較低,因為需要維護的鎖較少。SQLServer可以鎖定行、頁、擴展盤區(qū)、表、庫等資源。 行是可以鎖定的最小空間,行級鎖占用的數(shù)據(jù)資源最少,所以在事務的處理過程中,允許其他事務繼續(xù)操縱同一個表或者同一個頁的其他數(shù)據(jù),大大降低了其他事務等待處理的時間,提高了系統(tǒng)的并發(fā)性。 頁級鎖是指在事務的操縱過程中,無論事務處理數(shù)據(jù)的多少,每一次都鎖定一頁,在這個頁上的數(shù)據(jù)不能被其他事務操縱。在SQLServer7.0以前,使用的是頁級鎖。頁級鎖鎖定的資源比行級鎖鎖定的數(shù)據(jù)資源多。在頁級鎖中,即使是一個事務只操縱頁上的一行數(shù)據(jù),那么該頁上的其他數(shù)據(jù)行也不能被其他事務使用。因此,當使用頁級鎖時,會出現(xiàn)數(shù)據(jù)的浪費現(xiàn)象,也就是說,在同一個頁上會出現(xiàn)數(shù)據(jù)被占用卻沒有使用的現(xiàn)象。在這種現(xiàn)象中,數(shù)據(jù)的浪費最多不超過一個頁上的數(shù)據(jù)行。 表級鎖也是一個非常重要的鎖。表級鎖是指事務在操縱某一個表的數(shù)據(jù)時,鎖定了這個數(shù)據(jù)所在的整個表,其他事務不能訪問該表中的其他數(shù)據(jù)。當事務處理的數(shù)據(jù)量比較大時,一般使用表級鎖。表級鎖的特點是使用比較少的系統(tǒng)資源,但是卻占用比較多的數(shù)據(jù)資源。與行級鎖和頁級鎖相比,表級鎖占用的系統(tǒng)資源例如內(nèi)存比較少,但是占用的數(shù)據(jù)資源卻是最大。在表級鎖時,有可能出現(xiàn)數(shù)據(jù)的大量浪費現(xiàn)象,因為表級鎖鎖定整個表,那么其他的事務都不能操縱表中的其他數(shù)據(jù)。 盤區(qū)鎖是一種特殊類型的鎖,只能用在一些特殊的情況下。簇級鎖就是指事務占用一個盤區(qū),這個盤區(qū)不能同時被其他事務占用。例如在創(chuàng)建數(shù)據(jù)庫和創(chuàng)建表時,系統(tǒng)分配物理空間時使用這種類型的鎖。系統(tǒng)是按照盤區(qū)分配空間的。當系統(tǒng)分配空間時,使用盤區(qū)鎖,防止其他事務同時使用同一個盤區(qū)。當系統(tǒng)完成分配空間之后,就不再使用這種類型的盤區(qū)鎖。特別是,當涉及到對數(shù)據(jù)操作的事務時,不使用盤區(qū)鎖。 數(shù)據(jù)庫級鎖是指鎖定整個數(shù)據(jù)庫,防止任何用戶或者事務對鎖定的數(shù)據(jù)庫進行訪問。數(shù)據(jù)庫級鎖是一種非常特殊的鎖,它只是用于數(shù)據(jù)庫的恢復操作過程中。這種等級的鎖是一種最高等級的鎖,因為它控制整個數(shù)據(jù)庫的操作。只要對數(shù)據(jù)庫進行恢復操作,那么就需要設置數(shù)據(jù)庫為單用戶模式,這樣系統(tǒng)就能防止其他用戶對該數(shù)據(jù)庫進行各種操作。 行級鎖是一種最優(yōu)鎖,因為行級鎖不可能出現(xiàn)數(shù)據(jù)既被占用又沒有使用的浪費現(xiàn)象。但是,如果用戶事務中頻繁對某個表中的多條記錄操作,將導致對該表的許多記錄行都加上了行級鎖,數(shù)據(jù)庫系統(tǒng)中鎖的數(shù)目會急劇增加,這樣就加重了系統(tǒng)負荷,影響系統(tǒng)性能。因此,在SQLServer中,還支持鎖升級(lockescalation)。所謂鎖升級是指調(diào)整鎖的粒度,將多個低粒度的鎖替換成少數(shù)的更高粒度的鎖,以此來降低系統(tǒng)負荷。在SQLServer中當一個事務中的鎖較多,達到鎖升級門限時,系統(tǒng)自動將行級鎖和頁面鎖升級為表級鎖。