當前位置:首頁 » 編程語言 » sql錯誤1222

sql錯誤1222

發布時間: 2022-09-23 22:42:48

⑴ Microsoft sql Server Management Studio 已超過了鎖請求超時時段。 (Microsoft SQL Server,錯誤: 1222)

操作SQLServer資料庫時,遇到這樣的問題:已超過了鎖請求超時時段。 (Microsoft SQL Server,錯誤: 1222) 本文來自學盟網(www.stuhack.com)
經過查找材料了解為資源搶占,照成死鎖,殺死進程就OK了,具體操作如下:
select spId
from master..SysProcesses
where db_Name(dbID) = '資料庫名稱'
and spId <> @@SpId
and dbID <> 0
上面語句是獲取進程ID,下面就是根據ID殺死相應進程exec ('Kill '+spId(進程ID))

⑵ 資料庫表中某行數據由於事務超時,連接斷開無法回滾被鎖,但在被鎖的表中查不到該行數據所在表,怎麼解鎖

鎖的概述

一. 為什麼要引入鎖
多個用戶同時對資料庫的並發操作時會帶來以下數據不一致的問題:
丟失更新
A,B兩個用戶讀同一數據並進行修改,其中一個用戶的修改結果破壞了另一個修改的結果,比如訂票系統
臟讀
A用戶修改了數據,隨後B用戶又讀出該數據,但A用戶因為某些原因取消了對數據的修改,數據恢復原值,此時B得到的數據就與資料庫內的數據產生了不一致
不可重復讀
A用戶讀取數據,隨後B用戶讀出該數據並修改,此時A用戶再讀取數據時發現前後兩次的值不一致
並發控制的主要方法是封鎖,鎖就是在一段時間內禁止用戶做某些操作以避免產生數據不一致
二 鎖的分類
鎖的類別有兩種分法:
1. 從資料庫系統的角度來看:分為獨占鎖(即排它鎖),共享鎖和更新鎖
MS SQL Server 使用以下資源鎖模式。
鎖模式 描述
共享 (S) 用於不更改或不更新數據的操作(只讀操作),如 SELECT 語句。
更新 (U) 用於可更新的資源中。防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖。
排它 (X) 用於數據修改操作,例如 INSERT、UPDATE 或 DELETE。確保不會同時同一資源進行多重更新。
意向鎖 用於建立鎖的層次結構。意向鎖的類型為:意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
架構鎖 在執行依賴於表架構的操作時使用。架構鎖的類型為:架構修改 (Sch-M) 和架構穩定性 (Sch-S)。
大容量更新 (BU) 向表中大容量復制數據並指定了 TABLOCK 提示時使用。
共享鎖
共享 (S) 鎖允許並發事務讀取 (SELECT) 一個資源。資源上存在共享 (S) 鎖時,任何其它事務都不能修改數據。一旦已經讀取數據,便立即釋放資源上的共享 (S) 鎖,除非將事務隔離級別設置為可重復讀或更高級別,或者在事務生存周期內用鎖定提示保留共享 (S) 鎖。
更新鎖
更新 (U) 鎖可以防止通常形式的死鎖。一般更新模式由一個事務組成,此事務讀取記錄,獲取資源(頁或行)的共享 (S) 鎖,然後修改行,此操作要求鎖轉換為排它 (X) 鎖。如果兩個事務獲得了資源上的共享模式鎖,然後試圖同時更新數據,則一個事務嘗試將鎖轉換為排它 (X) 鎖。共享模式到排它鎖的轉換必須等待一段時間,因為一個事務的排它鎖與其它事務的共享模式鎖不兼容;發生鎖等待。第二個事務試圖獲取排它 (X) 鎖以進行更新。由於兩個事務都要轉換為排它 (X) 鎖,並且每個事務都等待另一個事務釋放共享模式鎖,因此發生死鎖。
若要避免這種潛在的死鎖問題,請使用更新 (U) 鎖。一次只有一個事務可以獲得資源的更新 (U) 鎖。如果事務修改資源,則更新 (U) 鎖轉換為排它 (X) 鎖。否則,鎖轉換為共享鎖。
排它鎖
排它 (X) 鎖可以防止並發事務對資源進行訪問。其它事務不能讀取或修改排它 (X) 鎖鎖定的數據。
意向鎖
意向鎖表示 SQL Server 需要在層次結構中的某些底層資源上獲取共享 (S) 鎖或排它 (X) 鎖。例如,放置在表級的共享意向鎖表示事務打算在表中的頁或行上放置共享 (S) 鎖。在表級設置意向鎖可防止另一個事務隨後在包含那一頁的表上獲取排它 (X) 鎖。意向鎖可以提高性能,因為 SQL Server 僅在表級檢查意向鎖來確定事務是否可以安全地獲取該表上的鎖。而無須檢查表中的每行或每頁上的鎖以確定事務是否可以鎖定整個表。
意向鎖包括意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
鎖模式
描述
意向共享 (IS) 通過在各資源上放置 S 鎖,表明事務的意向是讀取層次結構中的部分(而不是全部)底層資源。
意向排它 (IX) 通過在各資源上放置 X 鎖,表明事務的意向是修改層次結構中的部分(而不是全部)底層資源。IX 是 IS 的超集。與意向排它共享 (SIX) 通過在各資源上放置 IX 鎖,表明事務的意向是讀取層次結構中的全部底層資源並修改部分(而不是全部)底層資源。允許頂層資源上的並發 IS 鎖。例如,表的 SIX 鎖在表上放置一個 SIX 鎖(允許並發 IS 鎖),在當前所修改頁上放置 IX 鎖(在已修改行上放置 X 鎖)。雖然每個資源在一段時間內只能有一個 SIX 鎖,以防止其它事務對資源進行更新,但是其它事務可以通過獲取表級的 IS 鎖來讀取層次結構中的底層資源。
獨占鎖:只允許進行鎖定操作的程序使用,其他任何對他的操作均不會被接受。執行數據更新命令時,SQL Server會自動使用獨占鎖。當對象上有其他鎖存在時,無法對其加獨占鎖。
共享鎖:共享鎖鎖定的資源可以被其他用戶讀取,但其他用戶無法修改它,在執行Select時,SQL Server會對對象加共享鎖。
更新鎖:當SQL Server准備更新數據時,它首先對數據對象作更新鎖鎖定,這樣數據將不能被修改,但可以讀取。等到SQL Server確定要進行更新數據操作時,他會自動將更新鎖換為獨占鎖,當對象上有其他鎖存在時,無法對其加更新鎖。
2. 從程序員的角度看:分為樂觀鎖和悲觀鎖。
樂觀鎖:完全依靠資料庫來管理鎖的工作。
悲觀鎖:程序員自己管理數據或對象上的鎖處理。
MS SQL Server 使用鎖在多個同時在資料庫內執行修改的用戶間實現悲觀並發控制
三 鎖的粒度
鎖粒度是被封鎖目標的大小,封鎖粒度小則並發性高,但開銷大,封鎖粒度大則並發性低但開銷小
SQL Server支持的鎖粒度可以分為為行、頁、鍵、鍵范圍、索引、表或資料庫獲取鎖
資源描述
RID 行標識符。用於單獨鎖定表中的一行。
鍵 索引中的行鎖。用於保護可串列事務中的鍵范圍。
頁 8 千位元組 (KB) 的數據頁或索引頁。
擴展盤區 相鄰的八個數據頁或索引頁構成的一組。
表 包括所有數據和索引在內的整個表。
DB 資料庫。
四 鎖定時間的長短
鎖保持的時間長度為保護所請求級別上的資源所需的時間長度。
用於保護讀取操作的共享鎖的保持時間取決於事務隔離級別。採用 READ COMMITTED 的默認事務隔離級別時,只在讀取頁的期間內控制共享鎖。在掃描中,直到在掃描內的下一頁上獲取鎖時才釋放鎖。如果指定 HOLDLOCK 提示或者將事務隔離級別設置為 REPEATABLE READ 或 SERIALIZABLE,則直到事務結束才釋放鎖。
根據為游標設置的並發選項,游標可以獲取共享模式的滾動鎖以保護提取。當需要滾動鎖時,直到下一次提取或關閉游標(以先發生者為准)時才釋放滾動鎖。但是,如果指定 HOLDLOCK,則直到事務結束才釋放滾動鎖。
用於保護更新的排它鎖將直到事務結束才釋放。
如果一個連接試圖獲取一個鎖,而該鎖與另一個連接所控制的鎖沖突,則試圖獲取鎖的連接將一直阻塞到:
將沖突鎖釋放而且連接獲取了所請求的鎖。
連接的超時間隔已到期。默認情況下沒有超時間隔,但是一些應用程序設置超時間隔以防止無限期等待
五 SQL Server 中鎖的自定義
1 處理死鎖和設置死鎖優先順序
死鎖就是多個用戶申請不同封鎖,由於申請者均擁有一部分封鎖權而又等待其他用戶擁有的部分封鎖而引起的無休止的等待可以使用SET DEADLOCK_PRIORITY控制在發生死鎖情況時會話的反應方式。如果兩個進程都鎖定數據,並且直到其它進程釋放自己的鎖時,每個進程才能釋放自己的鎖,即發生死鎖情況。
2 處理超時和設置鎖超時持續時間。
@@LOCK_TIMEOUT 返回當前會話的當前鎖超時設置,單位為毫秒
SET LOCK_TIMEOUT 設置允許應用程序設置語句等待阻塞資源的最長時間。當語句等待的時間大於 LOCK_TIMEOUT 設置時,系統將自動取消阻塞的語句,並給應用程序返回"已超過了鎖請求超時時段"的 1222 號錯誤信息
示例
下例將鎖超時期限設置為 1,800 毫秒。
SET LOCK_TIMEOUT 1800

