SQL Server 中的 ACID 屬性

来源:https://www.cnblogs.com/broadm/archive/2022/07/13/16473717.html
-Advertisement-
Play Games

SQL Server 中的事務是什麼? SQL Server 中的事務是一組被視為一個單元的 SQL 語句,它們按照“做所有事或不做任何事”的原則執行,成功的事務必須通過 ACID 測試。 事務的 ACID 屬性是什麼? 首字母縮寫詞 ACID 是指事務的四個關鍵屬性 原子性: Atomicity ...


SQL Server 中的事務是什麼?

SQL Server 中的事務是一組被視為一個單元的 SQL 語句,它們按照“做所有事或不做任何事”的原則執行,成功的事務必須通過 ACID 測試。

事務的 ACID 屬性是什麼?

首字母縮寫詞 ACID 是指事務的四個關鍵屬性

  • 原子性: Atomicity
  • 一致性: Consistency
  • 隔離性: Isolation
  • 持久性: Durability

為了理解這一點,我們將使用以下兩個表測試。

Product (產品表)

ProductID Name Price Quantity
101 Laptop 15000 100
102 Desktop 20000 150
104 Mobile 3000 200
105 Tablet 4000 250

ProductSales (產品銷售表)

ProductSalesID ProductID QuantitySold
1 101 10
2 102 15
3 104 30
4 105 35

請使用以下 SQL 腳本創建並使用示例數據填充 Product 和 ProductSales 表。

IF OBJECT_ID('dbo.Product','U') IS NOT NULL
    DROP TABLE dbo.Product
IF OBJECT_ID('dbo.ProductSales','U') IS NOT NULL
    DROP TABLE dbo.ProductSales
GO
CREATE TABLE Product
(
  ProductID INT PRIMARY KEY, 
  Name VARCHAR(40), 
  Price INT,
  Quantity INT
 )
GO
INSERT INTO Product VALUES(101, 'Laptop', 15000, 100)
INSERT INTO Product VALUES(102, 'Desktop', 20000, 150)
INSERT INTO Product VALUES(103, 'Mobile', 3000, 200)
INSERT INTO Product VALUES(104, 'Tablet', 4000, 250)
GO
CREATE TABLE ProductSales
(
  ProductSalesId INT PRIMARY KEY,
  ProductId INT,
  QuantitySold INT
) 
GO
INSERT INTO ProductSales VALUES(1, 101, 10)
INSERT INTO ProductSales VALUES(2, 102, 15)
INSERT INTO ProductSales VALUES(3, 103, 30)
INSERT INTO ProductSales VALUES(4, 104, 35)
GO

SQL Server 中事務的原子性

SQL Server 中事務的原子性確保事務中的所有 DML 語句(即插入、更新、刪除)成功完成或全部回滾。例如,在以下 spSellProduct 存儲過程中,UPDATE 和 INSERT 語句都應該成功。如果 UPDATE 語句成功而 INSERT 語句失敗,資料庫應該通過回滾來撤消 UPDATE 語句所做的更改。

IF OBJECT_ID('spSellProduct','P') IS NOT NULL
    DROP PROCEDURE spSellProduct
GO
CREATE PROCEDURE spSellProduct
@ProductID INT,
@QuantityToSell INT
AS
BEGIN
  
  -- 首先我們需要檢查待銷售產品的可用庫存
  DECLARE @StockAvailable INT
  SELECT @StockAvailable = Quantity FROM Product WHERE ProductId = @ProductId

  --如果可用庫存小於要銷售的數量,拋出錯誤
  IF(@StockAvailable < @QuantityToSell)
  BEGIN
    Raiserror('可用庫存不足',16,1)
  END

  -- 如果可用庫存充足
  ELSE
  BEGIN
    BEGIN TRY
      -- 我們需要開啟一個事務
      BEGIN TRANSACTION

      -- 首先做減庫存操作
      UPDATE Product SET Quantity = (Quantity - @QuantityToSell) WHERE ProductID = @ProductID

      -- 計算當前最大的產品銷售ID,即 MaxProductSalesId
      DECLARE @MaxProductSalesId INT
      SELECT @MaxProductSalesId = CASE 
          WHEN MAX(ProductSalesId) IS NULL THEN 0 
          ELSE MAX(ProductSalesId) 
          END 
      FROM ProductSales

      -- 把 @MaxProductSalesId 加一, 所以我們會避免主鍵衝突 
      --(解釋下,建表的時候,沒有設置主鍵自增,所以需要人工處理自增)
      Set @MaxProductSalesId = @MaxProductSalesId + 1

      -- 把銷售的產品數量記錄到ProductSales表中
      INSERT INTO ProductSales VALUES (@MaxProductSalesId, @ProductId, @QuantityToSell)

      -- 最後,提交事務
      COMMIT TRANSACTION
    END TRY

    BEGIN CATCH
      -- 如果發生了異常,回滾事務
      ROLLBACK TRANSACTION
    END CATCH

  End
END

SQL Server 中事務的一致性

SQL Server 中事務的一致性確保資料庫數據在事務開始之前處於一致狀態,並且在事務完成後也使數據保持一致狀態。如果事務違反規則,則應回滾。例如,如果可用庫存從 Product 表中減少,那麼 ProductSales 表中必須有一個相關條目。

