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