3) 設置事務隔離級別。
4 ) 對 SELECT、INSERT、UPDATE 和 DELETE 語句使用表級鎖定提示。
5) 配置索引的鎖定粒度
可以使用 sp_indexoption 系統存儲過程來設置用於索引的鎖定粒度
六 查看鎖的信息 1 執行 EXEC SP_LOCK 報告有關鎖的信息
2 查詢分析器中按Ctrl+2可以看到鎖的信息
七 使用注意事項
如何避免死鎖
1 使用事務時,盡量縮短事務的邏輯處理過程,及早提交或回滾事務;
2 設置死鎖超時參數為合理范圍,如:3分鍾-10分種;超過時間,自動放棄本次操作,避免進程懸掛;
3 優化程序,檢查並避免死鎖現象出現;
4 .對所有的腳本和SP都要仔細測試,在正是版本之前。
5 所有的SP都要有錯誤處理(通過@error)
6 一般不要修改SQL Server事務的默認級別。不推薦強行加鎖
八 幾個有關鎖的問題
1 如何鎖一個表的某一行
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDSELECT * FROM table ROWLOCK WHERE id =
1

2 鎖定資料庫的一個表
SELECT * FROM table WITH (HOLDLOCK)

加鎖語句:
sybase:update 表 set col1=col1 where 1=0 ;MS SQL:select col1 from 表 (tablockx) where 1=0 ;oracle:LOCK TABLE 表 IN EXCLUSIVE MODE ;

加鎖後其它人不可操作,直到加鎖用戶解鎖,用commit或rollback解鎖

幾個例子幫助大家加深印象,設table1(A,B,C)
A B C
a1 b1 c1
a2 b2 c2
a3 b3 c3

1)排它鎖
新建兩個連接,在第一個連接中執行以下語句
begin tranupdate table1set A='aa'where B='b2'waitfor delay '00:00:30'
--等待30秒commit tran

在第二個連接中執行以下語句
begin transelect * from table1where B='b2'commit tran

若同時執行上述兩個語句,則select查詢必須等待update執行完畢才能執行即要等待30秒
2)共享鎖
在第一個連接中執行以下語句
begin transelect * from table1 holdlock -holdlock人為加鎖where B='b2'waitfor delay '00:00:30'
--等待30秒commit tran

在第二個連接中執行以下語句
begin transelect A,C from table1where B='b2'update table1set A='aa'where B='b2'commit tran

若同時執行上述兩個語句,則第二個連接中的select查詢可以執行,而update必須等待第一個事務釋放共享鎖轉為排它鎖後才能執行 即要等待30秒
3)死鎖
增設table2(D,E)
D E

d1 e1
d2 e2

在第一個連接中執行以下語句
begin tranupdate table1set A='aa'where B='b2'waitfor delay '00:00:30'update table2set D='d5'where E='e1'commit tran

在第二個連接中執行以下語句
begin tranupdate table2set D='d5'where E='e1'waitfor delay '00:00:10'update table1set A='aa'where B='b2'commit tran

同時執行,系統會檢測出死鎖,並中止進程
補充一點:
SQL Server 2000支持的表級鎖定提示
HOLDLOCK 持有共享鎖,直到整個事務完成,應該在被鎖對象不需要時立即釋放,等於SERIALIZABLE事務隔離級別
NOLOCK 語句執行時不發出共享鎖,允許臟讀 ,等於 READ UNCOMMITTED事務隔離級別
PAGLOCK 在使用一個表鎖的地方用多個頁鎖
READPAST 讓SQL Server跳過任何鎖定行,執行事務,適用於READ UNCOMMITTED事務隔離級別只跳過RID鎖,不跳過頁,區域和表鎖
ROWLOCK 強制使用行鎖
TABLOCKX 強制使用獨占表級鎖,這個鎖在事務期間阻止任何其他事務使用這個表
UPLOCK 強制在讀表時使用更新而不用共享鎖
應用程序鎖:
應用程序鎖就是客戶端代碼生成的鎖,而不是SQL Server本身生成的鎖
處理應用程序鎖的兩個過程
sp_getapplock 鎖定應用程序資源
sp_releaseapplock 為應用程序資源解鎖
注意: 鎖定資料庫的一個表的區別
SELECT * FROM table WITH (HOLDLOCK) 其他事務可以讀取表,但不能更新刪除
SELECT * FROM table WITH (TABLOCKX) 其他事務不能讀取表,更新和刪除

⑶ 大家好 緊急求救 SQL 刷新當前活動進程時,出現「 錯誤1222:

初步懷疑是SQL中某個表出現一致性錯誤或分配錯誤等原因造成。用DBCC CHECKTABLE 依次檢查每個表,DBCC CHECKTABLE用來檢查組成表或索引視圖的所有頁和結構的完整性。

⑷ 如何排查SQL死鎖的錯誤

1. 開啟死鎖日誌輸出(deadlock trace)

DBCC TRACEON(1204,1222)

Trace flag 1204 reports deadlock information formatted by each node involved in the deadlock.
Trace flag 1222 formats deadlock information, first by processes and then by resources.

開啟了上面的選項之後, SQL會輸出死鎖的細節信息到SQL Error Log中(默認位置Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\LOG\ERRORLOG and ERRORLOG.n)

2. 開啟SQL Profiler.
Start SQL profiler
On the Trace Properties dialog box, on the General tab, check Save to file and specify a path to save the trace
Click the Events tab, only add Locks\Lock:deadlock and Locks\Lock:deadlock chain
Click the Data columns tab, add DatabaseID, IndexID, ObjectID
可以通過下面的語句把DatabaseID和ObjectID換成DatabaseName和ObjectName

SELECT database_name(DatabaseID)
SELECT object_name(ObjectID)

3. 使用下面的查詢語句來檢查那個進程被鎖住了.

SELECT * FROM sys.sysprocesses WHERE blocked <> 0
從Blocked列中得到SPID
DBCC inputbuffer (SPID)
sp_who2
sp_lock2

