SQL事務


了解事務和鎖

事務:保持邏輯數據一致性與可恢復性,必不可少的利器。

:多用戶訪問同一數據庫資源時,對訪問的先后次序權限管理的一種機制,沒有他事務或許將會一塌糊塗,不能保證數據的安全正確讀寫。

死鎖:是數據庫性能的重量級殺手之一,而死鎖卻是不同事務之間搶占數據資源造成的。

一個事務中可以包含多個DML語句,一個DDL語句或者一個DCL語句。

事務中的語句要么全部執行,要么全部不執行。

書面解釋:事務具有原子性,一致性,隔離性,持久性(ACID)

  • A 原子性:事務必須是一個自動工作的單元,要么全部執行,要么全部不執行。
  • C 一致性:事務把數據庫從一個一致狀態帶入到另一個一致狀態,事務結束的時候,所有的內部數據都是正確的。
  • I 隔離性:並發多個事務時,一個事務的執行不受其他事務的影響。
  • D 持久性:事務提交之后,數據是永久性的,不可再回滾,不受關機等事件的影響。

事務在如下情況終止:

  1. 遇到rollback commit命令
  2. 遇到DDL或者DCL語句.
  3. 系統發生錯誤,崩潰或者退出。

然而在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 回滾事務即可

顯式事務的應用

常用語句就四個。

  • Begin Transaction:標記事務開始。
  • Commit Transaction:事務已經成功執行,數據已經處理妥當。
  • Rollback Transaction:數據處理過程中出錯,回滾到沒有處理之前的數據狀態,或回滾到事務內部的保存點。
  • Save Transaction:事務內部設置的保存點,就是事務可以不全部回滾,只回滾到這里,保證事務內部不出錯的前提下。
---開啟事務
begin tran
--錯誤捕捉機制,看好啦,這里也有的。並且可以嵌套。
begin try --語句正確
   insert into lives (Eat,Play,Numb) values ('豬肉','足球',1) --Numb為int類型,出錯
   insert into lives (Eat,Play,Numb) values ('豬肉','足球','abc') --語句正確
   insert into lives (Eat,Play,Numb) values ('狗肉','籃球',2) end try begin 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 catch if(@@trancount>0) commit tran  --如果成功Lives表中,將會有3條數據。

--表本身為空表,ID ,Numb為int 類型,其它為nvarchar類型
select * from lives

事務設置保存點

利用save transaction   和rollback transaction 語句,

---開啟事務
begin tran
--錯誤捕捉機制,看好啦,這里也有的。並且可以嵌套。
begin try --語句正確
   insert into lives (Eat,Play,Numb) values ('豬肉','足球',1) --加入保存點
   save tran pigOneIn
   insert into lives (Eat,Play,Numb) values ('豬肉','足球',2)
   insert into lives (Eat,Play,Numb) values ('狗肉','籃球',3) end try begin 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 catch if(@@trancount>0) rollback tran pigOneIn 

--表本身為空表,ID ,Numb為int 類型,其它為nvarchar類型
select * from lives

注:事務保存點以上的都將影響,當提交事務以后,只有保存點之前的語句被執行。

事務保存點示例:

在SQL Server中使用rollback會回滾所有的未提交事務狀態,但是有些時候我們只需要回滾部分語句,把不需要回滾的語句提到事務外面來,雖然是個方法,但是卻破壞了事務的ACID。

SQL中使用事務保存點,即可解決這個問題。

SQL 事務中存在錯誤信息 進行Catch 回滾事務時

begin try begin tran A insert into dbo.lives ( Eat, Play, Numb, times ) values ( 'A', '', 0, getdate() ) select 1/0    --錯誤信息
    save tran B_Point insert into dbo.lives ( Eat, Play, Numb, times ) values ( 'B', '', 0, getdate() ) save tran C_Point insert into dbo.lives ( Eat, Play, Numb, times ) values ( 'C', '', 0, getdate() ) rollback tran B_Point    --回滾事務點B_Point 即事務點下的部分都回滾
    select 1
    commit tran A    --提交整個事務信息
end try begin catch select 2
    rollback tran B_Point    --回滾事務點B_Point 即事務點下的部分都回滾
    commit tran A    --提交整個事務信息
end catch go

select * from dbo.lives go

 

 SQL回滾局部信息時

begin try begin tran A insert into dbo.lives ( Eat, Play, Numb, times ) values ( 'A', '', 0, getdate() ) --select 1/0 --錯誤信息
    save tran B_Point insert into dbo.lives ( Eat, Play, Numb, times ) values ( 'B', '', 0, getdate() ) save tran C_Point insert into dbo.lives ( Eat, Play, Numb, times ) values ( 'C', '', 0, getdate() ) rollback tran B_Point    --回滾事務點B_Point 即事務點下的部分都回滾
    select 1
    commit tran A    --提交整個事務信息
end try begin catch select 2
    rollback tran B_Point    --回滾事務點B_Point 即事務點下的部分都回滾
    commit tran A    --提交整個事務信息
end catch go

select * from dbo.lives go

回滾保存點B時 即保存點以下部分均要回滾,

注:使用保存點 無論try 或 catch 代碼塊 除提交或回滾保存點外,都要COMMIT或 ROLLBACK完整事務。

使用場景:當操作數據時前校驗數據成本太高且數據出錯率不高時 可采用.eg:用戶下單 檢查庫存信息是否>0時 可以設置庫存量需>=0的約束 當更新庫時信息小於0即出錯 進行事務回滾 並查詢返回當前庫存信息

使用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時,結果集為空,因為運行是數據過大溢出出錯,回滾整個事務。

 

 

 

 

 

 

 

 

 

 

原文鏈接:https://www.cnblogs.com/knowledgesea/p/3714417.html

     https://www.cnblogs.com/tx720/p/8472806.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM