或者當一個操作員對一個對象作讀操作時。另一個操作員對此對象作寫操作的時候
如何避免死鎖發生
/********** 加鎖 ***************
設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
同時執行,系統會檢測出死鎖,並中止進程
--------------------------------------------------------------
SET IMPLICIT_TRANSACTIONS ON --用戶每次必須顯式提交或回滾。否則當用戶斷開連接時,
--事務及其所包含的所有數據更改將回滾
SET IMPLICIT_TRANSACTIONS OFF --自動提交模式。在自動提交模式下,如果各個語句成功
--完成則提交。
1:如上
2: 如何鎖一個表的某一行
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 語句中“加鎖選項”的功能說明
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 將在整個表上置排它鎖直至該命令或事務結束。這將防止其他進程讀取或修改表中的數據。
--或者自己加鎖(控制更靈活)
--鎖定記錄,只允許單用戶修改的例子:
--創建測試環境
--創建測試表--部門表
create table 部門(departmentid int,name varchar(10))
--記錄鎖定表
create table lock(departmentid int,dt datetime)
go
--因爲函數中不可以用getdate,所以用個視圖,得到當前時間
create view v_getdate as select dt=getdate()
go
--創建自定義函數,判斷記錄是否鎖定
create function f_chk(@departmentid int)
returns bit
as
begin
declare @re bit,@dt datetime
select @dt=dt from v_getdate
if exists(select 1 from lock where departmentid=@departmentid
and datediff(ss,dt,@dt)<5)
set @re=1
else
set @re=0
return(@re)
end
go
--數據處理測試
if dbo.f_chk(3)=1
print '記錄被鎖定'
else
begin
--也可以是查詢
begin tran
insert into lock values(3,getdate())
update 部門 set name='A' where departmentid=3
delete from lock where departmentid=3
commit tran
end
--刪除測試環境
drop table 部門
drop view v_getdate
drop function f_chk
如果是死鎖可以查一下: 1:sp_who 或 sp_who2 2: Select * from sysprocesses where blocked <> 0 3: 企業管理器->服務器->管理工具->活動->當前活動 然後把他kill掉。。。 進程信息中,如果發現旁邊有一個鎖狀的圖標,就表明這個進程是死鎖,kill掉 4:SQL事件探查器,監控一下,看主要是那些處理引起的死鎖.然後做相應的處理. 用事件探查器new一個trace,監視一下造成你sqlserver停頓的情況。。。 最好的辦法還是檢查一下引起鎖的原因,一般是由你的代碼引起的。
經過根蹤調試。我發現問題如下:
1。當一個操作對一張表進行讀操作的時候。這時如果另一個表進行讀操作沒有問題。如果
另一個操作對這個表進行寫操作的時候。就會出現這樣的情況。在單擊保存時。會持續等。
只有另一個讀操作的程序。退出讀表的界面。這個就會保存成功。
2。如果把同樣的環境改到我的筆記本上沒有這個問題。如果再放到IBM服務器上就會出現上述所講的問題。
現有疑問如下:
1。爲何筆記本做服務(P41。8CPU。256M)沒有問題。面用IBM做服務器有問題?
2。如果我把SQLCA。AUTOCOMMIT=FALSE改爲SQLCA。AUTOCOMMIT=TRUE。這個問題就不存在了。但是我想這只是從表面上解決了這個問題。沒有從根上解決這個問題。
3。如果是多個工作站。一臺用SQLCA。AUTOCOMMIT=TRUE,另一臺AUTOCOMMIT=FALSE會有問題嗎。?如果我想進行ROLLBACK操作會有問題嗎?
4。如果在同一個網段上有兩個SQLSERVER2000服務器會有影響嗎?