⑸ SQLserver 執行語句後看不到結果

給你個最詳細的吧 可能有你要的內容
鎖的概述

一. 為什麼要引入鎖

多個用戶同時對資料庫的並發操作時會帶來以下數據不一致的問題:

丟失更新
A,B兩個用戶讀同一數據並進行修改,其中一個用戶的修改結果破壞了另一個修改的結果,比如訂票系統

臟讀
A用戶修改了數據,隨後B用戶又讀出該數據,但A用戶因為某些原因取消了對數據的修改,數據恢復原值,此時B得到的數據就與資料庫內的數據產生了不一致

不可重復讀
A用戶讀取數據,隨後B用戶讀出該數據並修改,此時A用戶再讀取數據時發現前後兩次的值不一致

並發控制的主要方法是封鎖,鎖就是在一段時間內禁止用戶做某些操作以避免產生數據不一致

二 鎖的分類

鎖的類別有兩種分法:

1. 從資料庫系統的角度來看:分為獨占鎖(即排它鎖),共享鎖和更新鎖

MS-SQL Server 使用以下資源鎖模式。

鎖模式 描述
共享 (S) 用於不更改或不更新數據的操作(只讀操作),如 SELECT 語句。
更新 (U) 用於可更新的資源中。防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖。
排它 (X) 用於數據修改操作,例如 INSERT、UPDATE 或 DELETE。確保不會同時同一資源進行多重更新。
意向鎖 用於建立鎖的層次結構。意向鎖的類型為:意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
架構鎖 在執行依賴於表架構的操作時使用。架構鎖的類型為:架構修改 (Sch-M) 和架構穩定性 (Sch-S)。
大容量更新 (BU) 向表中大容量復制數據並指定了 TABLOCK 提示時使用。

共享鎖
共享 (S) 鎖允許並發事務讀取 (SELECT) 一個資源。資源上存在共享 (S) 鎖時,任何其它事務都不能修改數據。一旦已經讀取數據,便立即釋放資源上的共享 (S) 鎖,除非將事務隔離級別設置為可重復讀或更高級別,或者在事務生存周期內用鎖定提示保留共享 (S) 鎖。

更新鎖
更新 (U) 鎖可以防止通常形式的死鎖。一般更新模式由一個事務組成,此事務讀取記錄,獲取資源(頁或行)的共享 (S) 鎖,然後修改行,此操作要求鎖轉換為排它 (X) 鎖。如果兩個事務獲得了資源上的共享模式鎖,然後試圖同時更新數據,則一個事務嘗試將鎖轉換為排它 (X) 鎖。共享模式到排它鎖的轉換必須等待一段時間,因為一個事務的排它鎖與其它事務的共享模式鎖不兼容;發生鎖等待。第二個事務試圖獲取排它 (X) 鎖以進行更新。由於兩個事務都要轉換為排它 (X) 鎖,並且每個事務都等待另一個事務釋放共享模式鎖,因此發生死鎖。

若要避免這種潛在的死鎖問題,請使用更新 (U) 鎖。一次只有一個事務可以獲得資源的更新 (U) 鎖。如果事務修改資源,則更新 (U) 鎖轉換為排它 (X) 鎖。否則,鎖轉換為共享鎖。

排它鎖
排它 (X) 鎖可以防止並發事務對資源進行訪問。其它事務不能讀取或修改排它 (X) 鎖鎖定的數據。

意向鎖
意向鎖表示 SQL Server 需要在層次結構中的某些底層資源上獲取共享 (S) 鎖或排它 (X) 鎖。例如,放置在表級的共享意向鎖表示事務打算在表中的頁或行上放置共享 (S) 鎖。在表級設置意向鎖可防止另一個事務隨後在包含那一頁的表上獲取排它 (X) 鎖。意向鎖可以提高性能,因為 SQL Server 僅在表級檢查意向鎖來確定事務是否可以安全地獲取該表上的鎖。而無須檢查表中的每行或每頁上的鎖以確定事務是否可以鎖定整個表。

意向鎖包括意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。

鎖模式 描述
意向共享 (IS) 通過在各資源上放置 S 鎖,表明事務的意向是讀取層次結構中的部分(而不是全部)底層資源。
意向排它 (IX) 通過在各資源上放置 X 鎖,表明事務的意向是修改層次結構中的部分(而不是全部)底層資源。IX 是 IS 的超集。
與意向排它共享 (SIX) 通過在各資源上放置 IX 鎖,表明事務的意向是讀取層次結構中的全部底層資源並修改部分(而不是全部)底層資源。允許頂層資源上的並發 IS 鎖。例如,表的 SIX 鎖在表上放置一個 SIX 鎖(允許並發 IS 鎖),在當前所修改頁上放置 IX 鎖(在已修改行上放置 X 鎖)。雖然每個資源在一段時間內只能有一個 SIX 鎖,以防止其它事務對資源進行更新,但是其它事務可以通過獲取表級的 IS 鎖來讀取層次結構中的底層資源。

獨占鎖:只允許進行鎖定操作的程序使用,其他任何對他的操作均不會被接受。執行數據更新命令時,SQL Server會自動使用獨占鎖。當對象上有其他鎖存在時,無法對其加獨占鎖。
共享鎖:共享鎖鎖定的資源可以被其他用戶讀取,但其他用戶無法修改它,在執行Select時,SQL Server會對對象加共享鎖。
更新鎖:當SQL Server准備更新數據時,它首先對數據對象作更新鎖鎖定,這樣數據將不能被修改,但可以讀取。等到SQL Server確定要進行更新數據操作時,他會自動將更新鎖換為獨占鎖,當對象上有其他鎖存在時,無法對其加更新鎖。

2. 從程序員的角度看:分為樂觀鎖和悲觀鎖。
樂觀鎖:完全依靠資料庫來管理鎖的工作。
悲觀鎖:程序員自己管理數據或對象上的鎖處理。

MS-SQLSERVER 使用鎖在多個同時在資料庫內執行修改的用戶間實現悲觀並發控制

三 鎖的粒度
鎖粒度是被封鎖目標的大小,封鎖粒度小則並發性高,但開銷大,封鎖粒度大則並發性低但開銷小

SQL Server支持的鎖粒度可以分為為行、頁、鍵、鍵范圍、索引、表或資料庫獲取鎖

資源 描述
RID 行標識符。用於單獨鎖定表中的一行。
鍵 索引中的行鎖。用於保護可串列事務中的鍵范圍。
頁 8 千位元組 (KB) 的數據頁或索引頁。
擴展盤區 相鄰的八個數據頁或索引頁構成的一組。
表 包括所有數據和索引在內的整個表。
DB 資料庫。

四 鎖定時間的長短

鎖保持的時間長度為保護所請求級別上的資源所需的時間長度。

用於保護讀取操作的共享鎖的保持時間取決於事務隔離級別。採用 READ COMMITTED 的默認事務隔離級別時,只在讀取頁的期間內控制共享鎖。在掃描中,直到在掃描內的下一頁上獲取鎖時才釋放鎖。如果指定 HOLDLOCK 提示或者將事務隔離級別設置為 REPEATABLE READ 或 SERIALIZABLE,則直到事務結束才釋放鎖。

根據為游標設置的並發選項,游標可以獲取共享模式的滾動鎖以保護提取。當需要滾動鎖時,直到下一次提取或關閉游標(以先發生者為准)時才釋放滾動鎖。但是,如果指定 HOLDLOCK,則直到事務結束才釋放滾動鎖。

用於保護更新的排它鎖將直到事務結束才釋放。
如果一個連接試圖獲取一個鎖,而該鎖與另一個連接所控制的鎖沖突,則試圖獲取鎖的連接將一直阻塞到:

將沖突鎖釋放而且連接獲取了所請求的鎖。

