事務:保持邏輯數據一致性與可恢復性,必不可少的利器。
鎖:多用戶訪問同一數據庫資源時,對訪問的先后次序權限管理的一種機制,沒有他事務或許將會一塌糊涂,不能保證數據的安全正確讀寫。
死鎖:是數據庫性能的重量級殺手之一,而死鎖卻是不同事務之間搶占數據資源造成的。
不懂的聽上去,挺神奇的,懂的感覺我在扯淡,下面帶你好好領略下他們的風采,嗅査下他們的狂騷。。
先說事務--概念,分類用華仔無間道中的一句來給你詮釋下:去不了終點,回到原點。
舉例說明:
在一個事務中,你寫啦2條sql語句,一條是修改訂單表狀態,一條是修改庫存表庫存-1 。 如果在修改訂單表狀態的時候出錯,事務能夠回滾,數據將恢復到沒修改之前的數據狀態,下面的修改庫存也就不執行,這樣確保你關系邏輯的一致,安全。。
事務就是這個樣子,倔脾氣,要么全部執行,要么全部不執行,回到原數據狀態。
書面解釋:事務具有原子性,一致性,隔離性,持久性。
然而在SQL Server中事務被分為3類常見的事務:
常用語句就四個。
上面的都是心法,下面的給你來個招式,要看仔細啦。
1 ---開啟事務 2 begin tran 3 --錯誤撲捉機制,看好啦,這里也有的。并且可以嵌套。 4 begin try 5 --語句正確 6 insert into lives (Eat,Play,Numb) values ('豬肉','足球',1) 7 --Numb為int類型,出錯 8 insert into lives (Eat,Play,Numb) values ('豬肉','足球','abc') 9 --語句正確10 insert into lives (Eat,Play,Numb) values ('狗肉','籃球',2)11 end try12 begin catch13 select Error_number() as ErrorNumber, --錯誤代碼14 Error_severity() as ErrorSeverity, --錯誤嚴重級別,級別小于10 try catch 捕獲不到15 Error_state() as ErrorState , --錯誤狀態碼16 Error_PRocedure() as ErrorProcedure , --出現錯誤的存儲過程或觸發器的名稱。17 Error_line() as ErrorLine, --發生錯誤的行號18 Error_message() as ErrorMessage --錯誤的具體信息19 if(@@trancount>0) --全局變量@@trancount,事務開啟此值+1,他用來判斷是有開啟事務20 rollback tran ---由于出錯,這里回滾到開始,第一條語句也沒有插入成功。21 end catch22 if(@@trancount>0)23 commit tran --如果成功Lives表中,將會有3條數據。24 25 --表本身為空表,ID ,Numb為int 類型,其它為nvarchar類型26 select * from lives
---開啟事務begin tran--錯誤撲捉機制,看好啦,這里也有的。并且可以嵌套。begin try --語句正確 insert into lives (Eat,Play,Numb) values ('豬肉','足球',1) --加入保存點 save tran pigOneIn --Numb為int類型,出錯 insert into lives (Eat,Play,Numb) values ('豬肉','足球',2) --語句正確 insert into lives (Eat,Play,Numb) values ('狗肉','籃球',3)end trybegin catch select Error_number() as ErrorNumber, --錯誤代碼 Error_severity() as ErrorSeverity, --錯誤嚴重級別,級別小于10 try catch 捕獲不到 Error_state() as ErrorState , --錯誤狀態碼 Error_Procedure() as ErrorProcedure , --出現錯誤的存儲過程或觸發器的名稱。 Error_line() as ErrorLine, --發生錯誤的行號 Error_message() as ErrorMessage --錯誤的具體信息 if(@@trancount>0) --全局變量@@trancount,事務開啟此值+1,他用來判斷是有開啟事務 rollback tran ---由于出錯,這里回滾事務到原點,第一條語句也沒有插入成功。end catchif(@@trancount>0)rollback tran pigOneIn --如果成功Lives表中,將會有3條數據。--表本身為空表,ID ,Numb為int 類型,其它為nvarchar類型select * from lives
設置 xact_abort on/off , 指定是否回滾當前事務,為on時如果當前sql出錯,回滾整個事務,為off時如果sql出錯回滾當前sql語句,其它語句照常運行讀寫數據庫。
需要注意的時:xact_abort只對運行時出現的錯誤有用,如果sql語句存在編譯時錯誤,那么他就失靈啦。
delete lives --清空數據set xact_abort offbegin tran --語句正確 insert into lives (Eat,Play,Numb) values ('豬肉','足球',1) --Numb為int類型,出錯,如果1234..那個大數據換成'132dsaf' xact_abort將失效 insert into lives (Eat,Play,Numb) values ('豬肉','足球',12345646879783213) --語句正確 insert into lives (Eat,Play,Numb) values ('狗肉','籃球',3)commit transelect * from lives
為on時,結果集為空,因為運行是數據過大溢出出錯,回滾整個事務。
事務把死鎖給整出來啦跟著做:打開兩個查詢窗口,把下面的語句,分別放入2個查詢窗口,在5秒內運行2個事務模塊。
begin tran update lives set play='羽毛球' waitfor delay '0:0:5' update dbo.Earth set Animal='老虎' commit tran
begin tran update Earth set Animal='老虎' waitfor delay '0:0:5' --等待5秒執行下面的語句 update lives set play='羽毛球'commit transelect * from livesselect * from Earth
為什么呢,下面我們看看鎖,什么是鎖。
并發事務成敗皆歸于鎖——鎖定在多用戶都用事務同時訪問同一個數據資源的情況下,就會造成以下幾種數據錯誤。
然而鎖定,就是為解決這些問題所生的,他的存在使得一個事務對他自己的數據塊進行操作的時候,而另外一個事務則不能插足這些數據塊。這就是所謂的鎖定。
鎖定從數據庫系統的角度大致可以分為6種:
這些鎖之間的相互兼容性,也就是,是否可以同時存在。
現有的授權模式 | ||||||
---|---|---|---|---|---|---|
請求的模式 | IS | S | U | IX | SIX | X |
意向共享 (IS) | 是 | 是 | 是 | 是 | 是 | 否 |
共享 (S) | 是 | 是 | 是 | 否 | 否 | 否 |
更新 (U) | 是 | 是 | 否 | 否 | 否 | 否 |
意向排他 (IX) | 是 | 否 | 否 | 是 | 否 | 否 |
意向排他共享 (SIX) | 是 | 否 | 否 | 否 | 否 | 否 |
排他 (X) | 否 | 否 | 否 | 否 | 否 | 否 |
鎖兼容性具體參見:http://msdn.microsoft.com/zh-cn/library/ms186396.aspx
鎖粒度和層次結構參見:http://msdn.microsoft.com/zh-cn/library/ms189849(v=sql.105).aspx
死鎖什么是死鎖,為什么會產生死鎖。我用 “事務把死鎖給整出來啦” 標題下的兩個事務產生的死鎖來解釋應該會更加生動形象點。
例子是這樣的:
第一個事務(稱為A):先更新lives表 --->>停頓5秒---->>更新earth表
第二個事務(稱為B):先更新earth表--->>停頓5秒---->>更新lives表
先執行事務A----5秒之內---執行事務B,出現死鎖現象。
過程是這樣子的:
這樣相互等待對方釋放資源,造成資源讀寫擁擠堵塞的情況,就被稱為死鎖現象,也叫做阻塞。而為什么會產生,上例就列舉出來啦。
然而數據庫并沒有出現無限等待的情況,是因為數據庫搜索引擎會定期檢測這種狀況,一旦發現有情況,立馬選擇一個事務作為犧牲品。犧牲的事務,將會回滾數據。有點像兩個人在過獨木橋,兩個無腦的人都走在啦獨木橋中間,如果不落水,必定要有一個人給退回來。這種相互等待的過程,是一種耗時耗資源的現象,所以能避則避。
哪個人會被退回來,作為犧牲品,這個我們是可以控制的??刂普Z法:
set deadlock_priority <級別>
死鎖處理的優先級別為 low<normal<high,不指定的情況下默認為normal,犧牲品為隨機。如果指定,犧牲品為級別低的。
還可以使用數字來處理標識級別:-10到-5為low,-5為normal,-5到10為high。
減少死鎖的發生,提高數據庫性能死鎖耗時耗資源,然而在大型數據庫中,高并發帶來的死鎖是不可避免的,所以我們只能讓其變的更少。
新聞熱點
疑難解答