SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)
1、了解事務(wù)和鎖
事務(wù):保持邏輯數(shù)據(jù)一致性與可恢復(fù)性,必不可少的利器。
鎖:多用戶訪問同一數(shù)據(jù)庫資源時,對訪問的先后次序權(quán)限管理的一種機制,沒有他事務(wù)或許將會一塌糊涂,不能保證數(shù)據(jù)的安全正確讀寫。
死鎖:是數(shù)據(jù)庫性能的重量級殺手之一,而死鎖卻是不同事務(wù)之間搶占數(shù)據(jù)資源造成的。
一個事務(wù)中可以包含多個DML語句,一個DDL語句或者一個DCL語句。
事務(wù)中的語句要么全部執(zhí)行,要么全部不執(zhí)行。
書面解釋:事務(wù)具有原子性,一致性,隔離性,持久性(ACID)
- A 原子性:事務(wù)必須是一個自動工作的單元,要么全部執(zhí)行,要么全部不執(zhí)行。
- C 一致性:事務(wù)把數(shù)據(jù)庫從一個一致狀態(tài)帶入到另一個一致狀態(tài),事務(wù)結(jié)束的時候,所有的內(nèi)部數(shù)據(jù)都是正確的。
- I 隔離性:并發(fā)多個事務(wù)時,一個事務(wù)的執(zhí)行不受其他事務(wù)的影響。
- D 持久性:事務(wù)提交之后,數(shù)據(jù)是永久性的,不可再回滾,不受關(guān)機等事件的影響。
事務(wù)在如下情況終止:
然而在SQL Server中事務(wù)被分為3類常見的事務(wù):
- 自動提交事務(wù):是SQL Server默認(rèn)的一種事務(wù)模式,每條Sql語句都被看成一個事務(wù)進行處理,你應(yīng)該沒有見過,一條Update 修改2個字段的語句,只修該了1個字段而另外一個字段沒有修改。。
- 顯式事務(wù):T-sql標(biāo)明,由Begin Transaction開啟事務(wù)開始,由Commit Transaction 提交事務(wù)、Rollback Transaction 回滾事務(wù)結(jié)束。
- 隱式事務(wù):使用Set IMPLICIT_TRANSACTIONS ON 將將隱式事務(wù)模式打開,不用Begin Transaction開啟事務(wù),當(dāng)一個事務(wù)結(jié)束,這個模式會自動啟用下一個事務(wù),只用Commit Transaction 提交事務(wù)、Rollback Transaction 回滾事務(wù)即可
2、顯式事務(wù)的應(yīng)用
常用語句就四個。
- Begin Transaction:標(biāo)記事務(wù)開始。
- Commit Transaction:事務(wù)已經(jīng)成功執(zhí)行,數(shù)據(jù)已經(jīng)處理妥當(dāng)。
- Rollback Transaction:數(shù)據(jù)處理過程中出錯,回滾到?jīng)]有處理之前的數(shù)據(jù)狀態(tài),或回滾到事務(wù)內(nèi)部的保存點。
- Save Transaction:事務(wù)內(nèi)部設(shè)置的保存點,就是事務(wù)可以不全部回滾,只回滾到這里,保證事務(wù)內(nèi)部不出錯的前提下。
3、事務(wù)設(shè)置保存點
利用save transaction? ?和rollback transaction 語句:
---開啟事務(wù) begin tran --錯誤捕捉機制,看好啦,這里也有的。并且可以嵌套。 begin try --語句正確insert into lives (Eat,Play,Numb) values ('豬肉','足球',1) --加入保存點save tran pigOneIninsert into lives (Eat,Play,Numb) values ('豬肉','足球',2)insert into lives (Eat,Play,Numb) values ('狗肉','籃球',3) end try begin catchselect Error_number() as ErrorNumber, --錯誤代碼Error_severity() as ErrorSeverity, --錯誤嚴(yán)重級別,級別小于10 try catch 捕獲不到Error_state() as ErrorState , --錯誤狀態(tài)碼Error_Procedure() as ErrorProcedure , --出現(xiàn)錯誤的存儲過程或觸發(fā)器的名稱。Error_line() as ErrorLine, --發(fā)生錯誤的行號Error_message() as ErrorMessage --錯誤的具體信息if(@@trancount>0) --全局變量@@trancount,事務(wù)開啟此值+1,他用來判斷是有開啟事務(wù)rollback tran end catch if(@@trancount>0) rollback tran pigOneIn --表本身為空表,ID ,Numb為int 類型,其它為nvarchar類型 select * from lives注:事務(wù)保存點以上的都將影響,當(dāng)提交事務(wù)以后,只有保存點之前的語句被執(zhí)行。
事務(wù)保存點示例:
在SQL Server中使用rollback會回滾所有的未提交事務(wù)狀態(tài),但是有些時候我們只需要回滾部分語句,把不需要回滾的語句提到事務(wù)外面來,雖然是個方法,但是卻破壞了事務(wù)的ACID。
SQL中使用事務(wù)保存點,即可解決這個問題。
SQL 事務(wù)中存在錯誤信息 進行Catch 回滾事務(wù)時
begin trybegin tran Ainsert into dbo.lives ( Eat, Play, Numb, times ) values ( 'A', '', 0, getdate() )select 1/0 --錯誤信息save tran B_Pointinsert into dbo.lives ( Eat, Play, Numb, times ) values ( 'B', '', 0, getdate() )save tran C_Pointinsert into dbo.lives ( Eat, Play, Numb, times ) values ( 'C', '', 0, getdate() )rollback tran B_Point --回滾事務(wù)點B_Point 即事務(wù)點下的部分都回滾select 1commit tran A --提交整個事務(wù)信息 end try begin catchselect 2rollback tran B_Point --回滾事務(wù)點B_Point 即事務(wù)點下的部分都回滾commit tran A --提交整個事務(wù)信息 end catch goselect * from dbo.lives goSQL回滾局部信息時:
begin trybegin tran Ainsert into dbo.lives ( Eat, Play, Numb, times ) values ( 'A', '', 0, getdate() )--select 1/0 --錯誤信息save tran B_Pointinsert into dbo.lives ( Eat, Play, Numb, times ) values ( 'B', '', 0, getdate() )save tran C_Pointinsert into dbo.lives ( Eat, Play, Numb, times ) values ( 'C', '', 0, getdate() )rollback tran B_Point --回滾事務(wù)點B_Point 即事務(wù)點下的部分都回滾select 1commit tran A --提交整個事務(wù)信息 end try begin catchselect 2rollback tran B_Point --回滾事務(wù)點B_Point 即事務(wù)點下的部分都回滾commit tran A --提交整個事務(wù)信息 end catch goselect * from dbo.lives go回滾保存點B時 即保存點以下部分均要回滾,
注:使用保存點 無論try 或 catch 代碼塊 除提交或回滾保存點外,都要COMMIT或 ROLLBACK完整事務(wù)。
使用場景:當(dāng)操作數(shù)據(jù)時前校驗數(shù)據(jù)成本太高且數(shù)據(jù)出錯率不高時 可采用.eg:用戶下單 檢查庫存信息是否>0時 可以設(shè)置庫存量需>=0的約束 當(dāng)更新庫時信息小于0即出錯 進行事務(wù)回滾 并查詢返回當(dāng)前庫存信息。
4、使用set xact_abort
設(shè)置 xact_abort on/off , 指定是否回滾當(dāng)前事務(wù),為on時如果當(dāng)前sql出錯,回滾整個事務(wù),為off時如果sql出錯回滾當(dāng)前sql語句,其它語句照常運行讀寫數(shù)據(jù)庫。
delete lives --清空數(shù)據(jù) set xact_abort off begin tran --語句正確insert into lives (Eat,Play,Numb) values ('豬肉','足球',1) --Numb為int類型,出錯,如果1234..那個大數(shù)據(jù)換成'132dsaf' xact_abort將失效insert into lives (Eat,Play,Numb) values ('豬肉','足球',12345646879783213)--語句正確insert into lives (Eat,Play,Numb) values ('狗肉','籃球',3) commit tran select * from lives為on時,結(jié)果集為空,因為運行是數(shù)據(jù)過大溢出出錯,回滾整個事務(wù)。
?
總結(jié)
以上是生活随笔為你收集整理的SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL基础【十七、uuid()、sys_
- 下一篇: SQL基础【十九、触发器】(不建议使用触