連接的超時間隔已到期。默認情況下沒有超時間隔,但是一些應用程序設置超時間隔以防止無限期等待

五 SQL Server 中鎖的自定義

1 處理死鎖和設置死鎖優先順序

死鎖就是多個用戶申請不同封鎖,由於申請者均擁有一部分封鎖權而又等待其他用戶擁有的部分封鎖而引起的無休止的等待

可以使用SET DEADLOCK_PRIORITY控制在發生死鎖情況時會話的反應方式。如果兩個進程都鎖定數據,並且直到其它進程釋放自己的鎖時,每個進程才能釋放自己的鎖,即發生死鎖情況。

2 處理超時和設置鎖超時持續時間。

@@LOCK_TIMEOUT 返回當前會話的當前鎖超時設置,單位為毫秒

SET LOCK_TIMEOUT 設置允許應用程序設置語句等待阻塞資源的最長時間。當語句等待的時間大於 LOCK_TIMEOUT 設置時,系統將自動取消阻塞的語句,並給應用程序返回"已超過了鎖請求超時時段"的 1222 號錯誤信息

示例
下例將鎖超時期限設置為 1,800 毫秒。
SET LOCK_TIMEOUT 1800

3) 設置事務隔離級別。

4 ) 對 SELECT、INSERT、UPDATE 和 DELETE 語句使用表級鎖定提示。

5) 配置索引的鎖定粒度
可以使用 sp_indexoption 系統存儲過程來設置用於索引的鎖定粒度

六 查看鎖的信息

1 執行 EXEC SP_LOCK 報告有關鎖的信息
2 查詢分析器中按Ctrl+2可以看到鎖的信息

七 使用注意事項

如何避免死鎖
1 使用事務時,盡量縮短事務的邏輯處理過程,及早提交或回滾事務;
2 設置死鎖超時參數為合理范圍,如:3分鍾-10分種;超過時間,自動放棄本次操作,避免進程懸掛;
3 優化程序,檢查並避免死鎖現象出現;
4 .對所有的腳本和SP都要仔細測試,在正是版本之前。
5 所有的SP都要有錯誤處理(通過@error)
6 一般不要修改SQL SERVER事務的默認級別。不推薦強行加鎖

解決問題 如何對行 表 資料庫加鎖

八 幾個有關鎖的問題

1 如何鎖一個表的某一行

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

SELECT * FROM table ROWLOCK WHERE id = 1

2 鎖定資料庫的一個表

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解鎖

幾個例子幫助大家加深印象
設table1(A,B,C)
A B C
a1 b1 c1
a2 b2 c2
a3 b3 c3

1)排它鎖
新建兩個連接
在第一個連接中執行以下語句
begin tran
update table1
set A='aa'
where B='b2'
waitfor delay '00:00:30' --等待30秒
commit tran
在第二個連接中執行以下語句
begin tran
select * from table1
where B='b2'
commit tran

若同時執行上述兩個語句,則select查詢必須等待update執行完畢才能執行即要等待30秒

2)共享鎖
在第一個連接中執行以下語句
begin tran
select * from table1 holdlock -holdlock人為加鎖
where B='b2'
waitfor delay '00:00:30' --等待30秒
commit tran

在第二個連接中執行以下語句
begin tran
select A,C from table1
where B='b2'
update table1
set A='aa'
where B='b2'
commit tran

若同時執行上述兩個語句,則第二個連接中的select查詢可以執行
而update必須等待第一個事務釋放共享鎖轉為排它鎖後才能執行 即要等待30秒

3)死鎖
增設table2(D,E)
D E
d1 e1
d2 e2
在第一個連接中執行以下語句
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

在第二個連接中執行以下語句
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

同時執行,系統會檢測出死鎖,並中止進程

補充一點:
Sql Server2000支持的表級鎖定提示

HOLDLOCK 持有共享鎖,直到整個事務完成,應該在被鎖對象不需要時立即釋放,等於SERIALIZABLE事務隔離級別

NOLOCK 語句執行時不發出共享鎖,允許臟讀 ,等於 READ UNCOMMITTED事務隔離級別

PAGLOCK 在使用一個表鎖的地方用多個頁鎖

READPAST 讓sql server跳過任何鎖定行,執行事務,適用於READ UNCOMMITTED事務隔離級別只跳過RID鎖,不跳過頁,區域和表鎖

ROWLOCK 強制使用行鎖

TABLOCKX 強制使用獨占表級鎖,這個鎖在事務期間阻止任何其他事務使用這個表

UPLOCK 強制在讀表時使用更新而不用共享鎖

應用程序鎖:
應用程序鎖就是客戶端代碼生成的鎖,而不是sql server本身生成的鎖

處理應用程序鎖的兩個過程

sp_getapplock 鎖定應用程序資源

sp_releaseapplock 為應用程序資源解鎖

注意: 鎖定資料庫的一個表的區別

SELECT * FROM table WITH (HOLDLOCK) 其他事務可以讀取表,但不能更新刪除

SELECT * FROM table WITH (TABLOCKX) 其他事務不能讀取表,更新和刪除
參考資料:

⑹ 備份sqlserver資料庫超時

  • 問題再現:使用SQL Server2008資料庫,右鍵點擊tempdb資料庫,查看屬性。

⑺ 如何處理SQL Server死鎖問題

死鎖,簡而言之,兩個或者多個trans,同時請求對方正在請求的某個對象,導致雙方互相等待。簡單的例子如下:
trans1 trans2
------------------------------------------------------------------------
1.IDBConnection.BeginTransaction 1.IDBConnection.BeginTransaction
2.update table A 2.update table B
3.update table B 3.update table A
4.IDBConnection.Commit 4.IDBConnection.Commit
那麼,很容易看到,如果trans1和trans2,分別到達了step3,那麼trans1會請求對於B的X鎖,trans2會請求對於A的X鎖,而二者的鎖在step2上已經被對方分別持有了。由於得不到鎖,後面的Commit無法執行,這樣雙方開始死鎖。
好,我們看一個簡單的例子,來解釋一下,應該如何解決死鎖問題。
-- Batch #1
CREATE DATABASE deadlocktest
GO
USE deadlocktest
SET NOCOUNT ON
DBCC TRACEON (1222, -1)
-- 在SQL2005中,增加了一個新的dbcc參數,就是1222,原來在2000下,我們知道,可以執行dbcc
--traceon(1204,3605,-1)看到所有的死鎖信息。SqlServer 2005中,對於1204進行了增強,這就是1222。
GO

