網(wǎng)站首頁 編程語言 正文
SQL Server 中的事務(wù)是什么?
SQL Server 中的事務(wù)是一組被視為一個(gè)單元的 SQL 語句,它們按照“做所有事或不做任何事”的原則執(zhí)行,成功的事務(wù)必須通過 ACID 測(cè)試。
事務(wù)的 ACID 屬性是什么?
首字母縮寫詞 ACID 是指事務(wù)的四個(gè)關(guān)鍵屬性
- 原子性: Atomicity
- 一致性: Consistency
- 隔離性: Isolation
- 持久性: Durability
為了理解這一點(diǎn),我們將使用以下兩個(gè)表測(cè)試。
Product (產(chǎn)品表)
ProductID | Name | Price | Quantity |
---|---|---|---|
101 | Laptop | 15000 | 100 |
102 | Desktop | 20000 | 150 |
104 | Mobile | 3000 | 200 |
105 | Tablet | 4000 | 250 |
ProductSales (產(chǎn)品銷售表)
ProductSalesID | ProductID | QuantitySold |
---|---|---|
1 | 101 | 10 |
2 | 102 | 15 |
3 | 104 | 30 |
4 | 105 | 35 |
請(qǐng)使用以下 SQL 腳本創(chuàng)建并使用示例數(shù)據(jù)填充 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 中事務(wù)的原子性
SQL Server 中事務(wù)的原子性確保事務(wù)中的所有 DML 語句(即插入、更新、刪除)成功完成或全部回滾。例如,在以下 spSellProduct 存儲(chǔ)過程中,UPDATE 和 INSERT 語句都應(yīng)該成功。如果 UPDATE 語句成功而 INSERT 語句失敗,數(shù)據(jù)庫應(yīng)該通過回滾來撤消 UPDATE 語句所做的更改。
IF OBJECT_ID('spSellProduct','P') IS NOT NULL DROP PROCEDURE spSellProduct GO CREATE PROCEDURE spSellProduct @ProductID INT, @QuantityToSell INT AS BEGIN -- 首先我們需要檢查待銷售產(chǎn)品的可用庫存 DECLARE @StockAvailable INT SELECT @StockAvailable = Quantity FROM Product WHERE ProductId = @ProductId --如果可用庫存小于要銷售的數(shù)量,拋出錯(cuò)誤 IF(@StockAvailable < @QuantityToSell) BEGIN Raiserror('可用庫存不足',16,1) END -- 如果可用庫存充足 ELSE BEGIN BEGIN TRY -- 我們需要開啟一個(gè)事務(wù) BEGIN TRANSACTION -- 首先做減庫存操作 UPDATE Product SET Quantity = (Quantity - @QuantityToSell) WHERE ProductID = @ProductID -- 計(jì)算當(dāng)前最大的產(chǎn)品銷售ID,即 MaxProductSalesId DECLARE @MaxProductSalesId INT SELECT @MaxProductSalesId = CASE WHEN MAX(ProductSalesId) IS NULL THEN 0 ELSE MAX(ProductSalesId) END FROM ProductSales -- 把 @MaxProductSalesId 加一, 所以我們會(huì)避免主鍵沖突 --(解釋下,建表的時(shí)候,沒有設(shè)置主鍵自增,所以需要人工處理自增) Set @MaxProductSalesId = @MaxProductSalesId + 1 -- 把銷售的產(chǎn)品數(shù)量記錄到ProductSales表中 INSERT INTO ProductSales VALUES (@MaxProductSalesId, @ProductId, @QuantityToSell) -- 最后,提交事務(wù) COMMIT TRANSACTION END TRY BEGIN CATCH -- 如果發(fā)生了異常,回滾事務(wù) ROLLBACK TRANSACTION END CATCH End END
SQL Server 中事務(wù)的一致性
SQL Server 中事務(wù)的一致性確保數(shù)據(jù)庫數(shù)據(jù)在事務(wù)開始之前處于一致狀態(tài),并且在事務(wù)完成后也使數(shù)據(jù)保持一致狀態(tài)。如果事務(wù)違反規(guī)則,則應(yīng)回滾。例如,如果可用庫存從 Product 表中減少,那么 ProductSales 表中必須有一個(gè)相關(guān)條目。
在我們的示例中,假設(shè)事務(wù)更新了 product 表中的可用數(shù)量,突然出現(xiàn)系統(tǒng)故障(就在插入 ProductSales 表之前或中間)。在這種情況下系統(tǒng)會(huì)回滾更新,否則我們無法追蹤庫存信息。
SQL Server 中事務(wù)的隔離性
SQL Server 中事務(wù)的隔離性確保事務(wù)的中間狀態(tài)對(duì)其他事務(wù)不可見。一個(gè)事務(wù)所做的數(shù)據(jù)修改必須與所有其他事務(wù)所做的數(shù)據(jù)修改隔離。大多數(shù)數(shù)據(jù)庫使用鎖定來維護(hù)事務(wù)隔離。
為了理解事務(wù)的隔離性,我們將使用兩個(gè)獨(dú)立的 SQL Server 事務(wù)。從第一個(gè)事務(wù)開始,我們啟動(dòng)了事務(wù)并更新了 Product 表中的記錄,但我們還沒有提交或回滾事務(wù)。在第二個(gè)事務(wù)中,我們使用 select 語句來選擇 Product 表中存在的記錄,如下所示。
在sqlserver management studio 或 Navicat 中新建兩個(gè)獨(dú)立的查詢窗口
首先在第1個(gè)窗口運(yùn)行以下事務(wù),更新庫存(注意事務(wù)沒有提交或回滾,回滾語句被注釋了)
begin tran update dbo.Product set Quantity = 150 where ProductID = 101 --rollback tran
然后在第2個(gè)窗口運(yùn)行以下語句,查詢被更新的產(chǎn)品
select * from dbo.Product where ProductID = 101
你會(huì)發(fā)現(xiàn),第2個(gè)窗口中的查詢語句被阻塞了(一直處于運(yùn)行狀態(tài),沒有返回?cái)?shù)據(jù))
解決阻塞: 切換到第1個(gè)窗口, (按下鼠標(biāo)左鍵拖動(dòng)選擇 rollback tran
,注意不包含注釋 -- ),
然后單獨(dú)執(zhí)行這個(gè)語句, 在 sqlserver management studio 直接點(diǎn)擊執(zhí)行就行, 在 Navicat 中,點(diǎn)擊運(yùn)行按鈕右邊的下拉箭頭,點(diǎn)擊運(yùn)行已選擇的,好了,再切換到第2個(gè)窗口,你會(huì)發(fā)現(xiàn)結(jié)果出來了
阻塞的原因: SqlServer默認(rèn)的事務(wù)隔離級(jí)別是 Read Committed,
在上述的Update語句執(zhí)行時(shí)會(huì)在對(duì)應(yīng)的數(shù)據(jù)行上加一個(gè) 排它鎖(X), 直到事務(wù)提交或者回滾才會(huì)釋放,這保證了在此期間,其他任何事務(wù)都不能操作此行數(shù)據(jù)(查詢也不行),因?yàn)榕潘i(也叫獨(dú)占鎖),和其他類型的鎖都是不兼容的,這保證了其他事務(wù)看不到另一個(gè)事務(wù)的中間狀態(tài),即避免了臟讀
SQL Server 中事務(wù)的持久性
SQL Server 中事務(wù)的持久性確保一旦事務(wù)成功完成,它對(duì)數(shù)據(jù)庫所做的更改將是永久性的。即使出現(xiàn)系統(tǒng)故障或電源故障或任何異常變化,它也應(yīng)該保護(hù)已提交的數(shù)據(jù)。
注意:首字母縮寫詞 ACID 由 Andreas Reuter 和 Theo H?rder 在 1983 年創(chuàng)建,然而,Jim Gray 在 1970 年代后期已經(jīng)定義了這些屬性。大多數(shù)流行的數(shù)據(jù)庫,如 SQL Server、Oracle、MySQL、Postgre SQL 默認(rèn)都遵循 ACID 屬性。
原文鏈接:https://www.cnblogs.com/broadm/p/16473717.html
相關(guān)推薦
- 2022-09-29 docker啟動(dòng)rabbitmq以及使用方式詳解_docker
- 2022-09-25 python?opencv實(shí)現(xiàn)圖像矯正功能_python
- 2022-09-12 C語言多媒體框架GStreamer使用教程深講_C 語言
- 2022-11-20 Pandas數(shù)據(jù)處理庫畫圖與文件讀取使用示例_python
- 2022-05-14 Python函數(shù)中的作用域規(guī)則詳解_python
- 2022-04-17 ajax請(qǐng)求成功后,設(shè)定一定時(shí)間過后執(zhí)行關(guān)閉窗口命令
- 2023-06-18 Docker之實(shí)現(xiàn)掛載的三種方式匯總_docker
- 2022-04-04 vscode中將.art文件與html文件相關(guān)聯(lián)
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支