在我們的示例中,假設事務更新了 product 表中的可用數量,突然出現系統故障(就在插入 ProductSales 表之前或中間)。在這種情況下系統會回滾更新,否則我們無法追蹤庫存信息。

SQL Server 中事務的隔離性

SQL Server 中事務的隔離性確保事務的中間狀態對其他事務不可見。一個事務所做的數據修改必須與所有其他事務所做的數據修改隔離。大多數資料庫使用鎖定來維護事務隔離

為了理解事務的隔離性,我們將使用兩個獨立的 SQL Server 事務。從第一個事務開始,我們啟動了事務並更新了 Product 表中的記錄,但我們還沒有提交或回滾事務。在第二個事務中,我們使用 select 語句來選擇 Product 表中存在的記錄,如下所示。

在sqlserver management studio 或 Navicat 中新建兩個獨立的查詢視窗

首先在第1個視窗運行以下事務,更新庫存(註意事務沒有提交或回滾,回滾語句被註釋了)

begin tran
update dbo.Product set Quantity = 150 where ProductID = 101
--rollback tran

然後在第2個視窗運行以下語句,查詢被更新的產品

select * from dbo.Product where ProductID = 101

你會發現,第2個視窗中的查詢語句被阻塞了(一直處於運行狀態,沒有返回數據)

解決阻塞: 切換到第1個視窗, (按下滑鼠左鍵拖動選擇 rollback tran ,註意不包含註釋 -- ),
然後單獨執行這個語句, 在 sqlserver management studio 直接點擊執行就行, 在 Navicat 中,點擊運行按鈕右邊的下拉箭頭,點擊運行已選擇的,好了,再切換到第2個視窗,你會發現結果出來了

阻塞的原因: SqlServer預設的事務隔離級別是 Read Committed,
在上述的Update語句執行時會在對應的數據行上加一個 排它鎖(X), 直到事務提交或者回滾才會釋放,這保證了在此期間,其他任何事務都不能操作此行數據(查詢也不行),因為排它鎖(也叫獨占鎖),和其他類型的鎖都是不相容的,這保證了其他事務看不到另一個事務的中間狀態,即避免了臟讀

SQL Server 中事務的持久性

SQL Server 中事務的持久性確保一旦事務成功完成,它對資料庫所做的更改將是永久性的。即使出現系統故障或電源故障或任何異常變化,它也應該保護已提交的數據。

註意:首字母縮寫詞 ACID 由 Andreas Reuter 和 Theo Härder 在 1983 年創建,然而,Jim Gray 在 1970 年代後期已經定義了這些屬性。大多數流行的資料庫,如 SQL Server、Oracle、MySQL、Postgre SQL 預設都遵循 ACID 屬性。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • EditReady for Mac是專業高效的視頻轉碼器,擁有快速,強大的特點,可以調整視頻大小,對視頻進行旋轉,重新定時等功能,對於需要的朋友,還可以查看和編輯元數據,EditReady Mac版可以對視頻進行自定義,是非常強大的視頻轉碼器。 詳情:EditReady for Mac(專業視頻轉碼 ...
  • apache編譯安裝以及三種風格的init程式特點和區別 源碼包編譯實例 下麵通過編譯安裝httpd來深入理解源碼包安裝(httpd-2.4.54) 下載編譯工具,httpd以及其兩個依賴包的源碼包 //源碼包建議到官方網站下載 [root@lnh ~]# mkdir xbz [root@lnh ~ ...
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 Eclipse中配置maven 1.Eclipse中預設的Maven配置 可以使用預設的,本地倉庫在當前用戶下的.m2文件夾下。 2.配置我們自己安裝的maven 2.1指定配置安裝maven的路徑 2.2關聯setting.xml文件 2.3配 ...
  • DBeaverEE for Mac是一款運行在MacOS上通用的資料庫管理工具。易用性是DBeaverEE的主要目標,支持 MySQL, PostgreSQL, Oracle等常用資料庫。操作簡單,功能強大。 詳情:DBeaverEE for Mac(資料庫管理工具) 功能特點 連接到各種數據源 1 ...
  • 為什麼我們需要 SQL Server 中的異常處理? 讓我們通過一個示例來瞭解 SQL Server 中異常處理的必要性。因此,創建一個 SQL Server 存儲過程,通過執行以下查詢來除以兩個數字。 IF OBJECT_ID('spDivideTwoNumber','P') IS NOT NUL ...
  • all的用法 與子查詢配合使用 在all的用法中,有三種 第一種: <>all類似於not in 等效於not in 語法:select 列名 from 表名 where 列名 <> all(select 列名 from 表名 where 條件表達式); 例如1:顯示表中與CLERK部門的員工工資都 ...
  • # md函數筆記五 註:筆記旨在記錄 五、MySQL 流程式控制制函數 | \ | 函 數 名 稱 | 作 用 | 完 成 | |: :|: |: |: :| | 1 | IF | 條件判斷 | 勾 | | 2 | IFNULL | 判空判斷 | 勾 | | 3 | CASE | 求數量 | 勾 | 0 ...
  • PostgreSQL 的 Slogan 是 "世界上最先進的開源關係型資料庫"。 PostgreSQL是一個功能非常強大、源代碼開放的對象關係資料庫系統(ORDBMS),在靈活的BSD許可證下發行。PostgreSQL可以運行在所有主要操作系統。PostgreSQL是以加州大學伯克利分校電腦系開發 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...