IF OBJECT_ID ('t1') IS NOT NULL DROP TABLE t1
IF OBJECT_ID ('p1') IS NOT NULL DROP PROC p1
IF OBJECT_ID ('p2') IS NOT NULL DROP PROC p2
GO
CREATE TABLE t1 (c1 int, c2 int, c3 int, c4 char(5000))
GO
DECLARE @x int
SET @x = 1
WHILE (@x <= 1000) BEGIN
INSERT INTO t1 VALUES (@x*2, @x*2, @x*2, @x*2)
SET @x = @x + 1
END
GO
CREATE CLUSTERED INDEX cidx ON t1 (c1)
CREATE NONCLUSTERED INDEX idx1 ON t1 (c2)
GO
CREATE PROC p1 @p1 int AS SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1
GO
CREATE PROC p2 @p1 int AS
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1
UPDATE t1 SET c2 = c2-1 WHERE c1 = @p1
GO
上述sql創建一個deadlock的示範資料庫,插入了1000條數據,並在表t1上建立了c1列的聚集索引,和c2列的非聚集索引。另外創建了兩個sp,分別是從t1中select數據和update數據。
好,打開一個新的查詢窗口,我們開始執行下面的query:
-- Batch #2
USE deadlocktest
SET NOCOUNT ON
WHILE (1=1) EXEC p2 4
GO
開始執行後,然後我們打開第三個查詢窗口,執行下面的query:
-- Batch #3
USE deadlocktest
SET NOCOUNT ON
CREATE TABLE #t1 (c2 int, c3 int)
GO
WHILE (1=1) BEGIN
INSERT INTO #t1 EXEC p1 4
TRUNCATE TABLE #t1
END
GO
開始執行,哈哈,很快,我們看到了這樣的錯誤信息:
Msg 1205, Level 13, State 51, Procere p1, Line 4
Transaction (Process ID 54) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
spid54發現了死鎖。
那麼,我們該如何解決它?
在SqlServer 2005中,我們可以這么做:
1.在trans3的窗口中,選擇EXEC p1 4,然後right click,看到了菜單了嗎?選擇Analyse Query in Database Engine Tuning Advisor。
2.注意右面的窗口中,wordload有三個選擇:負載文件、表、查詢語句,因為我們選擇了查詢語句的方式,所以就不需要修改這個radio option了。
3.點左上角的Start Analysis按鈕
4.抽根煙,回來後看結果吧!出現了一個分析結果窗口,其中,在Index Recommendations中,我們發現了一條信息:大意是,在表t1上增加一個非聚集索引索引:t2+t1。
5.在當前窗口的上方菜單上,選擇Action菜單,選擇Apply Recommendations,系統會自動創建這個索引。
重新運行batch #3,呵呵,死鎖沒有了。
這種方式,我們可以解決大部分的Sql Server死鎖問題。那麼,發生這個死鎖的根本原因是什麼呢?為什麼增加一個non clustered index,問題就解決了呢? 這次,我們分析一下,為什麼會死鎖呢?再回顧一下兩個sp的寫法:
CREATE PROC p1 @p1 int AS
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1
GO
CREATE PROC p2 @p1 int AS
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1
UPDATE t1 SET c2 = c2-1 WHERE c1 = @p1
GO
很奇怪吧!p1沒有insert,沒有delete,沒有update,只是一個select,p2才是update。這個和我們前面說過的,trans1裡面updata A,update B;trans2裡面upate B,update A,根本不貼邊啊!
那麼,什麼導致了死鎖?
需要從事件日誌中,看sql的死鎖信息:
Spid X is running this query (line 2 of proc [p1], inputbuffer 「… EXEC p1 4 …」):
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1
Spid Y is running this query (line 2 of proc [p2], inputbuffer 「EXEC p2 4」):
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1

