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 属性。

SQL Server 中的 ACID 属性的更多相关文章

  1. SQL SERVER中的扩展属性

    以前在SQL SERVER建表时,总看到扩展属性,但一直未使用过.今天研究下: 增加扩展属性: 语法: sp_addextendedproperty [ @name = ] { 'property_n ...

  2. 浅谈SQL Server中的事务日志(三)----在简单恢复模式下日志的角色

    简介 在简单恢复模式下,日志文件的作用仅仅是保证了SQL Server事务的ACID属性.并不承担具体的恢复数据的角色.正如”简单”这个词的字面意思一样,数据的备份和恢复仅仅是依赖于手动备份和恢复.在 ...

  3. SQL Server中的事物

    1.事务的四个属性 原子性Atomicity,一致性Consistency,隔离性Isolation,持久性Durability ,即ACID特性. 原子性:事务必须是一个完整工作的单元,要么全部执行 ...

  4. SQL Server中事务、锁定和阻塞

    事务是什么 在SQL Server中事务是构成一个工作逻辑单元的一系列任务,也就说多个任务放在一起执行,这些任务要么全部执行成功,要么全部执行失败. 通过事务我们可以保证数据的完整性,例如:用户A给用 ...

  5. 【转】T-SQL查询进阶—理解SQL Server中的锁

      简介 在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查 ...

  6. SQL Server中的锁的简单学习

    简介 在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查询的 ...

  7. T-SQL查询进阶—理解SQL Server中的锁

    在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查询的.这些 ...

  8. T-SQL查询进阶--SQL Server中的事务与锁

    为什么需要锁 在任何多用户的数据库中,必须有一套用于数据修改的一致的规则,当两个不同的进程试图同时修改同一份数据时,数据库管理系统(DBMS)负责解决它们之间潜在的冲突.任何关系数据库必须支持事务的A ...

  9. 浅谈SQL Server中的事务日志(一)----事务日志的物理和逻辑构架

    简介 SQL Server中的事务日志无疑是SQL Server中最重要的部分之一.因为SQL SERVER利用事务日志来确保持久性(Durability)和事务回滚(Rollback).从而还部分确 ...

随机推荐

  1. 攻防世界-MISC:pdf

    这是攻防世界新手练习区的第二题,题目如下: 点击附件1下载,打开后发现是一个pdf文件,里面只有一张图片 用WPS打开,没发现有什么不对的地方,参考一下WP,说是要转为word格式.随便找一个在线转换 ...

  2. 标准输入输出() & 打印流 &配置文件

    public static void main(String[] args) { //System 类 的 public final static InputStream in = null; // ...

  3. Linux-I/O模型详解

    I/O介绍 I/O通常有内存IO.网络I/O.磁盘I/O等,但我们通常说的是网络I/O以及磁盘I/O.网络I/O:本质是socket读取 每次I/O请求,都会有两个阶段组成: 第一步:等待数据,即数据 ...

  4. NS2的LEACH仿真出来的nam文件拓扑的节点为什么x=0,且y=0

    查看.tr文件和.nam发文件下所有的节点的x,y值都是(0,0),nam图像更没有运行出来 于是我将if { $opt(sc) == "" } {puts "*** N ...

  5. mySql in 语句查询优化

    有这么一条sql UPDATE product set BuyerCount =BuyerCount+1 where ProductId in( SELECT ProductId from order ...

  6. 国内访问 git 慢的方法

    在国内访问 git 的时候,总会存在访问慢或者git clone 的时候报下面的错误 这个时候,我们可以使用代理的方式去进行访问 需要注意的是:你必须存在一个国外的,能够让你快速访问到 GitHub ...

  7. 双webview模式,子窗口打不开或者无法切换

    iOS 真机调试时,发现window.open 无效.可以结合plusReady里面不执行一起参考,博主在当时遇到这个问题只查询了资料,而后并没有来得及自己亲自验证以下方法的可行性.来日再遇上mui的 ...

  8. Docker运行资源控制

    概述 ​ 一个 docker host 上会运行若干容器,每个容器都需要 CPU.内存和 IO 资源.对于 KVM,VMware 等虚拟化技术,用户可以控制分配多少 CPU.内存资源给每个虚拟机.对于 ...

  9. CabloyJS微信模块、企业微信模块已出齐

    前言 当Cabloy-企业微信模块完成时,加上之前已完成的Cabloy-微信模块,关于在CabloyJS中与微信/企业微信对接的任务已经完成了.这些模块的目标就是,只需填入各类服务的参数,就可以直接进 ...

  10. 验证cuda和cudnn是否安装成功(转载)

    本人cuda安装目录: 当然cuda安装目录也可默认:此处为方便安装不同cuda版本,所以单独建了文件夹. 转载自:https://zhuanlan.zhihu.com/p/139668028 安装完 ...