1. 程式人生 > >【SQL】- 基礎知識梳理(八) - 事務與鎖

【SQL】- 基礎知識梳理(八) - 事務與鎖

隔離性 rep del 數據表 訪問 關系 snapshot 轉換 pro

事務的概念

事務:若幹條T-SQL指令組成的一個操作數據庫的最小執行單元,這個整體要麽全部成功,要麽全部失敗。(並發控制)

事務的四個屬性:原子性、一致性、隔離性、持久性。稱為事務的ACID特性。

  • 原子性(atomicity)一個事務是一個不可分割的工作單位,事務中包括的諸操作要麽都做,要麽都不做。
  • 一致性(consistency)事務內的操作都不能違反數據庫約束或規則,事務完成時的內部數據結構都必須是正確的。
  • 隔離性(isolation)並發多個事務時,各個事務不幹涉內部數據,處理的都是另外一個事務處理之前或之後的數據,不可能是另一個事務處理中的數據。
  • 持久性(durability)也稱永久性(permanence),指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。

SQL Server中3類常見的事務

自動提交事務:是一種能夠自動執行並能自動回滾事務,這種方式是T-SQL的默認事務方式。例如在刪除一個表記錄的時候,如果這條記錄有主外鍵關系的時候,刪除就會受主外鍵約束的影響,那麽這個刪除就會取消。
顯式事務: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 tran_Addtable1
--錯誤捕捉
begin try
--語句正確
insert into table1 (id,name,value,sex) values (
4,michael2,chaoshuai2,1); --加入保存點 -- save tran pigOneIn --sex為int型 出錯 insert into table1 (id,name,value,sex) values (5,michael3,chaoshuai3,天氣下雨了); insert into table1 (id,name,value,sex) values (6,michael4,chaoshuai4,1); 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 tran_Addtable1 ---由於出錯,這裏回滾事務到原點,第一條語句也沒有插入成功。 end catch if(@@TRANCOUNT>0) commit tran tran_Addtable1 --提交事務

執行結果

技術分享

分析:由於插入table1時發生錯誤,根據事務的原子性,要麽全做,要全不錯,所以一條數據都沒有插入

事務的並發控制

在多用戶都用事務同時訪問同一個數據資源的情況下,就會造成以下幾種數據錯誤
1.更新丟失:多個用戶同時對一個數據資源進行更新,必定會產生被覆蓋的數據,造成數據讀寫異常。
2.不可重復讀:如果一個用戶在一個事務中多次讀取一條數據,而另外一個用戶則同時更新啦這條數據,造成第一個用戶多次讀取數據不一致。
3.臟讀:第一個事務讀取第二個事務正在更新的數據表,如果第二個事務還沒有更新完成,那麽第一個事務讀取的數據將是一半為更新過的,一半還沒更新過的數據,這樣的數據毫無意義。
4.幻讀:第一個事務讀取一個結果集後,第二個事務,對這個結果集經行增刪操作,然而第一個事務中再次對這個結果集進行查詢時,數據發現丟失或新增。

設置事務隔離級別

read uncommitted:這個隔離級別最低啦,可以讀取到一個事務正在處理的數據,但事務還未提交,這種級別的讀取叫做臟讀。
read committed:這個級別是默認選項,不能臟讀,不能讀取事務正在處理沒有提交的數據,但能修改。
repeatable read:不能讀取事務正在處理的數據,也不能修改事務處理數據前的數據。
snapshot:指定事務在開始的時候,就獲得了已經提交數據的快照,因此當前事務只能看到事務開始之前對數據所做的修改。
serializable:最高事務隔離級別,只能看到事務處理之前的數據。

鎖的概念

Microsoft SQL Server 數據庫引擎使用不同的鎖模式鎖定資源,這些鎖模式確定了並發事務訪問資源的方式。

鎖的分類

  • 共享鎖:允許並發事務在封閉式並發控制下讀取(SELECT)資源。資源上存在共享鎖(S 鎖)時,任何其他事務都不能修改數據。 讀取操作一完成,就立即釋放資源上的共享鎖(S 鎖);
  • 排他鎖:可以防止並發事務對資源進行訪問。使用排他鎖時,任何其他事務都無法修改數據;數據修改語句(如 INSERT、UPDATE 和 DELETE)合並了修改和讀取操作,通常請求共享鎖和排他鎖
  • 更新鎖:防止常見的死鎖。此事務讀取數據 [獲取資源(頁或行)的共享鎖(S 鎖)],然後修改數據 [此操作要求鎖轉換為排他鎖(X 鎖)]。果兩個事務獲得了資源上的共享模式鎖,然後試圖同時更新數據,則一個事務嘗試將鎖轉換為排他鎖(X 鎖)。 共享模式到排他鎖的轉換必須等待一段時間,因為一個事務的排他鎖與其他事務的共享模式鎖不兼容;發生鎖等待。 第二個事務試圖獲取排他鎖(X 鎖)以進行更新。 由於兩個事務都要轉換為排他鎖(X 鎖),並且每個事務都等待另一個事務釋放共享模式鎖,因此發生死鎖。

   更新鎖(U 鎖)使得一次只有一個事務可以獲得資源的更新鎖(U 鎖)。 如果事務修改資源,則更新鎖(U 鎖)轉換為排他鎖(X 鎖)

  • 意向鎖:數據庫引擎使用意向鎖來保護共享鎖(S 鎖)或排他鎖(X 鎖)放置在鎖層次結構的底層資源上。在較低級別鎖前可獲取它們,因此會通知意向將鎖放置在較低級別上。

   例如,在該表的頁或行上請求共享鎖(S 鎖)之前,在表級請求共享意向鎖。 在表級設置意向鎖可防止另一個事務隨後在包含那一頁的表上獲取排他鎖(X 鎖)。 意向鎖可以提高性能,因為數據庫引擎僅在表檢  查意向鎖來確定事務是否可以安全地獲取該表上的鎖。 而不需要檢查表中的每行或每頁上的鎖以確定事務是否可以鎖定整個表。

  • 意向鎖包括意向共享 (IS)、意向排他 (IX) 以及意向排他共享 (SIX)。
  • 架構鎖:數據庫引擎在表數據定義語言 (DDL) 操作(例如添加列或刪除表)的過程中使用架構修改 (Sch-M) 鎖。 保持該鎖期間,Sch-M 鎖將阻止對表進行並發訪問。
  • 大容量更新鎖: 大容量更新鎖(BU 鎖)允許多個線程將數據並發地大容量加載到同一表,同時防止其他不進行大容量加載數據的進程訪問該表。

鎖模式兼容性

技術分享

如何將死鎖降低到最低

按同一順序訪問對象。
避免事務中的用戶交互。
保持事務簡短並處於一個批處理中。
使用較低的隔離級別。
使用基於行版本控制的隔離級別。
將 READ_COMMITTED_SNAPSHOT 數據庫選項設置為 ON,使得已提交讀事務使用行版本控制。
使用快照隔離。
使用綁定連接。

【SQL】- 基礎知識梳理(八) - 事務與鎖