The SELECT is waiting for a Shared KEY lock on index t1.cidx. The UPDATE holds a conflicting X lock.
The UPDATE is waiting for an eXclusive KEY lock on index t1.idx1. The SELECT holds a conflicting S lock.
首先,我們看看p1的執行計劃。怎麼看呢?可以執行set statistics profile on,這句就可以了。下面是p1的執行計劃
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1
|--Nested Loops(Inner Join, OUTER REFERENCES:([Uniq1002], [t1].[c1]))
|--Index Seek(OBJECT:([t1].[idx1]), SEEK:([t1].[c2] >= [@p1] AND [t1].[c2] <= [@p1]+(1)) ORDERED FORWARD)
|--Clustered Index Seek(OBJECT:([t1].[cidx]), SEEK:([t1].[c1]=[t1].[c1] AND [Uniq1002]=[Uniq1002]) LOOKUP ORDERED FORWARD)
我們看到了一個nested loops,第一行,利用索引t1.c2來進行seek,seek出來的那個rowid,在第二行中,用來通過聚集索引來查找整行的數據。這是什麼?就是bookmark lookup啊!為什麼?因為我們需要的c2、c3不能完全的被索引t1.c1帶出來,所以需要書簽查找。
好,我們接著看p2的執行計劃。
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1
|--Clustered Index Update(OBJECT:([t1].[cidx]), OBJECT:([t1].[idx1]), SET:([t1].[c2] = [Expr1004]))
|--Compute Scalar(DEFINE:([Expr1013]=[Expr1013]))
|--Compute Scalar(DEFINE:([Expr1004]=[t1].[c2]+(1), [Expr1013]=CASE WHEN CASE WHEN ...
|--Top(ROWCOUNT est 0)
|--Clustered Index Seek(OBJECT:([t1].[cidx]), SEEK:([t1].[c1]=[@p1]) ORDERED FORWARD)
通過聚集索引的seek找到了一行,然後開始更新。這里注意的是,update的時候,它會申請一個針對clustered index的X鎖的。
實際上到這里,我們就明白了為什麼update會對select產生死鎖。update的時候,會申請一個針對clustered index的X鎖,這樣就阻塞住了(注意,不是死鎖!)select裡面最後的那個clustered index seek。死鎖的另一半在哪裡呢?注意我們的select語句,c2存在於索引idx1中,c1是一個聚集索引cidx。問題就在這里!我們在p2中更新了c2這個值,所以sqlserver會自動更新包含c2列的非聚集索引:idx1。而idx1在哪裡?就在我們剛才的select語句中。而對這個索引列的更改,意味著索引集合的某個行或者某些行,需要重新排列,而重新排列,需要一個X鎖。
SO………,問題就這樣被發現了。
總結一下,就是說,某個query使用非聚集索引來select數據,那麼它會在非聚集索引上持有一個S鎖。當有一些select的列不在該索引上,它需要根據rowid找到對應的聚集索引的那行,然後找到其他數據。而此時,第二個的查詢中,update正在聚集索引上忙乎:定位、加鎖、修改等。但因為正在修改的某個列,是另外一個非聚集索引的某個列,所以此時,它需要同時更改那個非聚集索引的信息,這就需要在那個非聚集索引上,加第二個X鎖。select開始等待update的X鎖,update開始等待select的S鎖,死鎖,就這樣發生鳥。
那麼,為什麼我們增加了一個非聚集索引,死鎖就消失鳥?我們看一下,按照上文中自動增加的索引之後的執行計劃:
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1
|--Index Seek(OBJECT:([deadlocktest].[dbo].[t1].[_dta_index_t1_7_2073058421__K2_K1_3]), SEEK:([deadlocktest].[dbo].[t1].[c2] >= [@p1] AND [deadlocktest].[dbo].[t1].[c2] <= [@p1]+(1)) ORDERED FORWARD)
哦,對於clustered index的需求沒有了,因為增加的覆蓋索引已經足夠把所有的信息都select出來。就這么簡單。
實際上,在sqlserver 2005中,如果用profiler來抓eventid:1222,那麼會出現一個死鎖的圖,很直觀的說。
下面的方法,有助於將死鎖減至最少(詳細情況,請看SQLServer聯機幫助,搜索:將死鎖減至最少即可。
按同一順序訪問對象。
避免事務中的用戶交互。
保持事務簡短並處於一個批處理中。
使用較低的隔離級別。
使用基於行版本控制的隔離級別。
將 READ_COMMITTED_SNAPSHOT 資料庫選項設置為 ON,使得已提交讀事務使用行版本控制。
使用快照隔離。
使用綁定連接。

⑻ sql server 怎麼保證查詢出的結果不能被其他電腦訪問,具體如下

這涉及到資料庫中,鎖的概念
首先,SQL Server更強調由系統來管理鎖。在用戶有SQL請求時,系統分析請求,自動在滿足鎖定條件和系統性能之間為資料庫加上適當的鎖,同時系統在運行期間常常自動進行優化處理,實行動態加鎖。也就是說,你的擔心是不必要的,SQLServer可以保證這種情況基本不會出現.如果特殊情況下,需要你手動出來,請參考下面文檔。
一. 為什麼要引入鎖
多個用戶同時對資料庫的並發操作時會帶來以下數據不一致的問題:
丟失更新
A,B兩個用戶讀同一數據並進行修改,其中一個用戶的修改結果破壞了另一個修改的結果,比如訂票系統
臟讀
A用戶修改了數據,隨後B用戶又讀出該數據,但A用戶因為某些原因取消了對數據的修改,數據恢復原值,此時B得到的數據就與資料庫內的數據產生了不一致
不可重復讀
A用戶讀取數據,隨後B用戶讀出該數據並修改,此時A用戶再讀取數據時發現前後兩次的值不一致
並發控制的主要方法是封鎖,鎖就是在一段時間內禁止用戶做某些操作以避免產生數據不一致
二 鎖的分類
鎖的類別有兩種分法:
1. 從資料庫系統的角度來看:分為獨占鎖(即排它鎖),共享鎖和更新鎖
MS-SQL Server 使用以下資源鎖模式。
鎖模式 描述
共享 (S) 用於不更改或不更新數據的操作(只讀操作),如 SELECT 語句。
更新 (U) 用於可更新的資源中。防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖。
排它 (X) 用於數據修改操作,例如 INSERT、UPDATE 或 DELETE。確保不會同時同一資源進行多重更新。
意向鎖 用於建立鎖的層次結構。意向鎖的類型為:意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
架構鎖 在執行依賴於表架構的操作時使用。架構鎖的類型為:架構修改 (Sch-M) 和架構穩定性 (Sch-S)。
大容量更新 (BU) 向表中大容量復制數據並指定了 TABLOCK 提示時使用。
共享鎖
共享 (S) 鎖允許並發事務讀取 (SELECT) 一個資源。資源上存在共享 (S) 鎖時,任何其它事務都不能修改數據。一旦已經讀取數據,便立即釋放資源上的共享 (S) 鎖,除非將事務隔離級別設置為可重復讀或更高級別,或者在事務生存周期內用鎖定提示保留共享 (S) 鎖。
更新鎖
更新 (U) 鎖可以防止通常形式的死鎖。一般更新模式由一個事務組成,此事務讀取記錄,獲取資源(頁或行)的共享 (S) 鎖,然後修改行,此操作要求鎖轉換為排它 (X) 鎖。如果兩個事務獲得了資源上的共享模式鎖,然後試圖同時更新數據,則一個事務嘗試將鎖轉換為排它 (X) 鎖。共享模式到排它鎖的轉換必須等待一段時間,因為一個事務的排它鎖與其它事務的共享模式鎖不兼容;發生鎖等待。第二個事務試圖獲取排它 (X) 鎖以進行更新。由於兩個事務都要轉換為排它 (X) 鎖,並且每個事務都等待另一個事務釋放共享模式鎖,因此發生死鎖。
若要避免這種潛在的死鎖問題,請使用更新 (U) 鎖。一次只有一個事務可以獲得資源的更新 (U) 鎖。如果事務修改資源,則更新 (U) 鎖轉換為排它 (X) 鎖。否則,鎖轉換為共享鎖。
排它鎖
排它 (X) 鎖可以防止並發事務對資源進行訪問。其它事務不能讀取或修改排它 (X) 鎖鎖定的數據。
意向鎖
意向鎖表示 SQL Server 需要在層次結構中的某些底層資源上獲取共享 (S) 鎖或排它 (X) 鎖。例如,放置在表級的共享意向鎖表示事務打算在表中的頁或行上放置共享 (S) 鎖。在表級設置意向鎖可防止另一個事務隨後在包含那一頁的表上獲取排它 (X) 鎖。意向鎖可以提高性能,因為 SQL Server 僅在表級檢查意向鎖來確定事務是否可以安全地獲取該表上的鎖。而無須檢查表中的每行或每頁上的鎖以確定事務是否可以鎖定整個表。
意向鎖包括意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
鎖模式 描述
意向共享 (IS) 通過在各資源上放置 S 鎖,表明事務的意向是讀取層次結構中的部分(而不是全部)底層資源。
意向排它 (IX) 通過在各資源上放置 X 鎖,表明事務的意向是修改層次結構中的部分(而不是全部)底層資源。IX 是 IS 的超集。
與意向排它共享 (SIX) 通過在各資源上放置 IX 鎖,表明事務的意向是讀取層次結構中的全部底層資源並修改部分(而不是全部)底層資源。允許頂層資源上的並發 IS 鎖。例如,表的 SIX 鎖在表上放置一個 SIX 鎖(允許並發 IS 鎖),在當前所修改頁上放置 IX 鎖(在已修改行上放置 X 鎖)。雖然每個資源在一段時間內只能有一個 SIX 鎖,以防止其它事務對資源進行更新,但是其它事務可以通過獲取表級的 IS 鎖來讀取層次結構中的底層資源。
獨占鎖:只允許進行鎖定操作的程序使用,其他任何對他的操作均不會被接受。執行數據更新命令時,SQL Server會自動使用獨占鎖。當對象上有其他鎖存在時,無法對其加獨占鎖。
共享鎖:共享鎖鎖定的資源可以被其他用戶讀取,但其他用戶無法修改它,在執行Select時,SQL Server會對對象加共享鎖。
更新鎖:當SQL Server准備更新數據時,它首先對數據對象作更新鎖鎖定,這樣數據將不能被修改,但可以讀取。等到SQL Server確定要進行更新數據操作時,他會自動將更新鎖換為獨占鎖,當對象上有其他鎖存在時,無法對其加更新鎖。
2. 從程序員的角度看:分為樂觀鎖和悲觀鎖。
樂觀鎖:完全依靠資料庫來管理鎖的工作。
悲觀鎖:程序員自己管理數據或對象上的鎖處理。
MS-SQLSERVER 使用鎖在多個同時在資料庫內執行修改的用戶間實現悲觀並發控制
三 鎖的粒度
鎖粒度是被封鎖目標的大小,封鎖粒度小則並發性高,但開銷大,封鎖粒度大則並發性低但開銷小
SQL Server支持的鎖粒度可以分為為行、頁、鍵、鍵范圍、索引、表或資料庫獲取鎖
資源 描述
RID 行標識符。用於單獨鎖定表中的一行。
鍵 索引中的行鎖。用於保護可串列事務中的鍵范圍。
頁 8 千位元組 (KB) 的數據頁或索引頁。
擴展盤區 相鄰的八個數據頁或索引頁構成的一組。
表 包括所有數據和索引在內的整個表。
DB 資料庫。
四 鎖定時間的長短
鎖保持的時間長度為保護所請求級別上的資源所需的時間長度。
用於保護讀取操作的共享鎖的保持時間取決於事務隔離級別。採用 READ COMMITTED 的默認事務隔離級別時,只在讀取頁的期間內控制共享鎖。在掃描中,直到在掃描內的下一頁上獲取鎖時才釋放鎖。如果指定 HOLDLOCK 提示或者將事務隔離級別設置為 REPEATABLE READ 或 SERIALIZABLE,則直到事務結束才釋放鎖。
根據為游標設置的並發選項,游標可以獲取共享模式的滾動鎖以保護提取。當需要滾動鎖時,直到下一次提取或關閉游標(以先發生者為准)時才釋放滾動鎖。但是,如果指定 HOLDLOCK,則直到事務結束才釋放滾動鎖。
用於保護更新的排它鎖將直到事務結束才釋放。
如果一個連接試圖獲取一個鎖,而該鎖與另一個連接所控制的鎖沖突,則試圖獲取鎖的連接將一直阻塞到:
將沖突鎖釋放而且連接獲取了所請求的鎖。
連接的超時間隔已到期。默認情況下沒有超時間隔,但是一些應用程序設置超時間隔以防止無限期等待
五 SQL Server 中鎖的自定義
1 處理死鎖和設置死鎖優先順序
死鎖就是多個用戶申請不同封鎖,由於申請者均擁有一部分封鎖權而又等待其他用戶擁有的部分封鎖而引起的無休止的等待
可以使用SET DEADLOCK_PRIORITY控制在發生死鎖情況時會話的反應方式。如果兩個進程都鎖定數據,並且直到其它進程釋放自己的鎖時,每個進程才能釋放自己的鎖,即發生死鎖情況。
2 處理超時和設置鎖超時持續時間。
@@LOCK_TIMEOUT 返回當前會話的當前鎖超時設置,單位為毫秒
SET LOCK_TIMEOUT 設置允許應用程序設置語句等待阻塞資源的最長時間。當語句等待的時間大於 LOCK_TIMEOUT 設置時,系統將自動取消阻塞的語句,並給應用程序返回"已超過了鎖請求超時時段"的 1222 號錯誤信息
示例
下例將鎖超時期限設置為 1,800 毫秒。
SET LOCK_TIMEOUT 1800
3) 設置事務隔離級別。
4 ) 對 SELECT、INSERT、UPDATE 和 DELETE 語句使用表級鎖定提示。
5) 配置索引的鎖定粒度
可以使用 sp_indexoption 系統存儲過程來設置用於索引的鎖定粒度
六 查看鎖的信息
1 執行 EXEC SP_LOCK 報告有關鎖的信息
2 查詢分析器中按Ctrl+2可以看到鎖的信息
七 使用注意事項
如何避免死鎖
1 使用事務時,盡量縮短事務的邏輯處理過程,及早提交或回滾事務;
2 設置死鎖超時參數為合理范圍,如:3分鍾-10分種;超過時間,自動放棄本次操作,避免進程懸掛;
3 優化程序,檢查並避免死鎖現象出現;
4 .對所有的腳本和SP都要仔細測試,在正是版本之前。
5 所有的SP都要有錯誤處理(通過@error)
6 一般不要修改SQL SERVER事務的默認級別。不推薦強行加鎖
解決問題 如何對行 表 資料庫加鎖
八 幾個有關鎖的問題
1 如何鎖一個表的某一行
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM table ROWLOCK WHERE id = 1
2 鎖定資料庫的一個表
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解鎖

幾個例子幫助大家加深印象
設table1(A,B,C)
A B C
a1 b1 c1
a2 b2 c2
a3 b3 c3
1)排它鎖
新建兩個連接
在第一個連接中執行以下語句
begin tran
update table1
set A='aa'
where B='b2'
waitfor delay '00:00:30' --等待30秒
commit tran
在第二個連接中執行以下語句
begin tran
select * from table1
where B='b2'
commit tran
若同時執行上述兩個語句,則select查詢必須等待update執行完畢才能執行即要等待30秒
2)共享鎖
在第一個連接中執行以下語句
begin tran
select * from table1 holdlock -holdlock人為加鎖
where B='b2'
waitfor delay '00:00:30' --等待30秒
commit tran
在第二個連接中執行以下語句
begin tran
select A,C from table1
where B='b2'
update table1
set A='aa'
where B='b2'
commit tran
若同時執行上述兩個語句,則第二個連接中的select查詢可以執行
而update必須等待第一個事務釋放共享鎖轉為排它鎖後才能執行 即要等待30秒
3)死鎖
增設table2(D,E)
D E
d1 e1
d2 e2
在第一個連接中執行以下語句
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
在第二個連接中執行以下語句
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
同時執行,系統會檢測出死鎖,並中止進程
補充一點:
Sql Server2000支持的表級鎖定提示
HOLDLOCK 持有共享鎖,直到整個事務完成,應該在被鎖對象不需要時立即釋放,等於SERIALIZABLE事務隔離級別
NOLOCK 語句執行時不發出共享鎖,允許臟讀 ,等於 READ UNCOMMITTED事務隔離級別
PAGLOCK 在使用一個表鎖的地方用多個頁鎖
READPAST 讓sql server跳過任何鎖定行,執行事務,適用於READ UNCOMMITTED事務隔離級別只跳過RID鎖,不跳過頁,區域和表鎖
ROWLOCK 強制使用行鎖
TABLOCKX 強制使用獨占表級鎖,這個鎖在事務期間阻止任何其他事務使用這個表
UPLOCK 強制在讀表時使用更新而不用共享鎖
應用程序鎖:
應用程序鎖就是客戶端代碼生成的鎖,而不是sql server本身生成的鎖
處理應用程序鎖的兩個過程
sp_getapplock 鎖定應用程序資源
sp_releaseapplock 為應用程序資源解鎖
注意: 鎖定資料庫的一個表的區別
SELECT * FROM table WITH (HOLDLOCK) 其他事務可以讀取表,但不能更新刪除
SELECT * FROM table WITH (TABLOCKX) 其他事務不能讀取表,更新和刪除

⑼ 如何處理SQL Server死鎖問題

死鎖,簡而言之,兩個或者多個trans,同時請求對方正在請求的某個對象,導致雙方互相等待。簡單的例子如下:
trans1 trans2
------------------------------------------------------------------------
1.IDBConnection.BeginTransaction 1.IDBConnection.BeginTransaction
2.update table A 2.update table B
3.update table B 3.update table A
4.IDBConnection.Commit 4.IDBConnection.Commit
那麼,很容易看到,如果trans1和trans2,分別到達了step3,那麼trans1會請求對於B的X鎖,trans2會請求對於A的X鎖,而二者的鎖在step2上已經被對方分別持有了。由於得不到鎖,後面的Commit無法執行,這樣雙方開始死鎖。
好,我們看一個簡單的例子,來解釋一下,應該如何解決死鎖問題。
-- Batch #1
CREATE DATABASE deadlocktest
GO
USE deadlocktest
SET NOCOUNT ON
DBCC TRACEON (1222, -1)
-- 在SQL2005中,增加了一個新的dbcc參數,就是1222,原來在2000下,我們知道,可以執行dbcc
--traceon(1204,3605,-1)看到所有的死鎖信息。SqlServer 2005中,對於1204進行了增強,這就是1222。
GO

IF OBJECT_ID ('t1') IS NOT NULL DROP TABLE t1
IF OBJECT_ID ('p1') IS NOT NULL DROP PROC p1
IF OBJECT_ID ('p2') IS NOT NULL DROP PROC p2
GO
CREATE TABLE t1 (c1 int, c2 int, c3 int, c4 char(5000))
GO
DECLARE @x int
SET @x = 1
WHILE (@x <= 1000) BEGIN
INSERT INTO t1 VALUES (@x*2, @x*2, @x*2, @x*2)
SET @x = @x + 1
END
GO
CREATE CLUSTERED INDEX cidx ON t1 (c1)
CREATE NONCLUSTERED INDEX idx1 ON t1 (c2)
GO
CREATE PROC p1 @p1 int AS SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1
GO
CREATE PROC p2 @p1 int AS
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1
UPDATE t1 SET c2 = c2-1 WHERE c1 = @p1
GO
上述sql創建一個deadlock的示範資料庫,插入了1000條數據,並在表t1上建立了c1列的聚集索引,和c2列的非聚集索引。另外創建了兩個sp,分別是從t1中select數據和update數據。
好,打開一個新的查詢窗口,我們開始執行下面的query:
-- Batch #2
USE deadlocktest
SET NOCOUNT ON
WHILE (1=1) EXEC p2 4
GO
開始執行後,然後我們打開第三個查詢窗口,執行下面的query:
-- Batch #3
USE deadlocktest
SET NOCOUNT ON
CREATE TABLE #t1 (c2 int, c3 int)
GO
WHILE (1=1) BEGIN
INSERT INTO #t1 EXEC p1 4
TRUNCATE TABLE #t1
END
GO
開始執行,哈哈,很快,我們看到了這樣的錯誤信息:
Msg 1205, Level 13, State 51, Procere p1, Line 4
Transaction (Process ID 54) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
spid54發現了死鎖。
那麼,我們該如何解決它?
在SqlServer 2005中,我們可以這么做:
1.在trans3的窗口中,選擇EXEC p1 4,然後right click,看到了菜單了嗎?選擇Analyse Query in Database Engine Tuning Advisor。
2.注意右面的窗口中,wordload有三個選擇:負載文件、表、查詢語句,因為我們選擇了查詢語句的方式,所以就不需要修改這個radio option了。
3.點左上角的Start Analysis按鈕
4.抽根煙,回來後看結果吧!出現了一個分析結果窗口,其中,在Index Recommendations中,我們發現了一條信息:大意是,在表t1上增加一個非聚集索引索引:t2+t1。
5.在當前窗口的上方菜單上,選擇Action菜單,選擇Apply Recommendations,系統會自動創建這個索引。
重新運行batch #3,呵呵,死鎖沒有了。
這種方式,我們可以解決大部分的Sql Server死鎖問題。那麼,發生這個死鎖的根本原因是什麼呢?為什麼增加一個non clustered index,問題就解決了呢? 這次,我們分析一下,為什麼會死鎖呢?再回顧一下兩個sp的寫法:
CREATE PROC p1 @p1 int AS
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1
GO
CREATE PROC p2 @p1 int AS
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1
UPDATE t1 SET c2 = c2-1 WHERE c1 = @p1
GO
很奇怪吧!p1沒有insert,沒有delete,沒有update,只是一個select,p2才是update。這個和我們前面說過的,trans1裡面updata A,update B;trans2裡面upate B,update A,根本不貼邊啊!
那麼,什麼導致了死鎖?
需要從事件日誌中,看sql的死鎖信息:
Spid X is running this query (line 2 of proc [p1], inputbuffer 「… EXEC p1 4 …」):
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1
Spid Y is running this query (line 2 of proc [p2], inputbuffer 「EXEC p2 4」):
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1

The SELECT is waiting for a Shared KEY lock on index t1.cidx. The UPDATE holds a conflicting X lock.
The UPDATE is waiting for an eXclusive KEY lock on index t1.idx1. The SELECT holds a conflicting S lock.
首先,我們看看p1的執行計劃。怎麼看呢?可以執行set statistics profile on,這句就可以了。下面是p1的執行計劃
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1
|--Nested Loops(Inner Join, OUTER REFERENCES:([Uniq1002], [t1].[c1]))
|--Index Seek(OBJECT:([t1].[idx1]), SEEK:([t1].[c2] >= [@p1] AND [t1].[c2] <= [@p1]+(1)) ORDERED FORWARD)
|--Clustered Index Seek(OBJECT:([t1].[cidx]), SEEK:([t1].[c1]=[t1].[c1] AND [Uniq1002]=[Uniq1002]) LOOKUP ORDERED FORWARD)
我們看到了一個nested loops,第一行,利用索引t1.c2來進行seek,seek出來的那個rowid,在第二行中,用來通過聚集索引來查找整行的數據。這是什麼?就是bookmark lookup啊!為什麼?因為我們需要的c2、c3不能完全的被索引t1.c1帶出來,所以需要書簽查找。
好,我們接著看p2的執行計劃。
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p1
|--Clustered Index Update(OBJECT:([t1].[cidx]), OBJECT:([t1].[idx1]), SET:([t1].[c2] = [Expr1004]))
|--Compute Scalar(DEFINE:([Expr1013]=[Expr1013]))
|--Compute Scalar(DEFINE:([Expr1004]=[t1].[c2]+(1), [Expr1013]=CASE WHEN CASE WHEN ...
|--Top(ROWCOUNT est 0)
|--Clustered Index Seek(OBJECT:([t1].[cidx]), SEEK:([t1].[c1]=[@p1]) ORDERED FORWARD)
通過聚集索引的seek找到了一行,然後開始更新。這里注意的是,update的時候,它會申請一個針對clustered index的X鎖的。
實際上到這里,我們就明白了為什麼update會對select產生死鎖。update的時候,會申請一個針對clustered index的X鎖,這樣就阻塞住了(注意,不是死鎖!)select裡面最後的那個clustered index seek。死鎖的另一半在哪裡呢?注意我們的select語句,c2存在於索引idx1中,c1是一個聚集索引cidx。問題就在這里!我們在p2中更新了c2這個值,所以sqlserver會自動更新包含c2列的非聚集索引:idx1。而idx1在哪裡?就在我們剛才的select語句中。而對這個索引列的更改,意味著索引集合的某個行或者某些行,需要重新排列,而重新排列,需要一個X鎖。
SO………,問題就這樣被發現了。
總結一下,就是說,某個query使用非聚集索引來select數據,那麼它會在非聚集索引上持有一個S鎖。當有一些select的列不在該索引上,它需要根據rowid找到對應的聚集索引的那行,然後找到其他數據。而此時,第二個的查詢中,update正在聚集索引上忙乎:定位、加鎖、修改等。但因為正在修改的某個列,是另外一個非聚集索引的某個列,所以此時,它需要同時更改那個非聚集索引的信息,這就需要在那個非聚集索引上,加第二個X鎖。select開始等待update的X鎖,update開始等待select的S鎖,死鎖,就這樣發生鳥。
那麼,為什麼我們增加了一個非聚集索引,死鎖就消失鳥?我們看一下,按照上文中自動增加的索引之後的執行計劃:
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+1
|--Index Seek(OBJECT:([deadlocktest].[dbo].[t1].[_dta_index_t1_7_2073058421__K2_K1_3]), SEEK:([deadlocktest].[dbo].[t1].[c2] >= [@p1] AND [deadlocktest].[dbo].[t1].[c2] <= [@p1]+(1)) ORDERED FORWARD)
哦,對於clustered index的需求沒有了,因為增加的覆蓋索引已經足夠把所有的信息都select出來。就這么簡單。
實際上,在sqlserver 2005中,如果用profiler來抓eventid:1222,那麼會出現一個死鎖的圖,很直觀的說。
下面的方法,有助於將死鎖減至最少(詳細情況,請看SQLServer聯機幫助,搜索:將死鎖減至最少即可。
按同一順序訪問對象。
避免事務中的用戶交互。
保持事務簡短並處於一個批處理中。
使用較低的隔離級別。
使用基於行版本控制的隔離級別。
將 READ_COMMITTED_SNAPSHOT 資料庫選項設置為 ON,使得已提交讀事務使用行版本控制。
使用快照隔離。
使用綁定連接。

⑽ 如何查看SQL Server 2008的死鎖

為了查看死鎖信息,資料庫引擎提供了監視工具,分別為兩個跟蹤標志以及
SQL
Server
Profiler中的死鎖圖形事件。
跟蹤標志
1204
和跟蹤標志
1222
發生死鎖時,跟蹤標志
1204
和跟蹤標志
1222
會返回在
SQL
Server
錯誤日誌中捕獲的信息。跟蹤標志
1204
會報告由死鎖所涉及的每個節點設置格式的死鎖信息。跟蹤標志
1222
會設置死鎖信息的格式,順序為先按進程,然後按資源。可以同時啟用這兩個跟蹤標志,以獲取同一個死鎖事件的兩種表示形式。
SQL
Server
Profiler
中的
TraceEvent
Class:
LocksEvent
Name:
Deadlock
Graph
提供
一個XML
圖表.,你可以從中看出發生了什麼。

熱點內容
資料庫相關論文 發布:2024-04-16 17:20:31 瀏覽:16
中山php培訓 發布:2024-04-16 16:57:29 瀏覽:951
java類實例 發布:2024-04-16 16:26:59 瀏覽:706
ipa編譯和反編譯 發布:2024-04-16 16:03:46 瀏覽:634
驗證身份證的密碼是什麼密碼 發布:2024-04-16 16:03:34 瀏覽:948
每個函數都能獨立的編譯 發布:2024-04-16 15:54:39 瀏覽:749
javacdll 發布:2024-04-16 15:24:55 瀏覽:608
編譯js代碼 發布:2024-04-16 15:16:20 瀏覽:32
gcc編譯教程 發布:2024-04-16 15:16:13 瀏覽:703
dh演算法簽名 發布:2024-04-16 14:54:32 瀏覽:810